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.lang.reflect.Modifier;
37 import java.lang.NoSuchMethodException;
38 import java.net.MalformedURLException;
39 import java.net.URISyntaxException;
41 import java.net.URLDecoder;
42 import java.net.URLEncoder;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.HashMap;
46 import java.util.LinkedList;
47 import java.util.List;
50 import java.util.SortedSet;
51 import java.util.TreeSet;
52 import java.util.regex.Matcher;
53 import java.util.regex.Pattern;
55 import javax.xml.bind.annotation.XmlType;
57 import org.apache.commons.lang.StringUtils;
58 import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
59 import org.onap.ccsdk.sli.adaptors.aai.query.FormattedQueryResultList;
60 import org.onap.ccsdk.sli.adaptors.aai.query.Result;
61 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
62 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
63 import org.onap.aai.inventory.v21.GenericVnf;
64 import org.onap.aai.inventory.v21.Image;
65 import org.onap.aai.inventory.v21.Metadata;
66 import org.onap.aai.inventory.v21.Metadatum;
67 import org.onap.aai.inventory.v21.RelatedToProperty;
68 import org.onap.aai.inventory.v21.Relationship;
69 import org.onap.aai.inventory.v21.RelationshipData;
70 import org.onap.aai.inventory.v21.RelationshipList;
71 import org.onap.aai.inventory.v21.ResultData;
72 import org.onap.aai.inventory.v21.SearchResults;
73 import org.onap.aai.inventory.v21.ServiceInstance;
74 import org.onap.aai.inventory.v21.Vlan;
75 import org.onap.aai.inventory.v21.Vlans;
76 import org.onap.aai.inventory.v21.Vserver;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
80 import com.fasterxml.jackson.core.JsonParseException;
81 import com.fasterxml.jackson.databind.JsonMappingException;
82 import com.fasterxml.jackson.databind.ObjectMapper;
85 public abstract class AAIDeclarations implements AAIClient {
87 public static final String TRUSTSTORE_PATH = "org.onap.ccsdk.sli.adaptors.aai.ssl.trust";
88 public static final String TRUSTSTORE_PSSWD = "org.onap.ccsdk.sli.adaptors.aai.ssl.trust.psswd";
89 public static final String KEYSTORE_PATH = "org.onap.ccsdk.sli.adaptors.aai.ssl.key";
90 public static final String KEYSTORE_PSSWD = "org.onap.ccsdk.sli.adaptors.aai.ssl.key.psswd";
92 public static final String APPLICATION_ID = "org.onap.ccsdk.sli.adaptors.aai.application";
94 public static final String CLIENT_NAME = "org.onap.ccsdk.sli.adaptors.aai.client.name";
95 public static final String CLIENT_PWWD = "org.onap.ccsdk.sli.adaptors.aai.client.psswd";
98 public static final String CONNECTION_TIMEOUT = "connection.timeout";
99 public static final String READ_TIMEOUT = "read.timeout";
101 public static final String TARGET_URI = "org.onap.ccsdk.sli.adaptors.aai.uri";
103 public static final String AAI_VERSION = "org.onap.ccsdk.sli.adaptors.aai.version";
105 // Availability zones query
106 public static final String QUERY_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.query";
109 public static final String UPDATE_PATH = "org.onap.ccsdk.sli.adaptors.aai.update";
112 public static final String SVC_INSTANCE_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.svcinst";
113 public static final String SVC_INST_QRY_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.svcinst.query";
116 public static final String NETWORK_VSERVER_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.vserver";
118 public static final String VNF_IMAGE_QUERY_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.vnf.image.query";
120 public static final String PARAM_SERVICE_TYPE = "org.onap.ccsdk.sli.adaptors.aai.param.service.type";
121 public static final String CERTIFICATE_HOST_ERROR = "org.onap.ccsdk.sli.adaptors.aai.host.certificate.ignore";
124 public static final String UBB_NOTIFY_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.notify";
125 public static final String SELFLINK_AVPN = "org.onap.ccsdk.sli.adaptors.aai.notify.selflink.avpn";
126 public static final String SELFLINK_FQDN = "org.onap.ccsdk.sli.adaptors.aai.notify.selflink.fqdn";
129 public static final String SERVICE_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.service";
132 public static final String SITE_PAIR_SET_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.site.pair.set";
135 public static final String QUERY_NODES_PATH = "org.onap.ccsdk.sli.adaptors.aai.query.nodes";
137 private static final String VERSION_PATTERN = "/v$/";
139 private static final String AAI_SERVICE_EXCEPTION = "AAI Service Exception";
141 protected abstract Logger getLogger();
142 public abstract AAIExecutorInterface getExecutor();
144 private static final String RELATIONSHIP_DATA= "Retrofitting relationship data: ";
148 public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx)
149 throws SvcLogicException {
151 getLogger().debug("AAIService.query \tresource = "+resource);
154 String vnfName = null;
155 HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
156 getLogger().debug("key = "+ nameValues.toString());
158 if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
159 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
160 return QueryStatus.FAILURE;
163 if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
164 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported", resource));
165 return QueryStatus.FAILURE;
168 // process data using new model
169 boolean useNewModelProcessing = true;
170 // process server query by name the old way
171 if("vserver".equals(resource) || "vserver2".equals(resource)){
172 if(nameValues.containsKey("vserver_name") || nameValues.containsKey("vserver-name") || nameValues.containsKey("vserver.vserver_name") || nameValues.containsKey("vserver.vserver-name"))
173 useNewModelProcessing = false;
175 if("generic-vnf".equals(resource)){
176 if(nameValues.containsKey("vnf_name") || nameValues.containsKey("vnf-name") || nameValues.containsKey("generic_vnf.vnf_name") || nameValues.containsKey("generic-vnf.vnf-name"))
177 useNewModelProcessing = false;
180 // process data using new model
181 if(useNewModelProcessing && AAIRequest.createRequest(resource, nameValues) != null) {
184 return newModelQuery(resource, localOnly, select, key, prefix, orderBy, ctx);
185 } catch (Exception exc) {
186 getLogger().warn("Failed query - returning FAILURE", exc);
187 return QueryStatus.FAILURE;
191 ObjectMapper mapper = AAIService.getObjectMapper();
192 Map<String,Object> attributes = new HashMap<>();
194 String modifier = null;
196 if(resource.contains(":")) {
197 String[] tokens = resource.split(":");
198 resource = tokens[0];
199 if(tokens.length > 1) {
200 modifier = tokens[1];
204 resource = resource.toLowerCase().replace("-", "_");
210 vnfId = nameValues.get("vnf_id");
211 if(nameValues.containsKey("vnf_id"))
212 vnfId = nameValues.get("vnf_id");
213 else if(nameValues.containsKey("generic_vnf.vnf_name"))
214 vnfId = nameValues.get("generic_vnf.vserver_name");
216 if(nameValues.containsKey("vnf_name"))
217 vnfName = nameValues.get("vnf_name");
218 else if(nameValues.containsKey("generic_vnf.vnf_name"))
219 vnfName = nameValues.get("generic_vnf.vnf_name");
221 if(vnfId != null && !vnfId.isEmpty()) {
222 // at this point of the project this part should not be executed
223 vnfId = vnfId.trim().replace("'", "").replace("$", "").replace("'", "");
224 GenericVnf vnf = this.requestGenericVnfData(vnfId);
226 return QueryStatus.NOT_FOUND;
229 attributes = mapper.convertValue(vnf, attributes.getClass());
230 } else if(vnfName != null && !vnfName.isEmpty()) {
232 vnfName = vnfName.trim().replace("'", "").replace("$", "").replace("'", "");
233 GenericVnf vnf = this.requestGenericVnfeNodeQuery(vnfName);
235 return QueryStatus.NOT_FOUND;
237 vnfId=vnf.getVnfId();
238 nameValues.put("vnf_id", vnfId);
239 attributes = mapper.convertValue(vnf, attributes.getClass());
240 } catch (AAIServiceException exc) {
241 int errorCode = exc.getReturnCode();
248 getLogger().warn("Caught exception trying to refresh generic VNF", exc);
250 ctx.setAttribute(prefix + ".error.message", exc.getMessage());
251 if(errorCode >= 300) {
252 ctx.setAttribute(prefix + ".error.http.response-code",
253 Integer.toString(exc.getReturnCode()));
255 return QueryStatus.FAILURE;
258 getLogger().warn("No arguments are available to process generic VNF");
259 return QueryStatus.FAILURE;
264 String vserverName = null;
265 if(nameValues.containsKey("vserver_name"))
266 vserverName = nameValues.get("vserver_name");
267 else if(nameValues.containsKey("vserver.vserver_name"))
268 vserverName = nameValues.get("vserver.vserver_name");
270 String vserverId = null;
271 if(nameValues.containsKey("vserver_id"))
272 vserverId = nameValues.get("vserver_id");
273 if(nameValues.containsKey("vserver.vserver_id"))
274 vserverId = nameValues.get("vserver.vserver_id");
275 String tenantId = nameValues.get("teannt_id");
277 if(vserverName != null) vserverName = vserverName.trim().replace("'", "").replace("$", "").replace("'", "");
278 if(vserverId != null) vserverId = vserverId.trim().replace("'", "").replace("$", "").replace("'", "");
279 if(tenantId != null) tenantId = tenantId.trim().replace("'", "").replace("$", "").replace("'", "");
281 if (vserverName != null) {
282 URL vserverUrl = null;
284 vserverUrl = this.requestVserverURLNodeQuery(vserverName);
285 } catch (AAIServiceException aaiexc) {
286 getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
287 ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
288 if (aaiexc.getReturnCode() >= 300) {
289 ctx.setAttribute(prefix + ".error.http" + "" + ".response-code", Integer.toString(aaiexc.getReturnCode()));
292 if (aaiexc.getReturnCode() == 404)
293 return QueryStatus.NOT_FOUND;
295 return QueryStatus.FAILURE;
297 if (vserverUrl == null) {
298 return QueryStatus.NOT_FOUND;
301 tenantId = getTenantIdFromVserverUrl(vserverUrl);
302 String cloudOwner = getCloudOwnerFromVserverUrl(vserverUrl);
303 String cloudRegionId = getCloudRegionFromVserverUrl(vserverUrl);
305 Vserver vserver = null;
307 vserver = this.requestVServerDataByURL(vserverUrl);
308 } catch (AAIServiceException aaiexc) {
309 getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
310 ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
311 if (aaiexc.getReturnCode() >= 300) {
312 ctx.setAttribute(prefix + ".error.http" + ".response-code", Integer.toString(aaiexc.getReturnCode()));
315 if (aaiexc.getReturnCode() == 404)
316 return QueryStatus.NOT_FOUND;
318 return QueryStatus.FAILURE;
320 if (vserver == null) {
321 return QueryStatus.NOT_FOUND;
323 attributes = mapper.convertValue(vserver, attributes.getClass());
324 if (!attributes.containsKey("tenant-id") && tenantId != null) {
325 attributes.put("tenant-id", tenantId);
327 if (!attributes.containsKey("cloud-owner") && cloudOwner != null) {
328 attributes.put("cloud-owner", cloudOwner);
330 if (!attributes.containsKey("cloud-region-id") && cloudRegionId != null) {
331 attributes.put("cloud-region-id", cloudRegionId);
333 } else if (vserverId != null && tenantId != null) {
334 Vserver vserver = this.requestVServerData(tenantId, vserverId, "att-aic", "AAIAIC25");
335 if(vserver == null) {
336 return QueryStatus.NOT_FOUND;
338 attributes = mapper.convertValue(vserver, attributes.getClass());
339 if(!attributes.containsKey("tenant-id") && tenantId != null){
340 attributes.put("tenant-id", tenantId);
343 return QueryStatus.FAILURE;
348 return QueryStatus.FAILURE;
351 QueryStatus retval = QueryStatus.SUCCESS;
353 if (attributes == null || attributes.isEmpty()) {
354 retval = QueryStatus.NOT_FOUND;
355 getLogger().debug("No data found");
358 if (prefix != null) {
359 ArrayList<String> keys = new ArrayList<>(attributes.keySet());
361 int numCols = keys.size();
363 for (int i = 0; i < numCols; i++) {
365 String colName = keys.get(i);
366 Object object = attributes.get(colName);
368 if(object != null && object instanceof String) {
369 colValue = (String)object;
371 if (prefix != null) {
372 getLogger().debug("Setting "+prefix + "." + colName.replaceAll("_", "-")+" = "+ colValue);
373 ctx.setAttribute(prefix + "." + colName.replaceAll("_", "-"), colValue);
375 getLogger().debug("Setting " + colValue.replaceAll("_", "-")+" = "+colValue);
376 ctx.setAttribute(colValue.replaceAll("_", "-"), colValue);
378 } else if(object != null && object instanceof Map) {
379 if(colName.equals(modifier) || "relationship-list".equals(colName)){
380 String localNodifier = modifier;
381 if(localNodifier == null)
382 localNodifier = "relationship-list";
383 Map<String, Object> properties = (Map<String, Object>)object;
384 writeMap(properties, prefix+"."+localNodifier, ctx);
391 getLogger().debug("Query - returning " + retval);
394 } catch (Exception exc) {
395 getLogger().warn("Failed query - returning FAILURE", exc);
396 return QueryStatus.FAILURE;
401 public void writeMap(Map<String, Object> properties, String prefix, SvcLogicContext ctx) {
402 Set<String> mapKeys = properties.keySet();
404 for(String mapKey : mapKeys) {
405 Object entity = properties.get(mapKey);
406 if(entity instanceof ArrayList) {
407 writeList((ArrayList<?>)entity, prefix + "." + mapKey, ctx);
409 if(entity instanceof String || entity instanceof Long || entity instanceof Integer || entity instanceof Boolean) {
410 ctx.setAttribute(prefix + "." + mapKey, entity.toString());
411 getLogger().debug(prefix + "." + mapKey + " : " + entity.toString());
412 } else if(entity instanceof Map) {
413 String localPrefix = prefix;
415 localPrefix = String.format("%s.%s", prefix, mapKey);
417 writeMap( (Map<String, Object>)entity, localPrefix, ctx);
422 private void writeList(ArrayList<?> list, String prefix, SvcLogicContext ctx) {
423 for(int i = 0; i < list.size(); i++ ) {
424 Object entity = list.get(i);
425 if(entity instanceof Map) {
426 writeMap( (Map<String, Object>)entity, prefix + "[" + i + "]", ctx);
428 if(entity instanceof String || entity instanceof Long || entity instanceof Integer || entity instanceof Boolean) {
429 ctx.setAttribute(prefix, entity.toString());
430 getLogger().debug(prefix + " : " + entity.toString());
434 if(!list.isEmpty()) {
435 ctx.setAttribute(prefix + "_length", Integer.toString(list.size()));
436 getLogger().debug(prefix + "_length" + " : " + Integer.toString(list.size()));
441 public QueryStatus save(String resource, boolean force, boolean localOnly, String key, Map<String, String> params, String prefix, SvcLogicContext ctx)
442 throws SvcLogicException {
444 getLogger().debug("AAIService.save\tresource="+resource);
445 HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
447 if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
448 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
449 return QueryStatus.FAILURE;
452 if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
453 getLogger().warn("AAIService.save has unspecified resource");
454 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported", resource));
455 return QueryStatus.FAILURE;
458 getLogger().debug("key = "+ Arrays.toString(nameValues.entrySet().toArray()));
461 if(params.containsKey("prefix")) {
462 Map<String, String> tmpParams = ctxGetBeginsWith(ctx, params.get("prefix"));
463 if(!tmpParams.isEmpty()) {
464 params.putAll(tmpParams);
465 // params.remove("prefix");
469 getLogger().debug("parms = "+ Arrays.toString(params.entrySet().toArray()));
471 boolean useNewModelProcessing = true;
472 // process server query by name the old way
473 if("vserver".equals(resource) || "vserver2".equals(resource)){
474 if(nameValues.containsKey("vserver-name")) {
475 useNewModelProcessing = false;
478 if(!params.containsKey("vserver-selflink")) {
480 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
483 request.processRequestPathValues(nameValues);
484 path = request.getRequestUrl("GET", null);
485 params.put("vserver-selflink", path.toString());
486 } catch (UnsupportedEncodingException | MalformedURLException | URISyntaxException e) {
487 getLogger().warn("URL error Exception", e);
488 params.put("vserver-selflink", "/vserver");
493 // process data using new model
494 if(useNewModelProcessing && AAIRequest.createRequest(resource, nameValues) != null) {
497 if(!resource.contains(":")){
498 return newModelSave(resource, force, key, params, prefix, ctx);
500 String[] tokens = resource.split(":");
501 String localResource = tokens[0];
502 String dependency = tokens[1];
504 AAIDatum instance = newModelObjectRequest( localResource, nameValues, prefix, ctx);
505 if(instance == null) {
506 return QueryStatus.NOT_FOUND;
510 case "relationship-list":
511 newModelProcessRelationshipList(instance, params, prefix, ctx);
514 newModelProcessMetadata(instance, params, prefix, ctx);
517 // create a method to update relationship-list
518 AAIRequest request = AAIRequest.createRequest(localResource, nameValues);
519 request.setRequestObject(instance);
520 request.processRequestPathValues(nameValues);
522 getExecutor().post(request);
523 getLogger().debug("Save relationship list - returning SUCCESS");
524 return QueryStatus.SUCCESS;
526 } catch (Exception exc) {
527 ctx.setAttribute(prefix + ".error.message", exc.getMessage());
528 if(exc instanceof AAIServiceException) {
529 AAIServiceException aaiexc = (AAIServiceException)exc;
530 if(aaiexc.getReturnCode() >= 300) {
531 ctx.setAttribute(prefix + ".error.http" + ".response-code", Integer.toString(aaiexc.getReturnCode()));
534 if(aaiexc.getReturnCode() == 404) {
535 return QueryStatus.NOT_FOUND;
538 getLogger().warn("Failed save() - returning FAILURE", exc);
539 return QueryStatus.FAILURE;
542 getLogger().debug("Save() request for {} is not supported- returning FAILURE", resource);
543 return QueryStatus.FAILURE;
548 public QueryStatus update(String resource, String key, Map<String, String> params, String prefix, SvcLogicContext ctx) throws SvcLogicException {
550 resource = resource.toLowerCase();
551 HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
552 getLogger().debug("key = "+ Arrays.toString(nameValues.entrySet().toArray()));
553 if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
554 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
555 return QueryStatus.FAILURE;
558 if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
559 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported", resource));
560 return QueryStatus.FAILURE;
563 // check if request is for groups
564 if(!AAIServiceUtils.containsResource(resource, nameValues)) {
565 ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not permitted in 'update' operation", resource));
566 return QueryStatus.FAILURE;
569 getLogger().debug("parms = "+ Arrays.toString(params.entrySet().toArray()));
571 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
572 request = new UpdateRequest(request, params);
574 String[] arguments = request.getArgsList();
575 for(String name : arguments) {
576 String modifiedKey = name.replaceAll("-", "_");
577 if(nameValues.containsKey(modifiedKey)) {
578 String argValue = nameValues.get(modifiedKey);
579 if(argValue != null) argValue = argValue.trim().replace("'", "").replace("$", "").replace("'", "");
580 request.addRequestProperty(name, argValue);
585 QueryStatus retval = QueryStatus.SUCCESS;
587 retval = newModelQuery(resource, false, null, key, "tmpDelete", null, ctx);
589 if(retval == null || retval != QueryStatus.SUCCESS) {
593 String resourceVersion = ctx.getAttribute("tmpDelete.resource-version");
594 if(resourceVersion == null) {
595 return QueryStatus.NOT_FOUND;
597 params.put("resource-version", resourceVersion);
599 request.processRequestPathValues(nameValues);
600 getExecutor().patch(request, resourceVersion);
601 } catch(AAIServiceException aaiexc) {
602 getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
603 if(aaiexc.getReturnCode() == 404)
604 return QueryStatus.NOT_FOUND;
606 return QueryStatus.FAILURE;
607 } catch (Exception exc) {
608 getLogger().warn("Failed update - returning FAILURE", exc);
609 return QueryStatus.FAILURE;
612 getLogger().debug("Update - returning SUCCESS");
613 return QueryStatus.SUCCESS;
617 public QueryStatus delete(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
618 getLogger().debug("AAIService.delete\tresource="+resource);
619 HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
620 getLogger().debug("key = "+ Arrays.toString(nameValues.entrySet().toArray()));
622 if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
623 ctx.setAttribute(String.format("%s.error.message", "aaiData"), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
624 return QueryStatus.FAILURE;
627 if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
628 ctx.setAttribute(String.format("%s.error.message", "tmpDelete"), String.format("Resource %s is not supported", resource));
629 return QueryStatus.FAILURE;
632 // check if request is for groups
633 if(!AAIServiceUtils.containsResource(resource, nameValues)) {
634 ctx.setAttribute(String.format("%s.error.message", "tmpDelete"), String.format("Resource %s is not permitted in 'delete' operation", resource));
635 return QueryStatus.FAILURE;
638 if(AAIRequest.createRequest(resource, nameValues) != null) {
639 if(resource.contains(":")) {
640 switch (resource.split(":")[1]){
641 case "relationship-list":
642 return processDeleteRelationshipList(resource, key, ctx, nameValues);
644 return processDeleteMetadata(resource, key, ctx, nameValues);
650 QueryStatus retval = QueryStatus.SUCCESS;
652 retval = newModelQuery(resource, false, null, key, "tmpDelete", null, ctx);
654 if(retval == null || retval != QueryStatus.SUCCESS) {
658 String resourceVersion = ctx.getAttribute("tmpDelete.resource-version");
659 if(resourceVersion == null) {
660 return QueryStatus.NOT_FOUND;
664 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
665 if(request == null) {
666 return QueryStatus.FAILURE;
669 request.processRequestPathValues(nameValues);
671 if(getExecutor().delete(request, resourceVersion)) {
672 return QueryStatus.SUCCESS;
674 } catch(AAIServiceException aaiexc) {
675 getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
676 if(aaiexc.getReturnCode() == 404)
677 return QueryStatus.NOT_FOUND;
679 return QueryStatus.FAILURE;
681 } catch (Exception exc) {
682 getLogger().warn("requestGenericVnfData", exc);
683 return QueryStatus.FAILURE;
686 } catch (Exception exc) {
687 getLogger().warn("Failed delete - returning FAILURE", exc);
688 return QueryStatus.FAILURE;
691 String resourceName = resource;
692 String identifier = null;
694 if(resourceName.contains(":")) {
695 String[] tokens = resourceName.split(":");
696 if(tokens != null && tokens.length > 0) {
697 resourceName = tokens[0];
698 identifier = tokens[1];
701 if("relationship-list".equals(identifier) || "relationshipList".equals(identifier)) {
702 // RelationshipRequest relationshipRequest = new RelationshipRequest();
703 if("generic-vnf".equals(resourceName)){
704 String vnfId = nameValues.get("vnf_id");
705 String relatedTo = nameValues.get("related_to");
706 vnfId = vnfId.trim().replace("'", "").replace("$", "").replace("'", "");
707 relatedTo = relatedTo.trim().replace("'", "").replace("$", "").replace("'", "");
711 vnf = this.requestGenericVnfData(vnfId);
713 return QueryStatus.NOT_FOUND;
714 } catch (AAIServiceException exc) {
715 getLogger().warn("Failed delete - returning NOT_FOUND", exc);
716 return QueryStatus.NOT_FOUND;
718 boolean itemRemoved = false;
719 RelationshipList relationshipList = vnf.getRelationshipList();
720 List<Relationship> relationships = relationshipList.getRelationship();
721 List<Relationship> iterableList = new LinkedList<>(relationships);
722 for(Relationship relationship : iterableList) {
723 if(relationship.getRelatedTo().equals(relatedTo)) {
724 relationships.remove(relationship);
730 return QueryStatus.NOT_FOUND;
732 this.postGenericVnfData(vnf.getVnfId(), vnf);
733 } catch (AAIServiceException exc) {
734 if(exc.getReturnCode() == 404){
735 return QueryStatus.NOT_FOUND;
737 getLogger().warn("Failed delete - returning FAILURE", exc);
738 return QueryStatus.FAILURE;
741 return QueryStatus.SUCCESS;
745 return QueryStatus.FAILURE;
749 public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException {
750 return query(resource, false, null, key, prefix, null, ctx);
754 public QueryStatus isAvailable(String arg0, String arg1, String arg2, SvcLogicContext arg3)
755 throws SvcLogicException {
756 throw new SvcLogicException("Method AAIService.isAvailable() has not been implemented yet");
760 public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx) throws SvcLogicException {
761 throw new SvcLogicException("Method AAIService.notify() has not been implemented yet");
765 public QueryStatus newModelQuery(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx) {
767 QueryStatus retval = QueryStatus.SUCCESS;
768 String modifier = null;
770 HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
771 if(resource.contains(":")) {
772 modifier = resource.split(":")[1];
776 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
777 if(request == null) {
778 return QueryStatus.FAILURE;
781 Map<String, String> params = new HashMap<>();
783 request.processRequestPathValues(nameValues);
784 if(nameValues.containsKey("prefix")){
785 Map<String, String> tmpParams = ctxGetBeginsWith(ctx, nameValues.get("prefix"));
786 if(!tmpParams.isEmpty()) {
787 params.putAll(tmpParams);
790 String rv = getExecutor().get(request);
792 retval = processResponseData(rv, resource, request, prefix, ctx, nameValues, modifier);
794 } catch(AAIServiceException aaiexc) {
795 getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
796 int errorCode = aaiexc.getReturnCode();
797 ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
798 if(errorCode >= 300) {
799 ctx.setAttribute(prefix + ".error.http.response-code",
800 Integer.toString(aaiexc.getReturnCode()));
803 if(aaiexc.getReturnCode() == 404)
804 return QueryStatus.NOT_FOUND;
806 return QueryStatus.FAILURE;
807 } catch (Exception exc) {
808 getLogger().warn("requestGenericVnfData", exc);
809 ctx.setAttribute(prefix + ".error.message", exc.getMessage());
810 return QueryStatus.FAILURE;
816 public QueryStatus processResponseData(String rv, String resource, AAIRequest request, String prefix, SvcLogicContext ctx, Map<String, String> nameValues, String modifier) throws JsonParseException, JsonMappingException, IOException, AAIServiceException
821 return QueryStatus.NOT_FOUND;
824 response = request.jsonStringToObject(rv);
825 if(response == null) {
826 return QueryStatus.NOT_FOUND;
829 if("generic-query".equals(resource)) {
830 SearchResults rd = SearchResults.class.cast(response);
831 List<ResultData> rdList = rd.getResultData();
832 if(rdList == null || rdList.isEmpty()) {
833 return QueryStatus.NOT_FOUND;
835 ResultData rDatum = rdList.get(0);
836 nameValues.put("selflink", rDatum.getResourceLink());
837 AAIRequest req2 = AAIRequest.createRequest(rDatum.getResourceType(), nameValues);
838 req2.processRequestPathValues(nameValues);
839 rv = getExecutor().get(req2);
841 return QueryStatus.NOT_FOUND;
844 response = req2.jsonStringToObject(rv);
845 if(response == null) {
846 return QueryStatus.NOT_FOUND;
850 if("nodes-query".equals(resource)) {
851 SearchResults rd = SearchResults.class.cast(response);
852 List<ResultData> rdList = rd.getResultData();
853 if(rdList == null || rdList.isEmpty()) {
854 return QueryStatus.NOT_FOUND;
856 ResultData rDatum = rdList.get(0);
860 if("formatted-query".equals(resource) || "custom-query".equals(resource)) {
861 FormattedQueryResultList rd = FormattedQueryResultList.class.cast(response);
862 List<Result> iRIlist = rd.getResults();
863 if(iRIlist == null || iRIlist.isEmpty()) {
864 return QueryStatus.NOT_FOUND;
868 // process relationship list
869 // this is a temporary soluton to address the realationship handling changes added in Release 17.07
871 Class<?> clazz = response.getClass();
872 Method getter = clazz.getMethod("getRelationshipList");
873 Object obj = getter.invoke(response);
874 if(obj != null && obj instanceof RelationshipList) {
875 RelationshipList list = RelationshipList.class.cast(obj);
876 AAIServiceUtils.populateRelationshipDataFromPath(list);
878 } catch(Exception exc) {
879 getLogger().debug(RELATIONSHIP_DATA + exc.getMessage());
883 if(prefix == null || prefix.isEmpty()) {
886 preFix = prefix + ".";
889 Map<String,Object> props = objectToProperties(response);
890 Set<String> keys = props.keySet();
891 for(String theKey: keys) {
892 if(getLogger().isTraceEnabled())
893 getLogger().trace(theKey);
895 Object value = props.get(theKey);
898 Object type = value.getClass();
899 if(value instanceof String) {
900 ctx.setAttribute(preFix + theKey, value.toString());
903 if(value instanceof Boolean) {
904 ctx.setAttribute(preFix + theKey, value.toString());
907 if(value instanceof Integer) {
908 ctx.setAttribute(preFix + theKey, value.toString());
911 if(value instanceof Long) {
912 ctx.setAttribute(preFix + theKey, value.toString());
916 if(value instanceof ArrayList) {
917 ArrayList<?> array = ArrayList.class.cast(value);
918 for(int i = 0; i < array.size(); i++) {
919 writeList(array, String.format("%s.%s", prefix, theKey), ctx);
924 if("relationship-list".equals(theKey)){
925 Map<String, Object> relationshipList = (Map<String, Object>)value;
926 // we are interested in seeing just the selected relationship
927 if(theKey.equals(modifier)) {
928 List<?> relationships = (List<?>)relationshipList.get("relationship");
929 if(relationships != null && !relationships.isEmpty()) {
931 List newRelationships = new LinkedList();
932 newRelationships.addAll(relationships);
934 for(Object obj : newRelationships){
935 if(obj instanceof Map<?, ?>) {
936 Map<?, ?> relProperties = (Map<?, ?>)obj;
937 if(relProperties.containsKey("related-to")) {
938 Object relPropsRelatedTo = relProperties.get("related-to");
940 String relatedTo = nameValues.get("related_to");
941 if(relatedTo != null) {
942 relatedTo = relatedTo.trim().replace("'", "").replace("$", "").replace("'", "");
943 if(!relatedTo.equals(relPropsRelatedTo)) {
944 relationships.remove(relProperties);
955 writeMap(relationshipList, String.format("%s.%s", prefix, theKey), ctx);
959 if(value instanceof Map) {
960 Map<String, Object> subnetsList = (Map<String, Object>)value;
961 writeMap(subnetsList, String.format("%s.%s", prefix, theKey), ctx);
966 return QueryStatus.SUCCESS;
970 public QueryStatus newModelBackupRequest(String resource, Map<String, String> params, String prefix, SvcLogicContext ctx) {
972 QueryStatus retval = QueryStatus.SUCCESS;
973 HashMap<String, String> nameValues = new HashMap<>();
976 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
977 if(request == null) {
978 return QueryStatus.FAILURE;
981 boolean argsFound = false;
982 String[] arguments = request.getArgsList();
983 for(String name : arguments) {
984 String tmpName = name.replaceAll("-", "_");
985 String value = params.get(tmpName);
986 if(value != null && !value.isEmpty()) {
987 value = value.trim().replace("'", "").replace("$", "").replace("'", "");
988 request.addRequestProperty(name, value);
993 getLogger().warn("No arguments were found. Terminating backup request.");
994 return QueryStatus.FAILURE;
997 String rv = getExecutor().get(request);
998 ctx.setAttribute(prefix, rv);
999 } catch(AAIServiceException aaiexc) {
1000 getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
1001 if(aaiexc.getReturnCode() == 404)
1002 return QueryStatus.NOT_FOUND;
1004 return QueryStatus.FAILURE;
1005 } catch (Exception exc) {
1006 getLogger().warn("newModelBackupRequest", exc);
1007 return QueryStatus.FAILURE;
1013 public AAIDatum newModelObjectRequest(String resource, Map<String, String> params, String prefix, SvcLogicContext ctx)
1014 throws AAIServiceException {
1016 AAIDatum response = null;
1019 AAIRequest request = AAIRequest.createRequest(resource, params);
1020 if(request == null) {
1024 request.processRequestPathValues(params);
1025 String rv = getExecutor().get(request);
1026 response = request.jsonStringToObject(rv);
1027 } catch(AAIServiceException aaiexc) {
1029 } catch (Exception exc) {
1030 getLogger().warn("newModelBackupRequest", exc);
1031 throw new AAIServiceException(exc);
1039 public QueryStatus release(String arg0, String arg1, SvcLogicContext arg2) throws SvcLogicException {
1040 throw new SvcLogicException("Method AAIService.release() has not been implemented yet");
1044 public QueryStatus reserve(String arg0, String arg1, String arg2, String arg3, SvcLogicContext arg4)
1045 throws SvcLogicException {
1046 throw new SvcLogicException("Method AAIService.reserve() has not been implemented yet");
1049 private QueryStatus newModelSave(String resource, boolean force, String key, Map<String, String> params, String prefix, SvcLogicContext ctx) {
1050 getLogger().debug("Executing newModelSave for resource : " + resource);
1051 HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
1054 ArrayList<String> subResources = new ArrayList<>();
1055 Set<String> set = params.keySet();
1056 Map<String, Method> setters = new HashMap<>();
1057 Map<String, Method> getters = new HashMap<>();
1060 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
1061 Class<? extends AAIDatum> resourceClass = request.getModelClass();
1062 getLogger().debug(resourceClass.getName());
1063 AAIDatum instance = resourceClass.newInstance();
1066 Annotation[] annotations = resourceClass.getAnnotations();
1067 for(Annotation annotation : annotations) {
1068 Class<? extends Annotation> anotationType = annotation.annotationType();
1069 String annotationName = anotationType.getName();
1071 // 2. find string property setters and getters for the lists
1072 if("javax.xml.bind.annotation.XmlType".equals(annotationName)){
1073 XmlType order = (XmlType)annotation;
1074 String[] values = order.propOrder();
1075 for(String value : values) {
1076 String id = AAIServiceUtils.camelCaseToDashedString(value);
1077 Field field = resourceClass.getDeclaredField(value);
1078 Class<?> type = field.getType();
1081 if(type.getName().startsWith("java.lang") || "boolean".equals(type.getName()) || "long".equals(type.getName()) || "int".equals(type.getName())) {
1083 Method setter = resourceClass.getMethod("set"+StringUtils.capitalize(value), type);
1084 Object arglist[] = new Object[1];
1085 arglist[0] = params.get(id);
1087 if(arglist[0] != null) {
1088 if(!type.getName().equals("java.lang.String")) {
1089 // getLogger().debug(String.format("Processing %s with parameter %s", types[0].getName(), value));
1090 if("java.lang.Long".equals(type.getName()) || "java.lang.Integer".equals(type.getName())) {
1091 String fv = params.get(id);
1092 if(fv == null || fv.isEmpty()) {
1095 arglist[0] = valueOf(type, params.get(id));
1097 } else if("boolean".equals(type.getName())) {
1098 arglist[0] = valueOf(Boolean.class, params.get(id));
1099 } else if("int".equals(type.getName())) {
1100 arglist[0] = valueOf(Integer.class, params.get(id));
1101 } else if("long".equals(type.getName())) {
1102 String fv = params.get(id);
1103 if(fv == null || fv.isEmpty()) {
1106 arglist[0] = valueOf(Long.class, params.get(id));
1109 arglist[0] = valueOf(type, params.get(id));
1112 Object obj = setter.invoke(instance, arglist);
1116 } catch (Exception x) {
1117 Throwable cause = x.getCause();
1118 getLogger().warn("Failed process for " + resourceClass.getName(), x);
1120 } else if("java.util.List".equals(type.getName())) {
1121 List<String> newValues = new ArrayList<>();
1122 String length = id+"_length";
1123 if(!params.isEmpty() && params.containsKey(length)) {
1124 String tmp = params.get(length);
1125 int count = Integer.parseInt(tmp);
1126 for(int i=0; i<count; i++) {
1127 String tmpValue = params.get(String.format("%s[%d]", id, i));
1128 newValues.add(tmpValue);
1130 if(!newValues.isEmpty()) {
1131 Method setter = findSetterFor(resourceClass, value);
1132 if(setter != null) {
1133 Object o = setter.invoke(instance, newValues);
1136 Method listGetter = resourceClass.getMethod("get"+StringUtils.capitalize(value));
1137 Object o = listGetter.invoke(instance);
1138 if(o != null && o instanceof java.util.List ) {
1139 List innerList = List.class.cast(o);
1140 innerList.addAll(newValues);
1142 } catch(NoSuchMethodException nsme) {
1143 getLogger().warn(AAI_SERVICE_EXCEPTION, nsme);
1150 Method setter = resourceClass.getMethod("set"+StringUtils.capitalize(value), type);
1151 setters.put(id, setter);
1153 } catch(Exception exc) {
1154 getLogger().warn(AAI_SERVICE_EXCEPTION, exc);
1159 getter = resourceClass.getMethod("get"+StringUtils.capitalize(value));
1160 if(!type.getName().equals("java.lang.String")) {
1161 getters.put(id, getter);
1163 } catch(NoSuchMethodException exc) {
1165 if(type.getName().equals("java.lang.Boolean")) {
1166 getter = resourceClass.getMethod("is"+StringUtils.capitalize(value));
1167 getters.put(id, getter);
1169 getLogger().warn(AAI_SERVICE_EXCEPTION, exc);
1171 } catch(Exception iexc) {
1172 getLogger().warn(AAI_SERVICE_EXCEPTION, iexc);
1174 } catch(Exception exc) {
1175 getLogger().warn(AAI_SERVICE_EXCEPTION, exc);
1179 subResources.addAll(Arrays.asList(values));
1184 // remove getters that have matching setter
1185 for(String setKey : setters.keySet()) {
1186 if(getters.containsKey(setKey)) {
1187 getters.remove(setKey);
1191 Set<String> relationshipKeys = new TreeSet<>();
1192 Set<String> vlansKeys = new TreeSet<>();
1193 Set<String> metadataKeys = new TreeSet<>();
1195 for(String attribute : set) {
1196 String value = params.get(attribute);
1197 if(attribute.startsWith("relationship-list")) {
1198 relationshipKeys.add(attribute);
1199 } else if(attribute.startsWith("vlans")) {
1200 vlansKeys.add(attribute);
1201 } else if(attribute.startsWith("metadata")) {
1202 metadataKeys.add(attribute);
1205 // 3. find list property getters
1206 for(String attribute : set) {
1207 String value = params.get(attribute);
1208 Method method = getters.get(attribute);
1209 if(method != null) {
1211 Object arglist[] = new Object[0];
1212 // arglist[0] = value;
1213 Class<?>[] types = method.getParameterTypes();
1214 if(types.length == 0){
1215 Object o = method.invoke(instance, arglist);
1216 if(o instanceof ArrayList) {
1217 ArrayList<String> values = (ArrayList<String>)o;
1218 value = value.replace("[", "").replace("]", "");
1219 List<String> items = Arrays.asList(value.split("\\s*,\\s*"));
1220 for(String s : items) {
1221 values.add(s.trim());
1225 } catch (Exception x) {
1226 Throwable cause = x.getCause();
1227 getLogger().warn("Failed process for " + resourceClass.getName(), x);
1231 // 4. Process Relationships
1232 // add relationship list
1233 if( (subResources.contains("relationship-list") || subResources.contains("relationshipList")) && !relationshipKeys.isEmpty()) {
1234 RelationshipList relationshipList = null;
1236 Method getRelationshipListMethod = null;
1238 getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
1239 } catch(Exception exc) {
1240 getLogger().debug(RELATIONSHIP_DATA + exc.getMessage());
1243 if(getRelationshipListMethod != null){
1245 obj = getRelationshipListMethod.invoke(instance);
1246 } catch (InvocationTargetException x) {
1247 Throwable cause = x.getCause();
1250 if(obj != null && obj instanceof RelationshipList){
1251 relationshipList = (RelationshipList)obj;
1253 relationshipList = new RelationshipList();
1254 Method setRelationshipListMethod = resourceClass.getMethod("setRelationshipList", RelationshipList.class);
1255 if(setRelationshipListMethod != null){
1257 Object arglist[] = new Object[1];
1258 arglist[0] = relationshipList;
1260 obj = setRelationshipListMethod.invoke(instance, arglist);
1261 } catch (InvocationTargetException x) {
1262 Throwable cause = x.getCause();
1267 List<Relationship> relationships = relationshipList.getRelationship();
1271 String searchKey = "relationship-list.relationship[" + i + "].related-to";
1272 if(!params.containsKey(searchKey))
1275 String relatedTo = params.get(searchKey);
1276 String relatedLinkKey = "relationship-list.relationship[" + i + "].related-link";
1277 String relatedLink = null;
1278 if(params.containsKey(relatedLinkKey)) {
1279 relatedLink = params.get(relatedLinkKey);
1281 Relationship relationship = new Relationship();
1282 relationships.add(relationship);
1283 relationship.setRelatedTo(relatedTo);
1284 String relationshipLabel = "relationship-list.relationship[" + i + "].relationship-label";
1285 if(params.containsKey(searchKey)) {
1286 relationship.setRelationshipLabel(params.get(relationshipLabel));
1288 getLogger().debug("About to process related link of {}", relatedLink);
1289 if(relatedLink != null) {
1290 if(relatedLink.contains("v$"))
1291 relatedLink = relatedLink.replace(VERSION_PATTERN, "/v21/");
1292 relationship.setRelatedLink(relatedLink);
1294 Map<String, String> relParams = new HashMap<>();
1297 String searchRelationshipKey = "relationship-list.relationship[" + i + "].relationship-data[" + j + "].relationship-key";
1298 String searchRelationshipValue = "relationship-list.relationship[" + i + "].relationship-data[" + j + "].relationship-value";
1299 if(!params.containsKey(searchRelationshipKey))
1302 relParams.put(params.get(searchRelationshipKey), params.get(searchRelationshipValue));
1305 AAIRequest rlRequest = AAIRequest.createRequest(relatedTo, relParams);
1306 for(Map.Entry<String,String> entry : relParams.entrySet()) {
1307 rlRequest.addRequestProperty(entry.getKey(), entry.getValue());
1309 String path = rlRequest.updatePathDataValues(null);
1310 relationship.setRelatedLink(path);
1314 // process related to properties
1315 Map<String, String> relParams = new HashMap<String, String>();
1318 String searchRelatedToKey = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-key";
1319 String searchRelatedToValue = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-value";
1320 if(!params.containsKey(searchRelatedToKey))
1323 RelatedToProperty relDatum = new RelatedToProperty();
1324 relDatum.setPropertyKey(params.get(searchRelatedToKey));
1325 relDatum.setPropertyValue(params.get(searchRelatedToValue));
1326 relationship.getRelatedToProperty().add(relDatum);
1328 relParams.put(params.get(searchRelatedToKey), params.get(searchRelatedToValue));
1337 if(subResources.contains("vlans") && !vlansKeys.isEmpty()) {
1339 Vlans vlanList = null;
1340 Method getVLansMethod = resourceClass.getMethod("getVlans");
1341 if(getVLansMethod != null){
1343 obj = getVLansMethod.invoke(instance);
1344 } catch (InvocationTargetException x) {
1345 Throwable cause = x.getCause();
1348 if(obj != null && obj instanceof Vlans){
1349 vlanList = (Vlans)obj;
1351 vlanList = new Vlans();
1352 Method setVlansMethod = resourceClass.getMethod("setVlans", Vlans.class);
1353 if(setVlansMethod != null){
1355 Object arglist[] = new Object[1];
1356 arglist[0] = vlanList;
1358 obj = setVlansMethod.invoke(instance, arglist);
1359 } catch (InvocationTargetException x) {
1360 Throwable cause = x.getCause();
1367 String searchKey = "vlans.vlan[" + i + "].vlan-interface";
1368 if(!params.containsKey(searchKey))
1371 String vlanInterface = params.get("vlans.vlan[" + i + "].vlan-interface");
1372 String vlanIdInner = params.get("vlans.vlan[" + i + "].vlan-id-inner");
1373 String vlanIdOute = params.get("vlans.vlan[" + i + "].vlan-id-outer");
1374 String speedValue = params.get("vlans.vlan[" + i + "].speed-value");
1375 String speedUnits = params.get("vlans.vlan[" + i + "].speed-units");
1377 Vlan vlan = new Vlan();
1378 vlan.setVlanInterface(vlanInterface);
1380 if(vlanIdInner != null) {
1381 Long iVlanIdInner = Long.parseLong(vlanIdInner);
1382 vlan.setVlanIdInner(iVlanIdInner);
1385 if(vlanIdOute != null) {
1386 Long iVlanIdOuter = Long.parseLong(vlanIdOute);
1387 vlan.setVlanIdOuter(iVlanIdOuter);
1390 if(speedValue != null) {
1391 vlan.setSpeedValue(speedValue);
1392 vlan.setSpeedUnits(speedUnits);
1395 vlanList.getVlan().add(vlan);
1401 if(subResources.contains("metadata") && !metadataKeys.isEmpty()) {
1403 Metadata metadataList = null;
1404 Method getMetadataMethod = resourceClass.getMethod("getMetadata");
1405 if(getMetadataMethod != null){
1407 obj = getMetadataMethod.invoke(instance);
1408 } catch (InvocationTargetException x) {
1409 Throwable cause = x.getCause();
1412 if(obj != null && obj instanceof Metadata){
1413 metadataList = (Metadata)obj;
1415 metadataList = new Metadata();
1416 Method setMetadataMethod = resourceClass.getMethod("setMetadata", Metadata.class);
1417 if(setMetadataMethod != null){
1419 Object arglist[] = new Object[1];
1420 arglist[0] = metadataList;
1422 obj = setMetadataMethod.invoke(instance, arglist);
1423 } catch (InvocationTargetException x) {
1424 Throwable cause = x.getCause();
1432 String metaKey = "metadata.metadatum[" + i + "].meta-key";
1433 if(!params.containsKey(metaKey))
1436 String metaValue = params.get("metadata.metadatum[" + i + "].meta-value");
1438 Metadatum vlan = new Metadatum();
1439 vlan.setMetaname(metaKey);
1440 vlan.setMetaval(metaValue);
1442 metadataList.getMetadatum().add(vlan);
1449 // 6. Prepare AAI request
1450 String[] args = request.getArgsList();
1451 for(String arg : args) {
1452 String modifiedKey = arg.replaceAll("-", "_");
1453 if(nameValues.containsKey(modifiedKey)) {
1454 String argValue = nameValues.get(modifiedKey);
1455 if(argValue != null) argValue = argValue.trim().replace("'", "").replace("$", "").replace("'", "");
1456 request.addRequestProperty(arg, argValue);
1460 request.processRequestPathValues(nameValues);
1461 request.setRequestObject(instance);
1462 Object response = getExecutor().post(request);
1463 if(request.expectsDataFromPUTRequest()){
1464 if(response != null && response instanceof String) {
1465 String rv = response.toString();
1466 QueryStatus retval = processResponseData(rv, resource, request, prefix, ctx, nameValues, null);
1467 getLogger().debug("newModelSave - returning " + retval.toString());
1472 } catch(AAIServiceException exc){
1473 ctx.setAttribute(prefix + ".error.message", exc.getMessage());
1474 int returnCode = exc.getReturnCode();
1475 if(returnCode >= 300) {
1476 ctx.setAttribute(prefix + ".error.http.response-code",
1477 Integer.toString(exc.getReturnCode()));
1480 if(returnCode == 400 || returnCode == 412)
1481 return QueryStatus.FAILURE;
1482 else if(returnCode == 404)
1483 return QueryStatus.NOT_FOUND;
1485 getLogger().warn("Failed newModelSave - returning FAILURE", exc);
1486 return QueryStatus.FAILURE;
1488 } catch(Exception exc){
1489 getLogger().warn("Failed newModelSave - returning FAILURE", exc);
1490 ctx.setAttribute(prefix + ".error.message", exc.getMessage());
1491 return QueryStatus.FAILURE;
1494 getLogger().debug("newModelSave - returning SUCCESS");
1495 return QueryStatus.SUCCESS;
1498 private Method findSetterFor(Class<? extends AAIDatum> resourceClass, String value) {
1500 String setterName = "set"+StringUtils.capitalize(value);
1501 for (Method method : resourceClass.getDeclaredMethods()) {
1502 int modifiers = method.getModifiers();
1503 if (Modifier.isPublic(modifiers) && setterName.contentEquals(method.getName())) {
1507 } catch(Exception exc) {
1508 getLogger().warn("findSetterFor()", exc);
1513 private QueryStatus newModelProcessRelationshipList(Object instance, Map<String, String> params, String prefix, SvcLogicContext ctx) throws Exception {
1515 Class resourceClass = instance.getClass();
1517 Set<String> relationshipKeys = new TreeSet<>();
1519 Set<String> set = params.keySet();
1521 for(String attribute : set) {
1522 String value = params.get(attribute);
1524 if(attribute.startsWith("relationship-list")) {
1525 relationshipKeys.add(attribute);
1529 // 3. Process Relationships
1530 // add relationship list
1531 if(!relationshipKeys.isEmpty()) {
1532 RelationshipList relationshipList;
1534 Method getRelationshipListMethod = null;
1536 getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
1537 } catch(Exception exc) {
1538 getLogger().debug(RELATIONSHIP_DATA + exc.getMessage());
1540 if(getRelationshipListMethod != null){
1542 obj = getRelationshipListMethod.invoke(instance);
1543 } catch (InvocationTargetException x) {
1544 Throwable cause = x.getCause();
1547 if(obj != null && obj instanceof RelationshipList){
1548 relationshipList = (RelationshipList)obj;
1550 relationshipList = new RelationshipList();
1551 Method setRelationshipListMethod = resourceClass.getMethod("setRelationshipList", RelationshipList.class);
1552 if(setRelationshipListMethod != null){
1554 Object arglist[] = new Object[1];
1555 arglist[0] = relationshipList;
1557 obj = setRelationshipListMethod.invoke(instance, arglist);
1558 } catch (InvocationTargetException x) {
1559 Throwable cause = x.getCause();
1564 boolean createdNewRelationships = false;
1565 List<Relationship> relationships = relationshipList.getRelationship();
1566 if(relationships == null) {
1567 relationships = new ArrayList<>();
1568 createdNewRelationships = true;
1573 String searchKey = "relationship-list.relationship[" + i + "].related-to";
1574 if(!params.containsKey(searchKey))
1577 String relatedTo = params.get(searchKey);
1578 String relatedLinkKey = "relationship-list.relationship[" + i + "].related-link";
1579 String relatedLink = null;
1580 if(params.containsKey(relatedLinkKey)) {
1581 relatedLink = params.get(relatedLinkKey);
1584 Relationship relationship = new Relationship();
1585 relationships.add(relationship);
1586 relationship.setRelatedTo(relatedTo);
1588 String relationshipLabel = "relationship-list.relationship[" + i + "].relationship-label";
1589 if(params.containsKey(searchKey)) {
1590 relationship.setRelationshipLabel(params.get(relationshipLabel));
1593 if (relatedLink != null) {
1594 if(relatedLink.contains("v$"))
1595 relatedLink = relatedLink.replace(VERSION_PATTERN, AAIRequest.getSupportedAAIVersion());
1596 relationship.setRelatedLink(relatedLink);
1598 Map<String, String> relParams = new HashMap<>();
1602 String searchRelationshipKey = "relationship-list.relationship[" + i + "].relationship-data["
1603 + j + "].relationship-key";
1604 String searchRelationshipValue = "relationship-list.relationship[" + i + "].relationship-data["
1605 + j + "].relationship-value";
1606 if (!params.containsKey(searchRelationshipKey))
1609 RelationshipData relDatum = new RelationshipData();
1610 relDatum.setRelationshipKey(params.get(searchRelationshipKey));
1611 relDatum.setRelationshipValue(params.get(searchRelationshipValue));
1612 relationship.getRelationshipData().add(relDatum);
1614 relParams.put(params.get(searchRelationshipKey), params.get(searchRelationshipValue));
1617 AAIRequest rlRequest = AAIRequest.createRequest(relatedTo, relParams);
1618 for (Map.Entry<String, String> entry : relParams.entrySet()) {
1619 rlRequest.addRequestProperty(entry.getKey(), entry.getValue());
1621 String path = rlRequest.updatePathDataValues(null);
1622 relationship.setRelatedLink(path);
1626 // process related to properties
1627 Map<String, String> relParams = new HashMap<String, String>();
1630 String searchRelatedToKey = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-key";
1631 String searchRelatedToValue = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-value";
1632 if(!params.containsKey(searchRelatedToKey))
1635 RelatedToProperty relDatum = new RelatedToProperty();
1636 relDatum.setPropertyKey(params.get(searchRelatedToKey));
1637 relDatum.setPropertyValue(params.get(searchRelatedToValue));
1638 relationship.getRelatedToProperty().add(relDatum);
1640 relParams.put(params.get(searchRelatedToKey), params.get(searchRelatedToValue));
1649 return QueryStatus.SUCCESS;
1652 private QueryStatus newModelProcessMetadata(Object instance, Map<String, String> params, String prefix, SvcLogicContext ctx) throws Exception {
1654 if (!(instance instanceof ServiceInstance) && !(instance instanceof Image)) {
1655 throw new IllegalArgumentException("request is not applicable for selected request");
1658 Class resourceClass = instance.getClass();
1659 Set<String> metadataKeys = new TreeSet<>();
1660 Set<String> set = params.keySet();
1661 for(String attribute : set) {
1662 if(attribute.startsWith("metadata")) {
1663 metadataKeys.add(attribute);
1667 // 3. Process Metadata
1669 if(!metadataKeys.isEmpty()) {
1670 Metadata metadata = null;
1672 Method getMetadataMethod = resourceClass.getMethod("getMetadata");
1673 if(getMetadataMethod != null){
1675 obj = getMetadataMethod.invoke(instance);
1676 } catch (InvocationTargetException x) {
1677 Throwable cause = x.getCause();
1680 if(obj != null && obj instanceof Metadata){
1681 metadata = (Metadata)obj;
1683 metadata = new Metadata();
1684 Method setMetadataMethod = resourceClass.getMethod("setMetadata", Metadata.class);
1685 if(setMetadataMethod != null){
1687 setMetadataMethod.invoke(instance, metadata);
1688 } catch (InvocationTargetException x) {
1693 List<Metadatum> metadatumList = metadata.getMetadatum();
1696 String metaNameKey = "metadata.metadatum[" + i + "].metaname";
1697 String metaValueKey = "metadata.metadatum[" + i + "].metaval";
1698 if(!params.containsKey(metaNameKey) || !params.containsKey(metaValueKey))
1701 Metadatum metadatum = new Metadatum();
1702 metadatum.setMetaname(params.get(metaNameKey));
1703 metadatum.setMetaval(params.get(metaValueKey));
1704 metadatumList.add(metadatum);
1710 return QueryStatus.SUCCESS;
1713 private Relationship findRelationship(List<Relationship> relationships, String relatedTo) {
1714 if(relatedTo == null)
1717 for(Relationship relationship : relationships) {
1718 if(relationship.getRelatedTo().equals(relatedTo)){
1719 return relationship;
1726 public QueryStatus backup(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
1727 String resource = params.get("resource").toLowerCase();
1728 String prefix = params.get("data-key");
1730 HashMap<String, String> nameValues = new HashMap<>();
1731 if(AAIRequest.createRequest(resource, nameValues) != null) {
1734 return newModelBackupRequest(resource, params, prefix, ctx);
1735 } catch (Exception exc) {
1736 getLogger().warn("Failed backup - returning FAILURE", exc);
1737 return QueryStatus.FAILURE;
1741 return QueryStatus.NOT_FOUND;
1745 public QueryStatus restore(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
1747 QueryStatus retval = QueryStatus.SUCCESS;
1748 String resource = params.get("resource").toLowerCase();
1749 String prefix = params.get("data-key");
1751 HashMap<String, String> nameValues = new HashMap<>();
1752 if(AAIRequest.createRequest(resource, nameValues) != null) {
1755 retval = newModelBackupRequest(resource, params, "tmpRestore", ctx);
1756 if(retval == QueryStatus.SUCCESS) {
1757 ctx.setAttribute("tmpRestore", null);
1759 } catch (Exception exc) {
1760 getLogger().warn("Failed restore - returning FAILURE", exc);
1761 return QueryStatus.FAILURE;
1765 return QueryStatus.NOT_FOUND;
1768 protected Map<String, Object> objectToProperties(Object object) {
1769 ObjectMapper mapper = AAIService.getObjectMapper();
1770 return mapper.convertValue(object, Map.class);
1773 static <T> T valueOf(Class<T> klazz, String arg) {
1774 Exception cause = null;
1777 ret = klazz.cast(klazz.getDeclaredMethod("valueOf", String.class).invoke(null, arg));
1778 } catch (NoSuchMethodException exc) {
1779 LoggerFactory.getLogger(AAIService.class).warn("Wrong data type", exc);
1780 ret = klazz.cast(arg);
1781 } catch (IllegalAccessException e) {
1783 } catch (InvocationTargetException e) {
1786 if (cause == null) {
1789 throw new IllegalArgumentException(cause);
1793 private QueryStatus processDeleteRelationshipList(String resource, String key, SvcLogicContext ctx, HashMap<String, String> nameValues) {
1795 AAIRequest request = AAIRequest.createRequest(resource.split(":")[0], nameValues);
1796 if(request == null) {
1797 return QueryStatus.FAILURE;
1800 request.processRequestPathValues(nameValues);
1801 URL url = request.getRequestUrl("GET", null);
1803 Class resourceClass = request.getModelClass();
1804 Object instance = getResource(url.toString(), resourceClass);
1805 if(instance == null)
1806 return QueryStatus.NOT_FOUND;
1808 // get resource version
1809 String resourceVersion = null;
1810 Method getResourceVersionMethod = resourceClass.getMethod("getResourceVersion");
1811 if(getResourceVersionMethod != null){
1813 Object object = getResourceVersionMethod.invoke(instance);
1815 resourceVersion = object.toString();
1816 } catch (InvocationTargetException exc) {
1817 getLogger().warn("Retrieving resource version", exc);
1821 RelationshipList relationshipList = null;
1823 Method getRelationshipListMethod = null;
1825 getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
1826 } catch(Exception exc) {
1827 getLogger().debug(RELATIONSHIP_DATA + exc.getMessage());
1829 if(getRelationshipListMethod != null){
1831 obj = getRelationshipListMethod.invoke(instance);
1832 } catch (InvocationTargetException x) {
1833 Throwable cause = x.getCause();
1836 if(obj != null && obj instanceof RelationshipList){
1837 relationshipList = (RelationshipList)obj;
1839 getLogger().debug("No relationships found to process.");
1840 return QueryStatus.NOT_FOUND;
1843 if(relationshipList.getRelationship() == null || relationshipList.getRelationship().isEmpty()) {
1844 return QueryStatus.NOT_FOUND;
1846 String relatedTo = nameValues.get("related_to");
1847 if(relatedTo == null) {
1848 return QueryStatus.FAILURE;
1851 relatedTo = relatedTo.replaceAll("_", "-");
1853 String relatedLink = nameValues.get("relationship.related_link");
1854 if(relatedLink != null) {
1855 relatedLink = URLDecoder.decode(relatedLink, "UTF-8");
1858 List<Relationship> relationships = relationshipList.getRelationship();
1859 List<Relationship> relationshipsToDelete = new LinkedList<>();
1861 for(Relationship relationship : relationships) {
1862 if(relatedTo.equals(relationship.getRelatedTo())) {
1863 if(relatedLink != null) {
1864 if(relationship.getRelatedLink() != null ) {
1865 String localRelatedLink = relationship.getRelatedLink();
1866 localRelatedLink = URLDecoder.decode(localRelatedLink, "UTF-8");
1867 if(localRelatedLink.endsWith(relatedLink)) {
1868 getLogger().debug(String.format("Found relationship of '%s' to keyword '%s'", relationship.getRelatedTo(), relatedTo));
1869 relationshipsToDelete.add(relationship);
1873 getLogger().debug(String.format("Found relationship of '%s' to keyword '%s'", relationship.getRelatedTo(), relatedTo));
1874 relationshipsToDelete.add(relationship);
1878 if(relationshipsToDelete == null || relationshipsToDelete.isEmpty()) {
1879 getLogger().info(String.format("Relationship has not been found for %s", key));
1880 return QueryStatus.NOT_FOUND;
1883 String path = url.toString();
1884 path = path + "/relationship-list/relationship";
1885 URL deleteUrl = new URL(path);
1887 ObjectMapper mapper = AAIService.getObjectMapper();
1889 boolean cumulativeResponse = true;
1891 for(Relationship targetRelationship : relationshipsToDelete) {
1892 String json_text = mapper.writeValueAsString(targetRelationship);
1893 boolean response = deleteList(deleteUrl, json_text);
1895 cumulativeResponse = response;
1899 if(!cumulativeResponse)
1900 return QueryStatus.FAILURE;
1902 return QueryStatus.SUCCESS;
1904 } catch(Exception exc) {
1905 getLogger().warn("processDelete", exc);
1906 return QueryStatus.FAILURE;
1910 private QueryStatus processDeleteMetadata(String resource, String key, SvcLogicContext ctx, HashMap<String, String> nameValues) {
1912 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
1913 if(request == null) {
1914 return QueryStatus.FAILURE;
1917 request.processRequestPathValues(nameValues);
1918 URL url = request.getRequestUrl("GET", null);
1920 Class<?> resourceClass = request.getModelClass();
1921 Object instance = getResource(url.toString(), resourceClass);
1923 // get resource version
1924 String resourceVersion = null;
1925 Method getResourceVersionMethod = resourceClass.getMethod("getResourceVersion");
1926 if(getResourceVersionMethod != null){
1928 resourceVersion = (String) getResourceVersionMethod.invoke(instance);
1929 } catch (InvocationTargetException x) {
1933 Metadata metadata = null;
1935 Method getMetadataMethod = resourceClass.getMethod("getMetadata");
1936 if(getMetadataMethod != null){
1938 obj = getMetadataMethod.invoke(instance);
1939 } catch (InvocationTargetException x) {
1940 Throwable cause = x.getCause();
1943 if(obj != null && obj instanceof Metadata){
1944 metadata = (Metadata)obj;
1946 getLogger().debug("No metadata found to process.");
1947 return QueryStatus.NOT_FOUND;
1950 if(metadata.getMetadatum() == null || metadata.getMetadatum().isEmpty()) {
1951 return QueryStatus.NOT_FOUND;
1954 List<Metadatum> metadatumList = metadata.getMetadatum();
1955 Metadatum metadatumToDelete = null;
1957 final String metaname = nameValues.get("metaname");
1959 for(Metadatum metadatum : metadatumList) {
1960 getLogger().debug(String.format("Comparing existing metadatum of '%s' to keyword '%s'", metadatum.getMetaname(), metaname));
1961 if(metaname.equals(metadatum.getMetaname())) {
1962 metadatumToDelete = metadatum;
1966 if(metadatumToDelete == null) {
1967 getLogger().info(String.format("Metadatum has not been found for %s", key));
1968 return QueryStatus.NOT_FOUND;
1971 String path = url.toString();
1972 path = path + "/metadata/metadatum/" + encodeQuery( metadatumToDelete.getMetaname() ) +
1973 "?resource-version=" + metadatumToDelete.getResourceVersion();
1974 URL deleteUrl = new URL(path);
1975 boolean response = deleteList(deleteUrl, null);
1978 return QueryStatus.FAILURE;
1980 return QueryStatus.SUCCESS;
1982 } catch(Exception exc) {
1983 getLogger().warn("processDelete", exc);
1984 return QueryStatus.FAILURE;
1988 protected String encodeQuery(String param) throws UnsupportedEncodingException {
1989 return URLEncoder.encode(param, "UTF-8").replace("+", "%20");
1992 static final Map<String, String> ctxGetBeginsWith( SvcLogicContext ctx, String prefix ) {
1993 Map<String, String> tmpPrefixMap = new HashMap<>();
1995 if(prefix == null || prefix.isEmpty()){
1996 return tmpPrefixMap;
1999 for( String key : ctx.getAttributeKeySet() ) {
2000 if( key.startsWith(prefix) ) {
2001 String tmpKey = key.substring(prefix.length() + 1);
2002 tmpPrefixMap.put( tmpKey, ctx.getAttribute(key));
2006 Map<String, String> prefixMap = new HashMap<>();
2007 Pattern p = Pattern.compile(".*\\[\\d\\]");
2009 SortedSet<String> keys = new TreeSet<String>(tmpPrefixMap.keySet () );
2010 for(String key : keys) {
2011 Matcher m = p.matcher(key);
2014 } else if(key.endsWith("_length")) {
2015 String listKey = key.substring(0, key.indexOf("_length"));
2016 int max = Integer.parseInt(tmpPrefixMap.get(key));
2018 ArrayList<String> data = new ArrayList<>();
2019 for(int x = 0; x < max; x++){
2020 String tmpKey = String.format("%s[%d]", listKey, x);
2021 String tmpValue = tmpPrefixMap.get(tmpKey);
2022 if(tmpValue != null && !tmpValue.isEmpty()) {
2026 if(!data.isEmpty()) {
2027 prefixMap.put(listKey, data.toString());
2029 prefixMap.put(key, tmpPrefixMap.get(key));
2032 prefixMap.put(key, tmpPrefixMap.get(key));
2039 public abstract <T> T getResource(String key, Class<T> type) throws AAIServiceException ;
2040 protected abstract boolean deleteList(URL url, String caller) throws AAIServiceException;