2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights
7 * ================================================================================
8 * Modifications Copyright (C) 2019 IBM.
9 * ================================================================================
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 * ============LICENSE_END=========================================================
25 * @author Rich Tabedzki
28 package org.onap.ccsdk.sli.adaptors.aai;
30 import java.io.IOException;
31 import java.io.UnsupportedEncodingException;
32 import java.lang.annotation.Annotation;
33 import java.lang.reflect.Field;
34 import java.lang.reflect.InvocationTargetException;
35 import java.lang.reflect.Method;
36 import java.net.MalformedURLException;
37 import java.net.URISyntaxException;
39 import java.net.URLDecoder;
40 import java.net.URLEncoder;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.HashMap;
44 import java.util.LinkedList;
45 import java.util.List;
48 import java.util.SortedSet;
49 import java.util.TreeSet;
50 import java.util.regex.Matcher;
51 import java.util.regex.Pattern;
53 import javax.xml.bind.annotation.XmlType;
55 import org.apache.commons.lang.StringUtils;
56 import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
57 import org.onap.ccsdk.sli.adaptors.aai.query.FormattedQueryResultList;
58 import org.onap.ccsdk.sli.adaptors.aai.query.Result;
59 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
60 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
61 import org.onap.aai.inventory.v16.GenericVnf;
62 import org.onap.aai.inventory.v16.Image;
63 import org.onap.aai.inventory.v16.InventoryResponseItem;
64 import org.onap.aai.inventory.v16.InventoryResponseItems;
65 import org.onap.aai.inventory.v16.L3Network;
66 import org.onap.aai.inventory.v16.LogicalLink;
67 import org.onap.aai.inventory.v16.Metadata;
68 import org.onap.aai.inventory.v16.Metadatum;
69 import org.onap.aai.inventory.v16.Pnf;
70 import org.onap.aai.inventory.v16.RelatedToProperty;
71 import org.onap.aai.inventory.v16.Relationship;
72 import org.onap.aai.inventory.v16.RelationshipData;
73 import org.onap.aai.inventory.v16.RelationshipList;
74 import org.onap.aai.inventory.v16.ResultData;
75 import org.onap.aai.inventory.v16.SearchResults;
76 import org.onap.aai.inventory.v16.ServiceInstance;
77 import org.onap.aai.inventory.v16.Vlan;
78 import org.onap.aai.inventory.v16.Vlans;
79 import org.onap.aai.inventory.v16.Vserver;
80 import org.slf4j.Logger;
81 import org.slf4j.LoggerFactory;
83 import com.fasterxml.jackson.core.JsonParseException;
84 import com.fasterxml.jackson.databind.JsonMappingException;
85 import com.fasterxml.jackson.databind.ObjectMapper;
88 public abstract class AAIDeclarations implements AAIClient {
90 public static final String TRUSTSTORE_PATH = "org.onap.ccsdk.sli.adaptors.aai.ssl.trust";
91 public static final String TRUSTSTORE_PSSWD = "org.onap.ccsdk.sli.adaptors.aai.ssl.trust.psswd";
92 public static final String KEYSTORE_PATH = "org.onap.ccsdk.sli.adaptors.aai.ssl.key";
93 public static final String KEYSTORE_PSSWD = "org.onap.ccsdk.sli.adaptors.aai.ssl.key.psswd";
95 public static final String APPLICATION_ID = "org.onap.ccsdk.sli.adaptors.aai.application";
97 public static final String CLIENT_NAME = "org.onap.ccsdk.sli.adaptors.aai.client.name";
98 public static final String CLIENT_PWWD = "org.onap.ccsdk.sli.adaptors.aai.client.psswd";
101 public static final String CONNECTION_TIMEOUT = "connection.timeout";
102 public static final String READ_TIMEOUT = "read.timeout";
104 public static final String TARGET_URI = "org.onap.ccsdk.sli.adaptors.aai.uri";
106 public static final String AAI_VERSION = "org.onap.ccsdk.sli.adaptors.aai.version";
108 // Availability zones query
109 public static final String QUERY_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.query";
112 public static final String UPDATE_PATH = "org.onap.ccsdk.sli.adaptors.aai.update";
115 public static final String SVC_INSTANCE_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.svcinst";
116 public static final String SVC_INST_QRY_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.svcinst.query";
119 public static final String NETWORK_VSERVER_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.vserver";
121 public static final String VNF_IMAGE_QUERY_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.vnf.image.query";
123 public static final String PARAM_SERVICE_TYPE = "org.onap.ccsdk.sli.adaptors.aai.param.service.type";
124 public static final String CERTIFICATE_HOST_ERROR = "org.onap.ccsdk.sli.adaptors.aai.host.certificate.ignore";
127 public static final String UBB_NOTIFY_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.notify";
128 public static final String SELFLINK_AVPN = "org.onap.ccsdk.sli.adaptors.aai.notify.selflink.avpn";
129 public static final String SELFLINK_FQDN = "org.onap.ccsdk.sli.adaptors.aai.notify.selflink.fqdn";
132 public static final String SERVICE_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.service";
135 public static final String SITE_PAIR_SET_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.site.pair.set";
138 public static final String QUERY_NODES_PATH = "org.onap.ccsdk.sli.adaptors.aai.query.nodes";
140 private static final String VERSION_PATTERN = "/v$/";
142 private static final String AAI_SERVICE_EXCEPTION = "AAI Service Exception";
144 protected abstract Logger getLogger();
145 public abstract AAIExecutorInterface getExecutor();
147 private static final String RELATIONSHIP_DATA= "Retrofitting relationship data: ";
151 public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx)
152 throws SvcLogicException {
154 getLogger().debug("AAIService.query \tresource = "+resource);
157 String vnfName = null;
158 HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
159 getLogger().debug("key = "+ nameValues.toString());
161 if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
162 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
163 return QueryStatus.FAILURE;
166 if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
167 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported", resource));
168 return QueryStatus.FAILURE;
171 // process data using new model
172 boolean useNewModelProcessing = true;
173 // process server query by name the old way
174 if("vserver".equals(resource) || "vserver2".equals(resource)){
175 if(nameValues.containsKey("vserver_name") || nameValues.containsKey("vserver-name") || nameValues.containsKey("vserver.vserver_name") || nameValues.containsKey("vserver.vserver-name"))
176 useNewModelProcessing = false;
178 if("generic-vnf".equals(resource)){
179 if(nameValues.containsKey("vnf_name") || nameValues.containsKey("vnf-name") || nameValues.containsKey("generic_vnf.vnf_name") || nameValues.containsKey("generic-vnf.vnf-name"))
180 useNewModelProcessing = false;
183 // process data using new model
184 if(useNewModelProcessing && AAIRequest.createRequest(resource, nameValues) != null) {
187 return newModelQuery(resource, localOnly, select, key, prefix, orderBy, ctx);
188 } catch (Exception exc) {
189 getLogger().warn("Failed query - returning FAILURE", exc);
190 return QueryStatus.FAILURE;
194 ObjectMapper mapper = AAIService.getObjectMapper();
195 Map<String,Object> attributes = new HashMap<>();
197 String modifier = null;
199 if(resource.contains(":")) {
200 String[] tokens = resource.split(":");
201 resource = tokens[0];
202 if(tokens.length > 1) {
203 modifier = tokens[1];
207 resource = resource.toLowerCase().replace("-", "_");
213 vnfId = nameValues.get("vnf_id");
214 if(nameValues.containsKey("vnf_id"))
215 vnfId = nameValues.get("vnf_id");
216 else if(nameValues.containsKey("generic_vnf.vnf_name"))
217 vnfId = nameValues.get("generic_vnf.vserver_name");
219 if(nameValues.containsKey("vnf_name"))
220 vnfName = nameValues.get("vnf_name");
221 else if(nameValues.containsKey("generic_vnf.vnf_name"))
222 vnfName = nameValues.get("generic_vnf.vnf_name");
224 if(vnfId != null && !vnfId.isEmpty()) {
225 // at this point of the project this part should not be executed
226 vnfId = vnfId.trim().replace("'", "").replace("$", "").replace("'", "");
227 GenericVnf vnf = this.requestGenericVnfData(vnfId);
229 return QueryStatus.NOT_FOUND;
232 attributes = mapper.convertValue(vnf, attributes.getClass());
233 } else if(vnfName != null && !vnfName.isEmpty()) {
235 vnfName = vnfName.trim().replace("'", "").replace("$", "").replace("'", "");
236 GenericVnf vnf = this.requestGenericVnfeNodeQuery(vnfName);
238 return QueryStatus.NOT_FOUND;
240 vnfId=vnf.getVnfId();
241 nameValues.put("vnf_id", vnfId);
242 attributes = mapper.convertValue(vnf, attributes.getClass());
243 } catch (AAIServiceException exc) {
244 int errorCode = exc.getReturnCode();
251 getLogger().warn("Caught exception trying to refresh generic VNF", exc);
253 ctx.setAttribute(prefix + ".error.message", exc.getMessage());
254 if(errorCode >= 300) {
255 ctx.setAttribute(prefix + ".error.http.response-code",
256 Integer.toString(exc.getReturnCode()));
258 return QueryStatus.FAILURE;
261 getLogger().warn("No arguments are available to process generic VNF");
262 return QueryStatus.FAILURE;
267 String vserverName = null;
268 if(nameValues.containsKey("vserver_name"))
269 vserverName = nameValues.get("vserver_name");
270 else if(nameValues.containsKey("vserver.vserver_name"))
271 vserverName = nameValues.get("vserver.vserver_name");
273 String vserverId = null;
274 if(nameValues.containsKey("vserver_id"))
275 vserverId = nameValues.get("vserver_id");
276 if(nameValues.containsKey("vserver.vserver_id"))
277 vserverId = nameValues.get("vserver.vserver_id");
278 String tenantId = nameValues.get("teannt_id");
280 if(vserverName != null) vserverName = vserverName.trim().replace("'", "").replace("$", "").replace("'", "");
281 if(vserverId != null) vserverId = vserverId.trim().replace("'", "").replace("$", "").replace("'", "");
282 if(tenantId != null) tenantId = tenantId.trim().replace("'", "").replace("$", "").replace("'", "");
284 if (vserverName != null) {
285 URL vserverUrl = null;
287 vserverUrl = this.requestVserverURLNodeQuery(vserverName);
288 } catch (AAIServiceException aaiexc) {
289 getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
290 ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
291 if (aaiexc.getReturnCode() >= 300) {
292 ctx.setAttribute(prefix + ".error.http" + "" + ".response-code", Integer.toString(aaiexc.getReturnCode()));
295 if (aaiexc.getReturnCode() == 404)
296 return QueryStatus.NOT_FOUND;
298 return QueryStatus.FAILURE;
300 if (vserverUrl == null) {
301 return QueryStatus.NOT_FOUND;
304 tenantId = getTenantIdFromVserverUrl(vserverUrl);
305 String cloudOwner = getCloudOwnerFromVserverUrl(vserverUrl);
306 String cloudRegionId = getCloudRegionFromVserverUrl(vserverUrl);
308 Vserver vserver = null;
310 vserver = this.requestVServerDataByURL(vserverUrl);
311 } catch (AAIServiceException aaiexc) {
312 getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
313 ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
314 if (aaiexc.getReturnCode() >= 300) {
315 ctx.setAttribute(prefix + ".error.http" + ".response-code", Integer.toString(aaiexc.getReturnCode()));
318 if (aaiexc.getReturnCode() == 404)
319 return QueryStatus.NOT_FOUND;
321 return QueryStatus.FAILURE;
323 if (vserver == null) {
324 return QueryStatus.NOT_FOUND;
326 attributes = mapper.convertValue(vserver, attributes.getClass());
327 if (!attributes.containsKey("tenant-id") && tenantId != null) {
328 attributes.put("tenant-id", tenantId);
330 if (!attributes.containsKey("cloud-owner") && cloudOwner != null) {
331 attributes.put("cloud-owner", cloudOwner);
333 if (!attributes.containsKey("cloud-region-id") && cloudRegionId != null) {
334 attributes.put("cloud-region-id", cloudRegionId);
336 } else if (vserverId != null && tenantId != null) {
337 Vserver vserver = this.requestVServerData(tenantId, vserverId, "att-aic", "AAIAIC25");
338 if(vserver == null) {
339 return QueryStatus.NOT_FOUND;
341 attributes = mapper.convertValue(vserver, attributes.getClass());
342 if(!attributes.containsKey("tenant-id") && tenantId != null){
343 attributes.put("tenant-id", tenantId);
346 return QueryStatus.FAILURE;
351 return QueryStatus.FAILURE;
354 QueryStatus retval = QueryStatus.SUCCESS;
356 if (attributes == null || attributes.isEmpty()) {
357 retval = QueryStatus.NOT_FOUND;
358 getLogger().debug("No data found");
361 if (prefix != null) {
362 ArrayList<String> keys = new ArrayList<>(attributes.keySet());
364 int numCols = keys.size();
366 for (int i = 0; i < numCols; i++) {
368 String colName = keys.get(i);
369 Object object = attributes.get(colName);
371 if(object != null && object instanceof String) {
372 colValue = (String)object;
374 if (prefix != null) {
375 getLogger().debug("Setting "+prefix + "." + colName.replaceAll("_", "-")+" = "+ colValue);
376 ctx.setAttribute(prefix + "." + colName.replaceAll("_", "-"), colValue);
378 getLogger().debug("Setting " + colValue.replaceAll("_", "-")+" = "+colValue);
379 ctx.setAttribute(colValue.replaceAll("_", "-"), colValue);
381 } else if(object != null && object instanceof Map) {
382 if(colName.equals(modifier) || "relationship-list".equals(colName)){
383 String localNodifier = modifier;
384 if(localNodifier == null)
385 localNodifier = "relationship-list";
386 Map<String, Object> properties = (Map<String, Object>)object;
387 writeMap(properties, prefix+"."+localNodifier, ctx);
394 getLogger().debug("Query - returning " + retval);
397 } catch (Exception exc) {
398 getLogger().warn("Failed query - returning FAILURE", exc);
399 return QueryStatus.FAILURE;
404 public void writeMap(Map<String, Object> properties, String prefix, SvcLogicContext ctx) {
405 Set<String> mapKeys = properties.keySet();
407 for(String mapKey : mapKeys) {
408 Object entity = properties.get(mapKey);
409 if(entity instanceof ArrayList) {
410 writeList((ArrayList<?>)entity, prefix + "." + mapKey, ctx);
412 if(entity instanceof String || entity instanceof Long || entity instanceof Integer || entity instanceof Boolean) {
413 ctx.setAttribute(prefix + "." + mapKey, entity.toString());
414 getLogger().debug(prefix + "." + mapKey + " : " + entity.toString());
415 } else if(entity instanceof Map) {
416 String localPrefix = prefix;
418 localPrefix = String.format("%s.%s", prefix, mapKey);
420 writeMap( (Map<String, Object>)entity, localPrefix, ctx);
425 private void writeList(ArrayList<?> list, String prefix, SvcLogicContext ctx) {
426 for(int i = 0; i < list.size(); i++ ) {
427 Object entity = list.get(i);
428 if(entity instanceof Map) {
429 writeMap( (Map<String, Object>)entity, prefix + "[" + i + "]", ctx);
431 if(entity instanceof String || entity instanceof Long || entity instanceof Integer || entity instanceof Boolean) {
432 ctx.setAttribute(prefix, entity.toString());
433 getLogger().debug(prefix + " : " + entity.toString());
437 if(!list.isEmpty()) {
438 ctx.setAttribute(prefix + "_length", Integer.toString(list.size()));
439 getLogger().debug(prefix + "_length" + " : " + Integer.toString(list.size()));
444 public QueryStatus save(String resource, boolean force, boolean localOnly, String key, Map<String, String> params, String prefix, SvcLogicContext ctx)
445 throws SvcLogicException {
447 getLogger().debug("AAIService.save\tresource="+resource);
448 HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
450 if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
451 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
452 return QueryStatus.FAILURE;
455 if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
456 getLogger().warn("AAIService.save has unspecified resource");
457 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported", resource));
458 return QueryStatus.FAILURE;
461 getLogger().debug("key = "+ Arrays.toString(nameValues.entrySet().toArray()));
464 if(params.containsKey("prefix")) {
465 Map<String, String> tmpParams = ctxGetBeginsWith(ctx, params.get("prefix"));
466 if(!tmpParams.isEmpty()) {
467 params.putAll(tmpParams);
468 // params.remove("prefix");
472 getLogger().debug("parms = "+ Arrays.toString(params.entrySet().toArray()));
474 boolean useNewModelProcessing = true;
475 // process server query by name the old way
476 if("vserver".equals(resource) || "vserver2".equals(resource)){
477 if(nameValues.containsKey("vserver-name")) {
478 useNewModelProcessing = false;
481 if(!params.containsKey("vserver-selflink")) {
483 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
486 request.processRequestPathValues(nameValues);
487 path = request.getRequestUrl("GET", null);
488 params.put("vserver-selflink", path.toString());
489 } catch (UnsupportedEncodingException | MalformedURLException | URISyntaxException e) {
490 getLogger().warn("URL error Exception", e);
491 params.put("vserver-selflink", "/vserver");
496 // process data using new model
497 if(useNewModelProcessing && AAIRequest.createRequest(resource, nameValues) != null) {
500 if(!resource.contains(":")){
501 return newModelSave(resource, force, key, params, prefix, ctx);
503 String[] tokens = resource.split(":");
504 String localResource = tokens[0];
505 String dependency = tokens[1];
507 AAIDatum instance = newModelObjectRequest( localResource, nameValues, prefix, ctx);
508 if(instance == null) {
509 return QueryStatus.NOT_FOUND;
513 case "relationship-list":
514 newModelProcessRelationshipList(instance, params, prefix, ctx);
517 newModelProcessMetadata(instance, params, prefix, ctx);
520 // create a method to update relationship-list
521 AAIRequest request = AAIRequest.createRequest(localResource, nameValues);
522 request.setRequestObject(instance);
523 request.processRequestPathValues(nameValues);
525 getExecutor().post(request);
526 getLogger().debug("Save relationship list - returning SUCCESS");
527 return QueryStatus.SUCCESS;
529 } catch (Exception exc) {
530 ctx.setAttribute(prefix + ".error.message", exc.getMessage());
531 if(exc instanceof AAIServiceException) {
532 AAIServiceException aaiexc = (AAIServiceException)exc;
533 if(aaiexc.getReturnCode() >= 300) {
534 ctx.setAttribute(prefix + ".error.http" + ".response-code", Integer.toString(aaiexc.getReturnCode()));
537 if(aaiexc.getReturnCode() == 404) {
538 return QueryStatus.NOT_FOUND;
541 getLogger().warn("Failed save() - returning FAILURE", exc);
542 return QueryStatus.FAILURE;
545 getLogger().debug("Save() request for {} is not supported- returning FAILURE", resource);
546 return QueryStatus.FAILURE;
551 public QueryStatus update(String resource, String key, Map<String, String> params, String prefix, SvcLogicContext ctx) throws SvcLogicException {
553 resource = resource.toLowerCase();
554 HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
555 getLogger().debug("key = "+ Arrays.toString(nameValues.entrySet().toArray()));
556 if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
557 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
558 return QueryStatus.FAILURE;
561 if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
562 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported", resource));
563 return QueryStatus.FAILURE;
566 // check if request is for groups
567 if(!AAIServiceUtils.containsResource(resource, nameValues)) {
568 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not permitted in 'update' operation", resource));
569 return QueryStatus.FAILURE;
572 getLogger().debug("parms = "+ Arrays.toString(params.entrySet().toArray()));
574 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
575 request = new UpdateRequest(request, params);
577 String[] arguments = request.getArgsList();
578 for(String name : arguments) {
579 String modifiedKey = name.replaceAll("-", "_");
580 if(nameValues.containsKey(modifiedKey)) {
581 String argValue = nameValues.get(modifiedKey);
582 if(argValue != null) argValue = argValue.trim().replace("'", "").replace("$", "").replace("'", "");
583 request.addRequestProperty(name, argValue);
588 QueryStatus retval = QueryStatus.SUCCESS;
590 retval = newModelQuery(resource, false, null, key, "tmpDelete", null, ctx);
592 if(retval == null || retval != QueryStatus.SUCCESS) {
596 String resourceVersion = ctx.getAttribute("tmpDelete.resource-version");
597 if(resourceVersion == null) {
598 return QueryStatus.NOT_FOUND;
600 params.put("resource-version", resourceVersion);
602 request.processRequestPathValues(nameValues);
603 getExecutor().patch(request, resourceVersion);
604 } catch(AAIServiceException aaiexc) {
605 getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
606 if(aaiexc.getReturnCode() == 404)
607 return QueryStatus.NOT_FOUND;
609 return QueryStatus.FAILURE;
610 } catch (Exception exc) {
611 getLogger().warn("Failed update - returning FAILURE", exc);
612 return QueryStatus.FAILURE;
615 getLogger().debug("Update - returning SUCCESS");
616 return QueryStatus.SUCCESS;
620 public QueryStatus delete(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
621 getLogger().debug("AAIService.delete\tresource="+resource);
622 HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
623 getLogger().debug("key = "+ Arrays.toString(nameValues.entrySet().toArray()));
625 if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
626 ctx.setAttribute(String.format("%s.error.message", "aaiData"), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
627 return QueryStatus.FAILURE;
630 if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
631 ctx.setAttribute(String.format("%s.error.message", "tmpDelete"), String.format("Resource %s is not supported", resource));
632 return QueryStatus.FAILURE;
635 // check if request is for groups
636 if(!AAIServiceUtils.containsResource(resource, nameValues)) {
637 ctx.setAttribute(String.format("%s.error.message", "tmpDelete"), String.format("Resource %s is not permitted in 'delete' operation", resource));
638 return QueryStatus.FAILURE;
641 if(AAIRequest.createRequest(resource, nameValues) != null) {
642 if(resource.contains(":")) {
643 switch (resource.split(":")[1]){
644 case "relationship-list":
645 return processDeleteRelationshipList(resource, key, ctx, nameValues);
647 return processDeleteMetadata(resource, key, ctx, nameValues);
653 QueryStatus retval = QueryStatus.SUCCESS;
655 retval = newModelQuery(resource, false, null, key, "tmpDelete", null, ctx);
657 if(retval == null || retval != QueryStatus.SUCCESS) {
661 String resourceVersion = ctx.getAttribute("tmpDelete.resource-version");
662 if(resourceVersion == null) {
663 return QueryStatus.NOT_FOUND;
667 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
668 if(request == null) {
669 return QueryStatus.FAILURE;
672 request.processRequestPathValues(nameValues);
674 if(getExecutor().delete(request, resourceVersion)) {
675 return QueryStatus.SUCCESS;
677 } catch(AAIServiceException aaiexc) {
678 getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
679 if(aaiexc.getReturnCode() == 404)
680 return QueryStatus.NOT_FOUND;
682 return QueryStatus.FAILURE;
684 } catch (Exception exc) {
685 getLogger().warn("requestGenericVnfData", exc);
686 return QueryStatus.FAILURE;
689 } catch (Exception exc) {
690 getLogger().warn("Failed delete - returning FAILURE", exc);
691 return QueryStatus.FAILURE;
694 String resourceName = resource;
695 String identifier = null;
697 if(resourceName.contains(":")) {
698 String[] tokens = resourceName.split(":");
699 if(tokens != null && tokens.length > 0) {
700 resourceName = tokens[0];
701 identifier = tokens[1];
704 if("relationship-list".equals(identifier) || "relationshipList".equals(identifier)) {
705 // RelationshipRequest relationshipRequest = new RelationshipRequest();
706 if("generic-vnf".equals(resourceName)){
707 String vnfId = nameValues.get("vnf_id");
708 String relatedTo = nameValues.get("related_to");
709 vnfId = vnfId.trim().replace("'", "").replace("$", "").replace("'", "");
710 relatedTo = relatedTo.trim().replace("'", "").replace("$", "").replace("'", "");
714 vnf = this.requestGenericVnfData(vnfId);
716 return QueryStatus.NOT_FOUND;
717 } catch (AAIServiceException exc) {
718 getLogger().warn("Failed delete - returning NOT_FOUND", exc);
719 return QueryStatus.NOT_FOUND;
721 boolean itemRemoved = false;
722 RelationshipList relationshipList = vnf.getRelationshipList();
723 List<Relationship> relationships = relationshipList.getRelationship();
724 List<Relationship> iterableList = new LinkedList<>(relationships);
725 for(Relationship relationship : iterableList) {
726 if(relationship.getRelatedTo().equals(relatedTo)) {
727 relationships.remove(relationship);
733 return QueryStatus.NOT_FOUND;
735 this.postGenericVnfData(vnf.getVnfId(), vnf);
736 } catch (AAIServiceException exc) {
737 if(exc.getReturnCode() == 404){
738 return QueryStatus.NOT_FOUND;
740 getLogger().warn("Failed delete - returning FAILURE", exc);
741 return QueryStatus.FAILURE;
744 return QueryStatus.SUCCESS;
748 return QueryStatus.FAILURE;
752 public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException {
753 return query(resource, false, null, key, prefix, null, ctx);
757 public QueryStatus isAvailable(String arg0, String arg1, String arg2, SvcLogicContext arg3)
758 throws SvcLogicException {
759 throw new SvcLogicException("Method AAIService.isAvailable() has not been implemented yet");
763 public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx) throws SvcLogicException {
764 throw new SvcLogicException("Method AAIService.notify() has not been implemented yet");
768 public QueryStatus newModelQuery(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx) {
770 QueryStatus retval = QueryStatus.SUCCESS;
771 String modifier = null;
773 HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
774 if(resource.contains(":")) {
775 modifier = resource.split(":")[1];
779 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
780 if(request == null) {
781 return QueryStatus.FAILURE;
784 Map<String, String> params = new HashMap<>();
786 request.processRequestPathValues(nameValues);
787 if(nameValues.containsKey("prefix")){
788 Map<String, String> tmpParams = ctxGetBeginsWith(ctx, nameValues.get("prefix"));
789 if(!tmpParams.isEmpty()) {
790 params.putAll(tmpParams);
793 String rv = getExecutor().get(request);
795 retval = processResponseData(rv, resource, request, prefix, ctx, nameValues, modifier);
797 } catch(AAIServiceException aaiexc) {
798 getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
799 int errorCode = aaiexc.getReturnCode();
800 ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
801 if(errorCode >= 300) {
802 ctx.setAttribute(prefix + ".error.http.response-code",
803 Integer.toString(aaiexc.getReturnCode()));
806 if(aaiexc.getReturnCode() == 404)
807 return QueryStatus.NOT_FOUND;
809 return QueryStatus.FAILURE;
810 } catch (Exception exc) {
811 getLogger().warn("requestGenericVnfData", exc);
812 ctx.setAttribute(prefix + ".error.message", exc.getMessage());
813 return QueryStatus.FAILURE;
819 public QueryStatus processResponseData(String rv, String resource, AAIRequest request, String prefix, SvcLogicContext ctx, Map<String, String> nameValues, String modifier) throws JsonParseException, JsonMappingException, IOException, AAIServiceException
824 return QueryStatus.NOT_FOUND;
827 response = request.jsonStringToObject(rv);
828 if(response == null) {
829 return QueryStatus.NOT_FOUND;
832 if("generic-query".equals(resource)) {
833 SearchResults rd = SearchResults.class.cast(response);
834 List<ResultData> rdList = rd.getResultData();
835 if(rdList == null || rdList.isEmpty()) {
836 return QueryStatus.NOT_FOUND;
838 ResultData rDatum = rdList.get(0);
839 nameValues.put("selflink", rDatum.getResourceLink());
840 AAIRequest req2 = AAIRequest.createRequest(rDatum.getResourceType(), nameValues);
841 req2.processRequestPathValues(nameValues);
842 rv = getExecutor().get(req2);
844 return QueryStatus.NOT_FOUND;
847 response = req2.jsonStringToObject(rv);
848 if(response == null) {
849 return QueryStatus.NOT_FOUND;
853 if("nodes-query".equals(resource)) {
854 SearchResults rd = SearchResults.class.cast(response);
855 List<ResultData> rdList = rd.getResultData();
856 if(rdList == null || rdList.isEmpty()) {
857 return QueryStatus.NOT_FOUND;
859 ResultData rDatum = rdList.get(0);
863 if("formatted-query".equals(resource) || "custom-query".equals(resource)) {
864 FormattedQueryResultList rd = FormattedQueryResultList.class.cast(response);
865 List<Result> iRIlist = rd.getResults();
866 if(iRIlist == null || iRIlist.isEmpty()) {
867 return QueryStatus.NOT_FOUND;
871 // process relationship list
872 // this is a temporary soluton to address the realationship handling changes added in Release 17.07
874 Class<?> clazz = response.getClass();
875 Method getter = clazz.getMethod("getRelationshipList");
876 Object obj = getter.invoke(response);
877 if(obj != null && obj instanceof RelationshipList) {
878 RelationshipList list = RelationshipList.class.cast(obj);
879 AAIServiceUtils.populateRelationshipDataFromPath(list);
881 } catch(Exception exc) {
882 getLogger().debug(RELATIONSHIP_DATA + exc.getMessage());
886 if(prefix == null || prefix.isEmpty()) {
889 preFix = prefix + ".";
892 Map<String,Object> props = objectToProperties(response);
893 Set<String> keys = props.keySet();
894 for(String theKey: keys) {
895 if(getLogger().isTraceEnabled())
896 getLogger().trace(theKey);
898 Object value = props.get(theKey);
901 Object type = value.getClass();
902 if(value instanceof String) {
903 ctx.setAttribute(preFix + theKey, value.toString());
906 if(value instanceof Boolean) {
907 ctx.setAttribute(preFix + theKey, value.toString());
910 if(value instanceof Integer) {
911 ctx.setAttribute(preFix + theKey, value.toString());
914 if(value instanceof Long) {
915 ctx.setAttribute(preFix + theKey, value.toString());
919 if(value instanceof ArrayList) {
920 ArrayList<?> array = ArrayList.class.cast(value);
921 for(int i = 0; i < array.size(); i++) {
922 writeList(array, String.format("%s.%s", prefix, theKey), ctx);
927 if("relationship-list".equals(theKey)){
928 Map<String, Object> relationshipList = (Map<String, Object>)value;
929 // we are interested in seeing just the selected relationship
930 if(theKey.equals(modifier)) {
931 List<?> relationships = (List<?>)relationshipList.get("relationship");
932 if(relationships != null && !relationships.isEmpty()) {
934 List newRelationships = new LinkedList();
935 newRelationships.addAll(relationships);
937 for(Object obj : newRelationships){
938 if(obj instanceof Map<?, ?>) {
939 Map<?, ?> relProperties = (Map<?, ?>)obj;
940 if(relProperties.containsKey("related-to")) {
941 Object relPropsRelatedTo = relProperties.get("related-to");
943 String relatedTo = nameValues.get("related_to");
944 if(relatedTo != null) {
945 relatedTo = relatedTo.trim().replace("'", "").replace("$", "").replace("'", "");
946 if(!relatedTo.equals(relPropsRelatedTo)) {
947 relationships.remove(relProperties);
958 writeMap(relationshipList, String.format("%s.%s", prefix, theKey), ctx);
962 if(value instanceof Map) {
963 Map<String, Object> subnetsList = (Map<String, Object>)value;
964 writeMap(subnetsList, String.format("%s.%s", prefix, theKey), ctx);
969 return QueryStatus.SUCCESS;
973 public QueryStatus newModelBackupRequest(String resource, Map<String, String> params, String prefix, SvcLogicContext ctx) {
975 QueryStatus retval = QueryStatus.SUCCESS;
976 HashMap<String, String> nameValues = new HashMap<>();
979 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
980 if(request == null) {
981 return QueryStatus.FAILURE;
984 boolean argsFound = false;
985 String[] arguments = request.getArgsList();
986 for(String name : arguments) {
987 String tmpName = name.replaceAll("-", "_");
988 String value = params.get(tmpName);
989 if(value != null && !value.isEmpty()) {
990 value = value.trim().replace("'", "").replace("$", "").replace("'", "");
991 request.addRequestProperty(name, value);
996 getLogger().warn("No arguments were found. Terminating backup request.");
997 return QueryStatus.FAILURE;
1000 String rv = getExecutor().get(request);
1001 ctx.setAttribute(prefix, rv);
1002 } catch(AAIServiceException aaiexc) {
1003 getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
1004 if(aaiexc.getReturnCode() == 404)
1005 return QueryStatus.NOT_FOUND;
1007 return QueryStatus.FAILURE;
1008 } catch (Exception exc) {
1009 getLogger().warn("newModelBackupRequest", exc);
1010 return QueryStatus.FAILURE;
1016 public AAIDatum newModelObjectRequest(String resource, Map<String, String> params, String prefix, SvcLogicContext ctx)
1017 throws AAIServiceException {
1019 AAIDatum response = null;
1022 AAIRequest request = AAIRequest.createRequest(resource, params);
1023 if(request == null) {
1027 request.processRequestPathValues(params);
1028 String rv = getExecutor().get(request);
1029 response = request.jsonStringToObject(rv);
1030 } catch(AAIServiceException aaiexc) {
1032 } catch (Exception exc) {
1033 getLogger().warn("newModelBackupRequest", exc);
1034 throw new AAIServiceException(exc);
1042 public QueryStatus release(String arg0, String arg1, SvcLogicContext arg2) throws SvcLogicException {
1043 throw new SvcLogicException("Method AAIService.release() has not been implemented yet");
1047 public QueryStatus reserve(String arg0, String arg1, String arg2, String arg3, SvcLogicContext arg4)
1048 throws SvcLogicException {
1049 throw new SvcLogicException("Method AAIService.reserve() has not been implemented yet");
1052 private QueryStatus newModelSave(String resource, boolean force, String key, Map<String, String> params, String prefix, SvcLogicContext ctx) {
1053 getLogger().debug("Executing newModelSave for resource : " + resource);
1054 HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
1057 ArrayList<String> subResources = new ArrayList<>();
1058 Set<String> set = params.keySet();
1059 Map<String, Method> setters = new HashMap<>();
1060 Map<String, Method> getters = new HashMap<>();
1063 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
1064 Class<? extends AAIDatum> resourceClass = request.getModelClass();
1065 getLogger().debug(resourceClass.getName());
1066 AAIDatum instance = resourceClass.newInstance();
1069 Annotation[] annotations = resourceClass.getAnnotations();
1070 for(Annotation annotation : annotations) {
1071 Class<? extends Annotation> anotationType = annotation.annotationType();
1072 String annotationName = anotationType.getName();
1074 // 2. find string property setters and getters for the lists
1075 if("javax.xml.bind.annotation.XmlType".equals(annotationName)){
1076 XmlType order = (XmlType)annotation;
1077 String[] values = order.propOrder();
1078 for(String value : values) {
1079 String id = AAIServiceUtils.camelCaseToDashedString(value);
1080 Field field = resourceClass.getDeclaredField(value);
1081 Class<?> type = field.getType();
1082 Method setter = null;
1084 setter = resourceClass.getMethod("set"+StringUtils.capitalize(value), type);
1085 if(type.getName().startsWith("java.lang") || "boolean".equals(type.getName()) || "long".equals(type.getName()) || "int".equals(type.getName())) {
1087 Object arglist[] = new Object[1];
1088 arglist[0] = params.get(id);
1090 if(arglist[0] != null) {
1091 if(!type.getName().equals("java.lang.String")) {
1092 // getLogger().debug(String.format("Processing %s with parameter %s", types[0].getName(), value));
1093 if("java.lang.Long".equals(type.getName()) || "java.lang.Integer".equals(type.getName())) {
1094 String fv = params.get(id);
1095 if(fv == null || fv.isEmpty()) {
1098 arglist[0] = valueOf(type, params.get(id));
1100 } else if("boolean".equals(type.getName())) {
1101 arglist[0] = valueOf(Boolean.class, params.get(id));
1102 } else if("int".equals(type.getName())) {
1103 arglist[0] = valueOf(Integer.class, params.get(id));
1104 } else if("long".equals(type.getName())) {
1105 String fv = params.get(id);
1106 if(fv == null || fv.isEmpty()) {
1109 arglist[0] = valueOf(Long.class, params.get(id));
1112 arglist[0] = valueOf(type, params.get(id));
1115 Object obj = setter.invoke(instance, arglist);
1119 } catch (Exception x) {
1120 Throwable cause = x.getCause();
1121 getLogger().warn("Failed process for " + resourceClass.getName(), x);
1123 } else if("java.util.List".equals(type.getName())) {
1124 List<String> newValues = new ArrayList<>();
1125 String length = id+"_length";
1126 if(!params.isEmpty() && params.containsKey(length)) {
1127 String tmp = params.get(length);
1128 int count = Integer.parseInt(tmp);
1129 for(int i=0; i<count; i++) {
1130 String tmpValue = params.get(String.format("%s[%d]", id, i));
1131 newValues.add(tmpValue);
1133 if(!newValues.isEmpty()) {
1134 Object o = setter.invoke(instance, newValues);
1139 setters.put(id, setter);
1141 } catch(Exception exc) {
1142 getLogger().warn(AAI_SERVICE_EXCEPTION, exc);
1147 getter = resourceClass.getMethod("get"+StringUtils.capitalize(value));
1148 if(!type.getName().equals("java.lang.String")) {
1149 getters.put(id, getter);
1151 } catch(Exception exc) {
1152 getLogger().warn(AAI_SERVICE_EXCEPTION, exc);
1156 subResources.addAll(Arrays.asList(values));
1161 // remove getters that have matching setter
1162 for(String setKey : setters.keySet()) {
1163 if(getters.containsKey(setKey)) {
1164 getters.remove(setKey);
1168 Set<String> relationshipKeys = new TreeSet<>();
1169 Set<String> vlansKeys = new TreeSet<>();
1170 Set<String> metadataKeys = new TreeSet<>();
1172 for(String attribute : set) {
1173 String value = params.get(attribute);
1174 if(attribute.startsWith("relationship-list")) {
1175 relationshipKeys.add(attribute);
1176 } else if(attribute.startsWith("vlans")) {
1177 vlansKeys.add(attribute);
1178 } else if(attribute.startsWith("metadata")) {
1179 metadataKeys.add(attribute);
1182 // 3. find list property getters
1183 for(String attribute : set) {
1184 String value = params.get(attribute);
1185 Method method = getters.get(attribute);
1186 if(method != null) {
1188 Object arglist[] = new Object[0];
1189 // arglist[0] = value;
1190 Class<?>[] types = method.getParameterTypes();
1191 if(types.length == 0){
1192 Object o = method.invoke(instance, arglist);
1193 if(o instanceof ArrayList) {
1194 ArrayList<String> values = (ArrayList<String>)o;
1195 value = value.replace("[", "").replace("]", "");
1196 List<String> items = Arrays.asList(value.split("\\s*,\\s*"));
1197 for(String s : items) {
1198 values.add(s.trim());
1202 } catch (Exception x) {
1203 Throwable cause = x.getCause();
1204 getLogger().warn("Failed process for " + resourceClass.getName(), x);
1208 // 4. Process Relationships
1209 // add relationship list
1210 if( (subResources.contains("relationship-list") || subResources.contains("relationshipList")) && !relationshipKeys.isEmpty()) {
1211 RelationshipList relationshipList = null;
1213 Method getRelationshipListMethod = null;
1215 getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
1216 } catch(Exception exc) {
1217 getLogger().debug(RELATIONSHIP_DATA + exc.getMessage());
1220 if(getRelationshipListMethod != null){
1222 obj = getRelationshipListMethod.invoke(instance);
1223 } catch (InvocationTargetException x) {
1224 Throwable cause = x.getCause();
1227 if(obj != null && obj instanceof RelationshipList){
1228 relationshipList = (RelationshipList)obj;
1230 relationshipList = new RelationshipList();
1231 Method setRelationshipListMethod = resourceClass.getMethod("setRelationshipList", RelationshipList.class);
1232 if(setRelationshipListMethod != null){
1234 Object arglist[] = new Object[1];
1235 arglist[0] = relationshipList;
1237 obj = setRelationshipListMethod.invoke(instance, arglist);
1238 } catch (InvocationTargetException x) {
1239 Throwable cause = x.getCause();
1244 List<Relationship> relationships = relationshipList.getRelationship();
1248 String searchKey = "relationship-list.relationship[" + i + "].related-to";
1249 if(!params.containsKey(searchKey))
1252 String relatedTo = params.get(searchKey);
1253 String relatedLinkKey = "relationship-list.relationship[" + i + "].related-link";
1254 String relatedLink = null;
1255 if(params.containsKey(relatedLinkKey)) {
1256 relatedLink = params.get(relatedLinkKey);
1258 Relationship relationship = new Relationship();
1259 relationships.add(relationship);
1260 relationship.setRelatedTo(relatedTo);
1261 String relationshipLabel = "relationship-list.relationship[" + i + "].relationship-label";
1262 if(params.containsKey(searchKey)) {
1263 relationship.setRelationshipLabel(params.get(relationshipLabel));
1265 getLogger().debug("About to process related link of {}", relatedLink);
1266 if(relatedLink != null) {
1267 if(relatedLink.contains("v$"))
1268 relatedLink = relatedLink.replace(VERSION_PATTERN, "/v16/");
1269 relationship.setRelatedLink(relatedLink);
1271 Map<String, String> relParams = new HashMap<>();
1274 String searchRelationshipKey = "relationship-list.relationship[" + i + "].relationship-data[" + j + "].relationship-key";
1275 String searchRelationshipValue = "relationship-list.relationship[" + i + "].relationship-data[" + j + "].relationship-value";
1276 if(!params.containsKey(searchRelationshipKey))
1279 relParams.put(params.get(searchRelationshipKey), params.get(searchRelationshipValue));
1282 AAIRequest rlRequest = AAIRequest.createRequest(relatedTo, relParams);
1283 for(Map.Entry<String,String> entry : relParams.entrySet()) {
1284 rlRequest.addRequestProperty(entry.getKey(), entry.getValue());
1286 String path = rlRequest.updatePathDataValues(null);
1287 relationship.setRelatedLink(path);
1291 // process related to properties
1292 Map<String, String> relParams = new HashMap<String, String>();
1295 String searchRelatedToKey = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-key";
1296 String searchRelatedToValue = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-value";
1297 if(!params.containsKey(searchRelatedToKey))
1300 RelatedToProperty relDatum = new RelatedToProperty();
1301 relDatum.setPropertyKey(params.get(searchRelatedToKey));
1302 relDatum.setPropertyValue(params.get(searchRelatedToValue));
1303 relationship.getRelatedToProperty().add(relDatum);
1305 relParams.put(params.get(searchRelatedToKey), params.get(searchRelatedToValue));
1314 if(subResources.contains("vlans") && !vlansKeys.isEmpty()) {
1316 Vlans vlanList = null;
1317 Method getVLansMethod = resourceClass.getMethod("getVlans");
1318 if(getVLansMethod != null){
1320 obj = getVLansMethod.invoke(instance);
1321 } catch (InvocationTargetException x) {
1322 Throwable cause = x.getCause();
1325 if(obj != null && obj instanceof Vlans){
1326 vlanList = (Vlans)obj;
1328 vlanList = new Vlans();
1329 Method setVlansMethod = resourceClass.getMethod("setVlans", Vlans.class);
1330 if(setVlansMethod != null){
1332 Object arglist[] = new Object[1];
1333 arglist[0] = vlanList;
1335 obj = setVlansMethod.invoke(instance, arglist);
1336 } catch (InvocationTargetException x) {
1337 Throwable cause = x.getCause();
1344 String searchKey = "vlans.vlan[" + i + "].vlan-interface";
1345 if(!params.containsKey(searchKey))
1348 String vlanInterface = params.get("vlans.vlan[" + i + "].vlan-interface");
1349 String vlanIdInner = params.get("vlans.vlan[" + i + "].vlan-id-inner");
1350 String vlanIdOute = params.get("vlans.vlan[" + i + "].vlan-id-outer");
1351 String speedValue = params.get("vlans.vlan[" + i + "].speed-value");
1352 String speedUnits = params.get("vlans.vlan[" + i + "].speed-units");
1354 Vlan vlan = new Vlan();
1355 vlan.setVlanInterface(vlanInterface);
1357 if(vlanIdInner != null) {
1358 Long iVlanIdInner = Long.parseLong(vlanIdInner);
1359 vlan.setVlanIdInner(iVlanIdInner);
1362 if(vlanIdOute != null) {
1363 Long iVlanIdOuter = Long.parseLong(vlanIdOute);
1364 vlan.setVlanIdOuter(iVlanIdOuter);
1367 if(speedValue != null) {
1368 vlan.setSpeedValue(speedValue);
1369 vlan.setSpeedUnits(speedUnits);
1372 vlanList.getVlan().add(vlan);
1378 if(subResources.contains("metadata") && !metadataKeys.isEmpty()) {
1380 Metadata metadataList = null;
1381 Method getMetadataMethod = resourceClass.getMethod("getMetadata");
1382 if(getMetadataMethod != null){
1384 obj = getMetadataMethod.invoke(instance);
1385 } catch (InvocationTargetException x) {
1386 Throwable cause = x.getCause();
1389 if(obj != null && obj instanceof Metadata){
1390 metadataList = (Metadata)obj;
1392 metadataList = new Metadata();
1393 Method setMetadataMethod = resourceClass.getMethod("setMetadata", Metadata.class);
1394 if(setMetadataMethod != null){
1396 Object arglist[] = new Object[1];
1397 arglist[0] = metadataList;
1399 obj = setMetadataMethod.invoke(instance, arglist);
1400 } catch (InvocationTargetException x) {
1401 Throwable cause = x.getCause();
1409 String metaKey = "metadata.metadatum[" + i + "].meta-key";
1410 if(!params.containsKey(metaKey))
1413 String metaValue = params.get("metadata.metadatum[" + i + "].meta-value");
1415 Metadatum vlan = new Metadatum();
1416 vlan.setMetaname(metaKey);
1417 vlan.setMetaval(metaValue);
1419 metadataList.getMetadatum().add(vlan);
1426 // 6. Prepare AAI request
1427 String[] args = request.getArgsList();
1428 for(String arg : args) {
1429 String modifiedKey = arg.replaceAll("-", "_");
1430 if(nameValues.containsKey(modifiedKey)) {
1431 String argValue = nameValues.get(modifiedKey);
1432 if(argValue != null) argValue = argValue.trim().replace("'", "").replace("$", "").replace("'", "");
1433 request.addRequestProperty(arg, argValue);
1437 request.processRequestPathValues(nameValues);
1438 request.setRequestObject(instance);
1439 Object response = getExecutor().post(request);
1440 if(request.expectsDataFromPUTRequest()){
1441 if(response != null && response instanceof String) {
1442 String rv = response.toString();
1443 QueryStatus retval = processResponseData(rv, resource, request, prefix, ctx, nameValues, null);
1444 getLogger().debug("newModelSave - returning " + retval.toString());
1449 } catch(AAIServiceException exc){
1450 ctx.setAttribute(prefix + ".error.message", exc.getMessage());
1451 int returnCode = exc.getReturnCode();
1452 if(returnCode >= 300) {
1453 ctx.setAttribute(prefix + ".error.http.response-code",
1454 Integer.toString(exc.getReturnCode()));
1457 if(returnCode == 400 || returnCode == 412)
1458 return QueryStatus.FAILURE;
1459 else if(returnCode == 404)
1460 return QueryStatus.NOT_FOUND;
1462 getLogger().warn("Failed newModelSave - returning FAILURE", exc);
1463 return QueryStatus.FAILURE;
1465 } catch(Exception exc){
1466 getLogger().warn("Failed newModelSave - returning FAILURE", exc);
1467 ctx.setAttribute(prefix + ".error.message", exc.getMessage());
1468 return QueryStatus.FAILURE;
1471 getLogger().debug("newModelSave - returning SUCCESS");
1472 return QueryStatus.SUCCESS;
1475 private QueryStatus newModelProcessRelationshipList(Object instance, Map<String, String> params, String prefix, SvcLogicContext ctx) throws Exception {
1477 Class resourceClass = instance.getClass();
1479 Set<String> relationshipKeys = new TreeSet<>();
1481 Set<String> set = params.keySet();
1483 for(String attribute : set) {
1484 String value = params.get(attribute);
1486 if(attribute.startsWith("relationship-list")) {
1487 relationshipKeys.add(attribute);
1491 // 3. Process Relationships
1492 // add relationship list
1493 if(!relationshipKeys.isEmpty()) {
1494 RelationshipList relationshipList;
1496 Method getRelationshipListMethod = null;
1498 getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
1499 } catch(Exception exc) {
1500 getLogger().debug(RELATIONSHIP_DATA + exc.getMessage());
1502 if(getRelationshipListMethod != null){
1504 obj = getRelationshipListMethod.invoke(instance);
1505 } catch (InvocationTargetException x) {
1506 Throwable cause = x.getCause();
1509 if(obj != null && obj instanceof RelationshipList){
1510 relationshipList = (RelationshipList)obj;
1512 relationshipList = new RelationshipList();
1513 Method setRelationshipListMethod = resourceClass.getMethod("setRelationshipList", RelationshipList.class);
1514 if(setRelationshipListMethod != null){
1516 Object arglist[] = new Object[1];
1517 arglist[0] = relationshipList;
1519 obj = setRelationshipListMethod.invoke(instance, arglist);
1520 } catch (InvocationTargetException x) {
1521 Throwable cause = x.getCause();
1526 boolean createdNewRelationships = false;
1527 List<Relationship> relationships = relationshipList.getRelationship();
1528 if(relationships == null) {
1529 relationships = new ArrayList<>();
1530 createdNewRelationships = true;
1535 String searchKey = "relationship-list.relationship[" + i + "].related-to";
1536 if(!params.containsKey(searchKey))
1539 String relatedTo = params.get(searchKey);
1540 String relatedLinkKey = "relationship-list.relationship[" + i + "].related-link";
1541 String relatedLink = null;
1542 if(params.containsKey(relatedLinkKey)) {
1543 relatedLink = params.get(relatedLinkKey);
1546 Relationship relationship = new Relationship();
1547 relationships.add(relationship);
1548 relationship.setRelatedTo(relatedTo);
1550 String relationshipLabel = "relationship-list.relationship[" + i + "].relationship-label";
1551 if(params.containsKey(searchKey)) {
1552 relationship.setRelationshipLabel(params.get(relationshipLabel));
1555 if (relatedLink != null) {
1556 if(relatedLink.contains("v$"))
1557 relatedLink = relatedLink.replace(VERSION_PATTERN, AAIRequest.getSupportedAAIVersion());
1558 relationship.setRelatedLink(relatedLink);
1560 Map<String, String> relParams = new HashMap<>();
1564 String searchRelationshipKey = "relationship-list.relationship[" + i + "].relationship-data["
1565 + j + "].relationship-key";
1566 String searchRelationshipValue = "relationship-list.relationship[" + i + "].relationship-data["
1567 + j + "].relationship-value";
1568 if (!params.containsKey(searchRelationshipKey))
1571 RelationshipData relDatum = new RelationshipData();
1572 relDatum.setRelationshipKey(params.get(searchRelationshipKey));
1573 relDatum.setRelationshipValue(params.get(searchRelationshipValue));
1574 relationship.getRelationshipData().add(relDatum);
1576 relParams.put(params.get(searchRelationshipKey), params.get(searchRelationshipValue));
1579 AAIRequest rlRequest = AAIRequest.createRequest(relatedTo, relParams);
1580 for (Map.Entry<String, String> entry : relParams.entrySet()) {
1581 rlRequest.addRequestProperty(entry.getKey(), entry.getValue());
1583 String path = rlRequest.updatePathDataValues(null);
1584 relationship.setRelatedLink(path);
1588 // process related to properties
1589 Map<String, String> relParams = new HashMap<String, String>();
1592 String searchRelatedToKey = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-key";
1593 String searchRelatedToValue = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-value";
1594 if(!params.containsKey(searchRelatedToKey))
1597 RelatedToProperty relDatum = new RelatedToProperty();
1598 relDatum.setPropertyKey(params.get(searchRelatedToKey));
1599 relDatum.setPropertyValue(params.get(searchRelatedToValue));
1600 relationship.getRelatedToProperty().add(relDatum);
1602 relParams.put(params.get(searchRelatedToKey), params.get(searchRelatedToValue));
1611 return QueryStatus.SUCCESS;
1614 private QueryStatus newModelProcessMetadata(Object instance, Map<String, String> params, String prefix, SvcLogicContext ctx) throws Exception {
1616 if (!(instance instanceof ServiceInstance) && !(instance instanceof Image)) {
1617 throw new IllegalArgumentException("request is not applicable for selected request");
1620 Class resourceClass = instance.getClass();
1621 Set<String> metadataKeys = new TreeSet<>();
1622 Set<String> set = params.keySet();
1623 for(String attribute : set) {
1624 if(attribute.startsWith("metadata")) {
1625 metadataKeys.add(attribute);
1629 // 3. Process Metadata
1631 if(!metadataKeys.isEmpty()) {
1632 Metadata metadata = null;
1634 Method getMetadataMethod = resourceClass.getMethod("getMetadata");
1635 if(getMetadataMethod != null){
1637 obj = getMetadataMethod.invoke(instance);
1638 } catch (InvocationTargetException x) {
1641 if(obj != null && obj instanceof Metadata){
1642 metadata = (Metadata)obj;
1644 metadata = new Metadata();
1645 Method setMetadataMethod = resourceClass.getMethod("setMetadata", Metadata.class);
1646 if(setMetadataMethod != null){
1648 setMetadataMethod.invoke(instance, metadata);
1649 } catch (InvocationTargetException x) {
1654 List<Metadatum> metadatumList = metadata.getMetadatum();
1657 String metaNameKey = "metadata.metadatum[" + i + "].metaname";
1658 String metaValueKey = "metadata.metadatum[" + i + "].metaval";
1659 if(!params.containsKey(metaNameKey) || !params.containsKey(metaValueKey))
1662 Metadatum metadatum = new Metadatum();
1663 metadatum.setMetaname(params.get(metaNameKey));
1664 metadatum.setMetaval(params.get(metaValueKey));
1665 metadatumList.add(metadatum);
1671 return QueryStatus.SUCCESS;
1674 private Relationship findRelationship(List<Relationship> relationships, String relatedTo) {
1675 if(relatedTo == null)
1678 for(Relationship relationship : relationships) {
1679 if(relationship.getRelatedTo().equals(relatedTo)){
1680 return relationship;
1687 public QueryStatus backup(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
1688 String resource = params.get("resource").toLowerCase();
1689 String prefix = params.get("data-key");
1691 HashMap<String, String> nameValues = new HashMap<>();
1692 if(AAIRequest.createRequest(resource, nameValues) != null) {
1695 return newModelBackupRequest(resource, params, prefix, ctx);
1696 } catch (Exception exc) {
1697 getLogger().warn("Failed backup - returning FAILURE", exc);
1698 return QueryStatus.FAILURE;
1702 return QueryStatus.NOT_FOUND;
1706 public QueryStatus restore(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
1708 QueryStatus retval = QueryStatus.SUCCESS;
1709 String resource = params.get("resource").toLowerCase();
1710 String prefix = params.get("data-key");
1712 HashMap<String, String> nameValues = new HashMap<>();
1713 if(AAIRequest.createRequest(resource, nameValues) != null) {
1716 retval = newModelBackupRequest(resource, params, "tmpRestore", ctx);
1717 if(retval == QueryStatus.SUCCESS) {
1718 ctx.setAttribute("tmpRestore", null);
1720 } catch (Exception exc) {
1721 getLogger().warn("Failed restore - returning FAILURE", exc);
1722 return QueryStatus.FAILURE;
1726 return QueryStatus.NOT_FOUND;
1729 protected Map<String, Object> objectToProperties(Object object) {
1730 ObjectMapper mapper = AAIService.getObjectMapper();
1731 return mapper.convertValue(object, Map.class);
1734 static <T> T valueOf(Class<T> klazz, String arg) {
1735 Exception cause = null;
1738 ret = klazz.cast(klazz.getDeclaredMethod("valueOf", String.class).invoke(null, arg));
1739 } catch (NoSuchMethodException exc) {
1740 LoggerFactory.getLogger(AAIService.class).warn("Wrong data type", exc);
1741 ret = klazz.cast(arg);
1742 } catch (IllegalAccessException e) {
1744 } catch (InvocationTargetException e) {
1747 if (cause == null) {
1750 throw new IllegalArgumentException(cause);
1754 private QueryStatus processDeleteRelationshipList(String resource, String key, SvcLogicContext ctx, HashMap<String, String> nameValues) {
1756 AAIRequest request = AAIRequest.createRequest(resource.split(":")[0], nameValues);
1757 if(request == null) {
1758 return QueryStatus.FAILURE;
1761 request.processRequestPathValues(nameValues);
1762 URL url = request.getRequestUrl("GET", null);
1764 Class resourceClass = request.getModelClass();
1765 Object instance = getResource(url.toString(), resourceClass);
1766 if(instance == null)
1767 return QueryStatus.NOT_FOUND;
1769 // get resource version
1770 String resourceVersion = null;
1771 Method getResourceVersionMethod = resourceClass.getMethod("getResourceVersion");
1772 if(getResourceVersionMethod != null){
1774 Object object = getResourceVersionMethod.invoke(instance);
1776 resourceVersion = object.toString();
1777 } catch (InvocationTargetException exc) {
1778 getLogger().warn("Retrieving resource version", exc);
1782 RelationshipList relationshipList = null;
1784 Method getRelationshipListMethod = null;
1786 getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
1787 } catch(Exception exc) {
1788 getLogger().debug(RELATIONSHIP_DATA + exc.getMessage());
1790 if(getRelationshipListMethod != null){
1792 obj = getRelationshipListMethod.invoke(instance);
1793 } catch (InvocationTargetException x) {
1794 Throwable cause = x.getCause();
1797 if(obj != null && obj instanceof RelationshipList){
1798 relationshipList = (RelationshipList)obj;
1800 getLogger().debug("No relationships found to process.");
1801 return QueryStatus.NOT_FOUND;
1804 if(relationshipList.getRelationship() == null || relationshipList.getRelationship().isEmpty()) {
1805 return QueryStatus.NOT_FOUND;
1807 String relatedTo = nameValues.get("related_to");
1808 if(relatedTo == null) {
1809 return QueryStatus.FAILURE;
1812 relatedTo = relatedTo.replaceAll("_", "-");
1814 String relatedLink = nameValues.get("relationship.related_link");
1815 if(relatedLink != null) {
1816 relatedLink = URLDecoder.decode(relatedLink, "UTF-8");
1819 List<Relationship> relationships = relationshipList.getRelationship();
1820 List<Relationship> relationshipsToDelete = new LinkedList<>();
1822 for(Relationship relationship : relationships) {
1823 if(relatedTo.equals(relationship.getRelatedTo())) {
1824 if(relatedLink != null) {
1825 if(relationship.getRelatedLink() != null ) {
1826 String localRelatedLink = relationship.getRelatedLink();
1827 localRelatedLink = URLDecoder.decode(localRelatedLink, "UTF-8");
1828 if(localRelatedLink.endsWith(relatedLink)) {
1829 getLogger().debug(String.format("Found relationship of '%s' to keyword '%s'", relationship.getRelatedTo(), relatedTo));
1830 relationshipsToDelete.add(relationship);
1834 getLogger().debug(String.format("Found relationship of '%s' to keyword '%s'", relationship.getRelatedTo(), relatedTo));
1835 relationshipsToDelete.add(relationship);
1839 if(relationshipsToDelete == null || relationshipsToDelete.isEmpty()) {
1840 getLogger().info(String.format("Relationship has not been found for %s", key));
1841 return QueryStatus.NOT_FOUND;
1844 String path = url.toString();
1845 path = path + "/relationship-list/relationship";
1846 URL deleteUrl = new URL(path);
1848 ObjectMapper mapper = AAIService.getObjectMapper();
1850 boolean cumulativeResponse = true;
1852 for(Relationship targetRelationship : relationshipsToDelete) {
1853 String json_text = mapper.writeValueAsString(targetRelationship);
1854 boolean response = deleteList(deleteUrl, json_text);
1856 cumulativeResponse = response;
1860 if(!cumulativeResponse)
1861 return QueryStatus.FAILURE;
1863 return QueryStatus.SUCCESS;
1865 } catch(Exception exc) {
1866 getLogger().warn("processDelete", exc);
1867 return QueryStatus.FAILURE;
1871 private QueryStatus processDeleteMetadata(String resource, String key, SvcLogicContext ctx, HashMap<String, String> nameValues) {
1873 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
1874 if(request == null) {
1875 return QueryStatus.FAILURE;
1878 request.processRequestPathValues(nameValues);
1879 URL url = request.getRequestUrl("GET", null);
1881 Class<?> resourceClass = request.getModelClass();
1882 Object instance = getResource(url.toString(), resourceClass);
1884 // get resource version
1885 String resourceVersion = null;
1886 Method getResourceVersionMethod = resourceClass.getMethod("getResourceVersion");
1887 if(getResourceVersionMethod != null){
1889 resourceVersion = (String) getResourceVersionMethod.invoke(instance);
1890 } catch (InvocationTargetException x) {
1894 Metadata metadata = null;
1896 Method getMetadataMethod = resourceClass.getMethod("getMetadata");
1897 if(getMetadataMethod != null){
1899 obj = getMetadataMethod.invoke(instance);
1900 } catch (InvocationTargetException x) {
1901 Throwable cause = x.getCause();
1904 if(obj != null && obj instanceof Metadata){
1905 metadata = (Metadata)obj;
1907 getLogger().debug("No metadata found to process.");
1908 return QueryStatus.NOT_FOUND;
1911 if(metadata.getMetadatum() == null || metadata.getMetadatum().isEmpty()) {
1912 return QueryStatus.NOT_FOUND;
1915 List<Metadatum> metadatumList = metadata.getMetadatum();
1916 Metadatum metadatumToDelete = null;
1918 final String metaname = nameValues.get("metaname");
1920 for(Metadatum metadatum : metadatumList) {
1921 getLogger().debug(String.format("Comparing existing metadatum of '%s' to keyword '%s'", metadatum.getMetaname(), metaname));
1922 if(metaname.equals(metadatum.getMetaname())) {
1923 metadatumToDelete = metadatum;
1927 if(metadatumToDelete == null) {
1928 getLogger().info(String.format("Metadatum has not been found for %s", key));
1929 return QueryStatus.NOT_FOUND;
1932 String path = url.toString();
1933 path = path + "/metadata/metadatum/" + encodeQuery( metadatumToDelete.getMetaname() ) +
1934 "?resource-version=" + metadatumToDelete.getResourceVersion();
1935 URL deleteUrl = new URL(path);
1936 boolean response = deleteList(deleteUrl, null);
1939 return QueryStatus.FAILURE;
1941 return QueryStatus.SUCCESS;
1943 } catch(Exception exc) {
1944 getLogger().warn("processDelete", exc);
1945 return QueryStatus.FAILURE;
1949 protected String encodeQuery(String param) throws UnsupportedEncodingException {
1950 return URLEncoder.encode(param, "UTF-8").replace("+", "%20");
1953 static final Map<String, String> ctxGetBeginsWith( SvcLogicContext ctx, String prefix ) {
1954 Map<String, String> tmpPrefixMap = new HashMap<>();
1956 if(prefix == null || prefix.isEmpty()){
1957 return tmpPrefixMap;
1960 for( String key : ctx.getAttributeKeySet() ) {
1961 if( key.startsWith(prefix) ) {
1962 String tmpKey = key.substring(prefix.length() + 1);
1963 tmpPrefixMap.put( tmpKey, ctx.getAttribute(key));
1967 Map<String, String> prefixMap = new HashMap<>();
1968 Pattern p = Pattern.compile(".*\\[\\d\\]");
1970 SortedSet<String> keys = new TreeSet<String>(tmpPrefixMap.keySet () );
1971 for(String key : keys) {
1972 Matcher m = p.matcher(key);
1975 } else if(key.endsWith("_length")) {
1976 String listKey = key.substring(0, key.indexOf("_length"));
1977 int max = Integer.parseInt(tmpPrefixMap.get(key));
1979 ArrayList<String> data = new ArrayList<>();
1980 for(int x = 0; x < max; x++){
1981 String tmpKey = String.format("%s[%d]", listKey, x);
1982 String tmpValue = tmpPrefixMap.get(tmpKey);
1983 if(tmpValue != null && !tmpValue.isEmpty()) {
1987 if(!data.isEmpty()) {
1988 prefixMap.put(listKey, data.toString());
1990 prefixMap.put(key, tmpPrefixMap.get(key));
1993 prefixMap.put(key, tmpPrefixMap.get(key));
2000 public abstract <T> T getResource(String key, Class<T> type) throws AAIServiceException ;
2001 protected abstract boolean deleteList(URL url, String caller) throws AAIServiceException;