Isolate deprecated code in CCSDK aai-service
[ccsdk/sli/adaptors.git] / aai-service / provider / src / main / java / org / onap / ccsdk / sli / adaptors / aai / AAIDeclarations.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *             reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.ccsdk.sli.adaptors.aai;
23
24 import java.io.IOException;
25 import java.io.UnsupportedEncodingException;
26 import java.lang.annotation.Annotation;
27 import java.lang.reflect.Field;
28 import java.lang.reflect.InvocationTargetException;
29 import java.lang.reflect.Method;
30 import java.net.MalformedURLException;
31 import java.net.URISyntaxException;
32 import java.net.URL;
33 import java.net.URLDecoder;
34 import java.net.URLEncoder;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.HashMap;
38 import java.util.LinkedList;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Set;
42 import java.util.SortedSet;
43 import java.util.TreeSet;
44 import java.util.regex.Matcher;
45 import java.util.regex.Pattern;
46
47 import javax.xml.bind.annotation.XmlType;
48
49 import org.apache.commons.lang.StringUtils;
50 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
51 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
52 import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
53 import org.openecomp.aai.inventory.v11.Image;
54 import org.openecomp.aai.inventory.v11.GenericVnf;
55 import org.openecomp.aai.inventory.v11.InventoryResponseItem;
56 import org.openecomp.aai.inventory.v11.InventoryResponseItems;
57 import org.openecomp.aai.inventory.v11.L3Network;
58 import org.openecomp.aai.inventory.v11.LogicalLink;
59 import org.openecomp.aai.inventory.v11.Metadata;
60 import org.openecomp.aai.inventory.v11.Metadatum;
61 import org.openecomp.aai.inventory.v11.Pnf;
62 import org.openecomp.aai.inventory.v11.RelatedToProperty;
63 import org.openecomp.aai.inventory.v11.Relationship;
64 import org.openecomp.aai.inventory.v11.RelationshipData;
65 import org.openecomp.aai.inventory.v11.RelationshipList;
66 import org.openecomp.aai.inventory.v11.ResultData;
67 import org.openecomp.aai.inventory.v11.SearchResults;
68 import org.openecomp.aai.inventory.v11.ServiceInstance;
69 import org.openecomp.aai.inventory.v11.Vlan;
70 import org.openecomp.aai.inventory.v11.Vlans;
71 import org.openecomp.aai.inventory.v11.Vserver;
72 import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
73 import org.onap.ccsdk.sli.adaptors.aai.query.FormattedQueryResultList;
74 import org.onap.ccsdk.sli.adaptors.aai.query.InstanceFilter;
75 import org.onap.ccsdk.sli.adaptors.aai.query.InstanceFilters;
76 import org.onap.ccsdk.sli.adaptors.aai.query.NamedQuery;
77 import org.onap.ccsdk.sli.adaptors.aai.query.NamedQueryData;
78 import org.onap.ccsdk.sli.adaptors.aai.query.QueryParameters;
79 import org.onap.ccsdk.sli.adaptors.aai.query.Result;
80 import org.slf4j.Logger;
81 import org.slf4j.LoggerFactory;
82
83 import com.fasterxml.jackson.core.JsonParseException;
84 import com.fasterxml.jackson.databind.JsonMappingException;
85 import com.fasterxml.jackson.databind.ObjectMapper;
86
87
88 public abstract class AAIDeclarations implements AAIClient {
89
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";
94
95     public static final String APPLICATION_ID     = "org.onap.ccsdk.sli.adaptors.aai.application";
96
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";
99
100
101     public static final String CONNECTION_TIMEOUT = "connection.timeout";
102     public static final String READ_TIMEOUT       = "read.timeout";
103
104     public static final String TARGET_URI         = "org.onap.ccsdk.sli.adaptors.aai.uri";
105
106     // Availability zones query
107     public static final String QUERY_PATH         = "org.onap.ccsdk.sli.adaptors.aai.path.query";
108
109     // Update
110     public static final String UPDATE_PATH          = "org.onap.ccsdk.sli.adaptors.aai.update";
111
112     // Service instance
113     public static final String SVC_INSTANCE_PATH  = "org.onap.ccsdk.sli.adaptors.aai.path.svcinst";
114     public static final String SVC_INST_QRY_PATH  = "org.onap.ccsdk.sli.adaptors.aai.path.svcinst.query";
115
116     // VServer
117     public static final String NETWORK_VSERVER_PATH  = "org.onap.ccsdk.sli.adaptors.aai.path.vserver";
118
119     public static final String VNF_IMAGE_QUERY_PATH      = "org.onap.ccsdk.sli.adaptors.aai.path.vnf.image.query";
120
121     public static final String PARAM_SERVICE_TYPE     = "org.onap.ccsdk.sli.adaptors.aai.param.service.type";
122     public static final String CERTIFICATE_HOST_ERROR = "org.onap.ccsdk.sli.adaptors.aai.host.certificate.ignore";
123
124     // UBB Notify
125     public static final String UBB_NOTIFY_PATH        = "org.onap.ccsdk.sli.adaptors.aai.path.notify";
126     public static final String SELFLINK_AVPN          = "org.onap.ccsdk.sli.adaptors.aai.notify.selflink.avpn";
127     public static final String SELFLINK_FQDN          = "org.onap.ccsdk.sli.adaptors.aai.notify.selflink.fqdn";
128
129     //Service
130     public static final String SERVICE_PATH              = "org.onap.ccsdk.sli.adaptors.aai.path.service";
131
132     // P-Interfaces
133     public static final String P_INTERFACE_PATH       = "org.onap.ccsdk.sli.adaptors.aai.path.pserver.pinterface";
134
135     // site-pair-sets
136     public static final String SITE_PAIR_SET_PATH     = "org.onap.ccsdk.sli.adaptors.aai.path.site.pair.set";
137
138     // node query (1602)
139     public static final String QUERY_NODES_PATH          = "org.onap.ccsdk.sli.adaptors.aai.query.nodes";
140
141
142     protected abstract Logger getLogger();
143     public abstract AAIExecutorInterface getExecutor();
144
145
146     @Override
147     public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx)
148         throws SvcLogicException {
149
150         getLogger().debug("AAIService.query \tresource = "+resource);
151
152         String vnfId;
153         String vnfName = null;
154         HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
155         getLogger().debug("key = "+ nameValues.toString());
156
157         if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
158             ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
159             return QueryStatus.FAILURE;
160         }
161
162         if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
163             ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported", resource));
164             return QueryStatus.FAILURE;
165         }
166
167         // process data using new model
168         boolean useNewModelProcessing = true;
169         // process server query by name the old way
170         if("vserver".equals(resource) || "vserver2".equals(resource)){
171             if(nameValues.containsKey("vserver_name") || nameValues.containsKey("vserver-name") || nameValues.containsKey("vserver.vserver_name") || nameValues.containsKey("vserver.vserver-name"))
172                 useNewModelProcessing = false;
173         }
174         if("generic-vnf".equals(resource)){
175             if(nameValues.containsKey("vnf_name") || nameValues.containsKey("vnf-name") || nameValues.containsKey("generic_vnf.vnf_name") || nameValues.containsKey("generic-vnf.vnf-name"))
176                 useNewModelProcessing = false;
177         }
178
179         // process data using new model
180         if(useNewModelProcessing && AAIRequest.createRequest(resource, nameValues) != null) {
181
182             try {
183                 return newModelQuery(resource, localOnly, select, key, prefix, orderBy, ctx);
184             } catch (Exception exc) {
185                 getLogger().warn("Failed query - returning FAILURE", exc);
186                 return QueryStatus.FAILURE;
187             }
188         }
189
190         ObjectMapper mapper = AAIService.getObjectMapper();
191         Map<String,Object> attributes = new HashMap<>();
192
193         String modifier = null;
194
195         if(resource.contains(":")) {
196             String[] tokens = resource.split(":");
197             resource = tokens[0];
198             if(tokens.length > 1) {
199                 modifier = tokens[1];
200             }
201         }
202
203         resource = resource.toLowerCase().replace("-", "_");
204
205         try {
206
207             switch(resource) {
208                 case "generic_vnf":
209                     vnfId = nameValues.get("vnf_id");
210                     if(nameValues.containsKey("vnf_id"))
211                         vnfId = nameValues.get("vnf_id");
212                     else if(nameValues.containsKey("generic_vnf.vnf_name"))
213                         vnfId = nameValues.get("generic_vnf.vserver_name");
214
215                     if(nameValues.containsKey("vnf_name"))
216                         vnfName = nameValues.get("vnf_name");
217                     else if(nameValues.containsKey("generic_vnf.vnf_name"))
218                         vnfName = nameValues.get("generic_vnf.vnf_name");
219
220                     if(vnfId != null && !vnfId.isEmpty()) {
221                         // at this point of the project this part should not be executed
222                         vnfId = vnfId.trim().replace("'", "").replace("$", "").replace("'", "");
223                         GenericVnf vnf = this.requestGenericVnfData(vnfId);
224                         if(vnf == null) {
225                             return QueryStatus.NOT_FOUND;
226                         }
227
228                         attributes = mapper.convertValue(vnf, attributes.getClass());
229                     } else if(vnfName != null && !vnfName.isEmpty()) {
230                         try {
231                             vnfName = vnfName.trim().replace("'", "").replace("$", "").replace("'", "");
232                             GenericVnf vnf = this.requestGenericVnfeNodeQuery(vnfName);
233                             if(vnf == null) {
234                                 return QueryStatus.NOT_FOUND;
235                             }
236                             vnfId=vnf.getVnfId();
237                             nameValues.put("vnf_id", vnfId);
238                             attributes = mapper.convertValue(vnf, attributes.getClass());
239                         } catch (AAIServiceException exc) {
240                             int errorCode = exc.getReturnCode();
241                             switch(errorCode) {
242                             case 400:
243                             case 404:
244                             case 412:
245                                 break;
246                             default:
247                                 getLogger().warn("Caught exception trying to refresh generic VNF", exc);
248                             }
249                             ctx.setAttribute(prefix + ".error.message", exc.getMessage());
250                             if(errorCode >= 300) {
251                                 ctx.setAttribute(prefix + ".error.http.response-code",
252                                                  Integer.toString(exc.getReturnCode()));
253                             }
254                             return QueryStatus.FAILURE;
255                         }
256                     } else {
257                         getLogger().warn("No arguments are available to process generic VNF");
258                         return QueryStatus.FAILURE;
259                     }
260                     break;
261                 case "vserver":
262                 case "vserver2":
263                     String vserverName = null;
264                     if(nameValues.containsKey("vserver_name"))
265                         vserverName = nameValues.get("vserver_name");
266                     else if(nameValues.containsKey("vserver.vserver_name"))
267                         vserverName = nameValues.get("vserver.vserver_name");
268
269                     String vserverId = null;
270                     if(nameValues.containsKey("vserver_id"))
271                         vserverId = nameValues.get("vserver_id");
272                     if(nameValues.containsKey("vserver.vserver_id"))
273                         vserverId = nameValues.get("vserver.vserver_id");
274                     String tenantId = nameValues.get("teannt_id");
275
276                     if(vserverName != null) vserverName = vserverName.trim().replace("'", "").replace("$", "").replace("'", "");
277                     if(vserverId != null) vserverId = vserverId.trim().replace("'", "").replace("$", "").replace("'", "");
278                     if(tenantId != null) tenantId = tenantId.trim().replace("'", "").replace("$", "").replace("'", "");
279
280                 if (vserverName != null) {
281                     URL vserverUrl = null;
282                     try {
283                         vserverUrl = this.requestVserverURLNodeQuery(vserverName);
284                     } catch (AAIServiceException aaiexc) {
285                         ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
286                         if (aaiexc.getReturnCode() >= 300) {
287                             ctx.setAttribute(prefix + ".error.http" + "" + ".response-code", Integer.toString(aaiexc.getReturnCode()));
288                         }
289
290                         if (aaiexc.getReturnCode() == 404)
291                             return QueryStatus.NOT_FOUND;
292                         else
293                             return QueryStatus.FAILURE;
294                     }
295                     if (vserverUrl == null) {
296                         return QueryStatus.NOT_FOUND;
297                     }
298
299                     tenantId = getTenantIdFromVserverUrl(vserverUrl);
300                             String cloudOwner = getCloudOwnerFromVserverUrl(vserverUrl);
301                             String cloudRegionId = getCloudRegionFromVserverUrl(vserverUrl);
302
303                     Vserver vserver = null;
304                     try {
305                         vserver = this.requestVServerDataByURL(vserverUrl);
306                     } catch (AAIServiceException aaiexc) {
307                         ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
308                         if (aaiexc.getReturnCode() >= 300) {
309                             ctx.setAttribute(prefix + ".error.http" + ".response-code", Integer.toString(aaiexc.getReturnCode()));
310                         }
311
312                         if (aaiexc.getReturnCode() == 404)
313                             return QueryStatus.NOT_FOUND;
314                         else
315                             return QueryStatus.FAILURE;
316                     }
317                     if (vserver == null) {
318                         return QueryStatus.NOT_FOUND;
319                     }
320                     attributes = mapper.convertValue(vserver, attributes.getClass());
321                     if (!attributes.containsKey("tenant-id") && tenantId != null) {
322                         attributes.put("tenant-id", tenantId);
323                     }
324                     if (!attributes.containsKey("cloud-owner") && cloudOwner != null) {
325                         attributes.put("cloud-owner", cloudOwner);
326                     }
327                     if (!attributes.containsKey("cloud-region-id") && cloudRegionId != null) {
328                         attributes.put("cloud-region-id", cloudRegionId);
329                     }
330                 } else if (vserverId != null && tenantId != null) {
331                         Vserver vserver = this.requestVServerData(tenantId, vserverId, "att-aic", "AAIAIC25");
332                         if(vserver == null) {
333                             return QueryStatus.NOT_FOUND;
334                         }
335                         attributes = mapper.convertValue(vserver, attributes.getClass());
336                         if(!attributes.containsKey("tenant-id") && tenantId != null){
337                             attributes.put("tenant-id", tenantId);
338                         }
339                     } else {
340                         return QueryStatus.FAILURE;
341                     }
342                     break;
343
344                 default:
345                     return QueryStatus.FAILURE;
346             }
347
348             QueryStatus retval = QueryStatus.SUCCESS;
349
350             if (attributes == null || attributes.isEmpty()) {
351                 retval = QueryStatus.NOT_FOUND;
352                 getLogger().debug("No data found");
353             } else {
354                 if (ctx != null) {
355                     if (prefix != null) {
356                         ArrayList<String> keys = new ArrayList<>(attributes.keySet());
357
358                         int numCols = keys.size();
359
360                         for (int i = 0; i < numCols; i++) {
361                             String colValue;
362                             String colName = keys.get(i);
363                             Object object = attributes.get(colName);
364
365                             if(object != null && object instanceof String) {
366                                 colValue = (String)object;
367
368                                 if (prefix != null) {
369                                     getLogger().debug("Setting "+prefix    + "." + colName.replaceAll("_", "-")+" = "+ colValue);
370                                     ctx.setAttribute(prefix    + "." + colName.replaceAll("_", "-"), colValue);
371                                 } else {
372                                     getLogger().debug("Setting " + colValue.replaceAll("_", "-")+" = "+colValue);
373                                     ctx.setAttribute(colValue.replaceAll("_", "-"), colValue);
374                                 }
375                             } else if(object != null && object instanceof Map) {
376                                 if(colName.equals(modifier) || "relationship-list".equals(colName)){
377                                     String localNodifier = modifier;
378                                     if(localNodifier == null)
379                                         localNodifier = "relationship-list";
380                                     Map<String, Object> properties = (Map<String, Object>)object;
381                                     writeMap(properties, prefix+"."+localNodifier,  ctx);
382                                 }
383                             }
384                         }
385                     }
386                 }
387             }
388             getLogger().debug("Query - returning " + retval);
389             return retval;
390
391         } catch (Exception exc) {
392             getLogger().warn("Failed query - returning FAILURE", exc);
393             return QueryStatus.FAILURE;
394         }
395
396 //        return QueryStatus.SUCCESS;
397     }
398
399
400     public void writeMap(Map<String, Object> properties, String prefix, SvcLogicContext ctx) {
401         Set<String> mapKeys = properties.keySet();
402
403         for(String mapKey : mapKeys) {
404             Object entity = properties.get(mapKey);
405             if(entity instanceof ArrayList) {
406                 writeList((ArrayList<?>)entity, prefix + "." + mapKey, ctx);
407             } else
408             if(entity instanceof String ||  entity instanceof Long || entity instanceof Integer || entity instanceof Boolean) {
409                 ctx.setAttribute(prefix + "." + mapKey, entity.toString());
410                 getLogger().debug(prefix + "." + mapKey + " : " + entity.toString());
411             } else if(entity instanceof Map) {
412                 String localPrefix = prefix;
413                 if(mapKey != null) {
414                     localPrefix = String.format("%s.%s", prefix, mapKey);
415                 }
416                 writeMap( (Map<String, Object>)entity,  localPrefix,  ctx);
417             }
418         }
419     }
420
421     private void writeList(ArrayList<?> list, String prefix, SvcLogicContext ctx) {
422         for(int i = 0; i < list.size(); i++ ) {
423             Object entity = list.get(i);
424             if(entity instanceof Map) {
425                 writeMap( (Map<String, Object>)entity,  prefix + "[" + i + "]",  ctx);
426             } else
427                 if(entity instanceof String ||  entity instanceof Long || entity instanceof Integer || entity instanceof Boolean) {
428                 ctx.setAttribute(prefix, entity.toString());
429                 getLogger().debug(prefix  + " : " + entity.toString());
430             }
431         }
432
433         if(!list.isEmpty()) {
434             ctx.setAttribute(prefix + "_length", Integer.toString(list.size()));
435             getLogger().debug(prefix + "_length"  + " : " + Integer.toString(list.size()));
436         }
437     }
438
439     @Override
440     public QueryStatus save(String resource, boolean force, boolean localOnly, String key, Map<String, String> params, String prefix, SvcLogicContext ctx)
441             throws SvcLogicException {
442
443         getLogger().debug("AAIService.save\tresource="+resource);
444         HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
445
446         if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
447             ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
448             return QueryStatus.FAILURE;
449         }
450
451         if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
452             getLogger().warn("AAIService.save has unspecified resource");
453             ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported", resource));
454             return QueryStatus.FAILURE;
455         }
456         // keys passed
457         getLogger().debug("key = "+ Arrays.toString(nameValues.entrySet().toArray()));
458
459         // process params
460         if(params.containsKey("prefix")) {
461             Map<String, String> tmpParams = ctxGetBeginsWith(ctx, params.get("prefix"));
462             if(!tmpParams.isEmpty()) {
463                 params.putAll(tmpParams);
464 //                params.remove("prefix");
465             }
466         }
467         // params passed
468         getLogger().debug("parms = "+ Arrays.toString(params.entrySet().toArray()));
469
470         boolean useNewModelProcessing = true;
471         // process server query by name the old way
472         if("vserver".equals(resource) || "vserver2".equals(resource)){
473             if(nameValues.containsKey("vserver-name")) {
474                 useNewModelProcessing = false;
475             }
476
477             if(!params.containsKey("vserver-selflink")) {
478
479                 AAIRequest request = AAIRequest.createRequest(resource, nameValues);
480                 URL path = null;
481                 try {
482                     request.processRequestPathValues(nameValues);
483                     path = request.getRequestUrl("GET", null);
484                     params.put("vserver-selflink", path.toString());
485                 } catch (UnsupportedEncodingException | MalformedURLException | URISyntaxException e) {
486                     // TODO : Fix this
487                     params.put("vserver-selflink", "/vserver");
488                 }
489             }
490         }
491
492         // process data using new model
493         if(useNewModelProcessing && AAIRequest.createRequest(resource, nameValues) != null) {
494
495             try {
496                 if(!resource.contains(":")){
497                     return newModelSave(resource, force, key, params, prefix, ctx);
498                 } else {
499                     String[] tokens = resource.split(":");
500                     String localResource = tokens[0];
501                     String dependency = tokens[1];
502
503                     AAIDatum instance = newModelObjectRequest( localResource, nameValues, prefix, ctx);
504                     if(instance == null) {
505                         return QueryStatus.NOT_FOUND;
506                     }
507
508                     switch(dependency){
509                         case "relationship-list":
510                             newModelProcessRelationshipList(instance, params, prefix, ctx);
511                             break;
512                         case "metadata":
513                             newModelProcessMetadata(instance, params, prefix, ctx);
514                             break;
515                     }
516                     // create a method to update relationship-list
517                     AAIRequest request = AAIRequest.createRequest(localResource, nameValues);
518                     request.setRequestObject(instance);
519                     request.processRequestPathValues(nameValues);
520
521                     getExecutor().post(request);
522                         getLogger().debug("Save relationship list - returning SUCCESS");
523                         return QueryStatus.SUCCESS;
524                 }
525             } catch (Exception exc) {
526                 ctx.setAttribute(prefix + ".error.message", exc.getMessage());
527                 if(exc instanceof AAIServiceException) {
528                     AAIServiceException aaiexc = (AAIServiceException)exc;
529                     if(aaiexc.getReturnCode() >= 300) {
530                         ctx.setAttribute(prefix + ".error.http" + ".response-code", Integer.toString(aaiexc.getReturnCode()));
531                     }
532
533                     if(aaiexc.getReturnCode() == 404) {
534                         return QueryStatus.NOT_FOUND;
535                     }
536                 }
537                 getLogger().warn("Failed save() - returning FAILURE", exc);
538                 return QueryStatus.FAILURE;
539             }
540         } else {
541             String reSource = resource.toLowerCase().replace("-", "_");
542                 String vnfId;
543
544             try {
545                 switch(reSource) {
546                     case "generic_vnf":
547                     case "generic-vnf":
548                         vnfId = nameValues.get("vnf_id");
549                         if(vnfId == null) {
550                             getLogger().debug("Save(generic-vnf) with no vnf-id specified. Returning FAILURE");
551                             return QueryStatus.FAILURE;
552                         }
553                         vnfId = vnfId.trim().replace("'", "").replace("$", "").replace("'", "");
554                         GenericVnf vnf = this.requestGenericVnfData(vnfId);
555                         String status = params.get("prov-status");
556                         boolean updated = false;
557                         if(status != null && !status.isEmpty()) {
558                             vnf.setProvStatus(status);
559                         }
560                         if(updated) {
561                             this.postGenericVnfData(vnfId, vnf);
562                         }
563                         break;
564                     case "vpe":
565                         return update( resource,  key, params, prefix, ctx) ;
566
567                     default:
568                         getLogger().debug("Save() executing default path - returning FAILURE");
569                         return QueryStatus.FAILURE;
570                 }
571             } catch (Exception exc) {
572                 getLogger().warn("Failed save - returning FAILURE", exc);
573                 ctx.setAttribute(prefix + ".error.message", exc.getMessage());
574                 return QueryStatus.FAILURE;
575             }
576         }
577
578         getLogger().debug("Save - returning SUCCESS");
579         return QueryStatus.SUCCESS;
580     }
581
582     @Override
583     public QueryStatus update(String resource, String key, Map<String, String> params, String prefix, SvcLogicContext ctx) throws SvcLogicException {
584
585         resource = resource.toLowerCase();
586         HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
587         getLogger().debug("key = "+ Arrays.toString(nameValues.entrySet().toArray()));
588         if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
589             ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
590             return QueryStatus.FAILURE;
591         }
592
593         if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
594             ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported", resource));
595             return QueryStatus.FAILURE;
596         }
597
598         // check if request is for groups
599         if(!AAIServiceUtils.containsResource(resource, nameValues)) {
600             ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not permitted in 'update' operation", resource));
601             return QueryStatus.FAILURE;
602         }
603
604         getLogger().debug("parms = "+ Arrays.toString(params.entrySet().toArray()));
605
606         AAIRequest request = AAIRequest.createRequest(resource, nameValues);
607         request = new UpdateRequest(request, params);
608
609         String[] arguments = request.getArgsList();
610         for(String name : arguments) {
611             String modifiedKey = name.replaceAll("-", "_");
612             if(nameValues.containsKey(modifiedKey)) {
613                 String argValue = nameValues.get(modifiedKey);
614                 if(argValue != null) argValue = argValue.trim().replace("'", "").replace("$", "").replace("'", "");
615                 request.addRequestProperty(name, argValue);
616             }
617         }
618
619         try {
620             QueryStatus retval = QueryStatus.SUCCESS;
621
622             retval = newModelQuery(resource, false, null, key, "tmpDelete", null,  ctx);
623
624             if(retval == null || retval != QueryStatus.SUCCESS) {
625                 return retval;
626             }
627
628             String resourceVersion = ctx.getAttribute("tmpDelete.resource-version");
629             if(resourceVersion == null) {
630                 return QueryStatus.NOT_FOUND;
631             }
632             params.put("resource-version", resourceVersion);
633
634             request.processRequestPathValues(nameValues);
635             getExecutor().patch(request, resourceVersion);
636         } catch(AAIServiceException aaiexc) {
637             if(aaiexc.getReturnCode() == 404)
638                 return QueryStatus.NOT_FOUND;
639             else
640                 return QueryStatus.FAILURE;
641         } catch (Exception exc) {
642             getLogger().warn("Failed update - returning FAILURE", exc);
643             return QueryStatus.FAILURE;
644         }
645
646         getLogger().debug("Update - returning SUCCESS");
647         return QueryStatus.SUCCESS;
648     }
649
650     @Override
651     public QueryStatus delete(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
652         getLogger().debug("AAIService.delete\tresource="+resource);
653         HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
654         getLogger().debug("key = "+ Arrays.toString(nameValues.entrySet().toArray()));
655
656         if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
657             ctx.setAttribute(String.format("%s.error.message", "aaiData"), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
658             return QueryStatus.FAILURE;
659         }
660
661         if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
662             ctx.setAttribute(String.format("%s.error.message", "tmpDelete"), String.format("Resource %s is not supported", resource));
663             return QueryStatus.FAILURE;
664         }
665
666         // check if request is for groups
667         if(!AAIServiceUtils.containsResource(resource, nameValues)) {
668             ctx.setAttribute(String.format("%s.error.message", "tmpDelete"), String.format("Resource %s is not permitted in 'delete' operation", resource));
669             return QueryStatus.FAILURE;
670         }
671
672         if(AAIRequest.createRequest(resource, nameValues) != null) {
673             if(resource.contains(":")) {
674                 switch (resource.split(":")[1]){
675                     case "relationship-list":
676                         return processDeleteRelationshipList(resource, key, ctx, nameValues);
677                     case "metadata":
678                         return processDeleteMetadata(resource, key, ctx, nameValues);
679                 }
680             }
681
682
683             try {
684                 QueryStatus retval = QueryStatus.SUCCESS;
685
686                 retval = newModelQuery(resource, false, null, key, "tmpDelete", null,  ctx);
687
688                 if(retval == null || retval != QueryStatus.SUCCESS) {
689                     return retval;
690                 }
691
692                 String resourceVersion = ctx.getAttribute("tmpDelete.resource-version");
693                 if(resourceVersion == null) {
694                     return QueryStatus.NOT_FOUND;
695                 }
696
697                 try {
698                     AAIRequest request = AAIRequest.createRequest(resource, nameValues);
699                     if(request == null) {
700                         return QueryStatus.FAILURE;
701                     }
702
703                     request.processRequestPathValues(nameValues);
704
705                     if(getExecutor().delete(request, resourceVersion)) {
706                         return QueryStatus.SUCCESS;
707                     }
708                 } catch(AAIServiceException aaiexc) {
709                     if(aaiexc.getReturnCode() == 404)
710                         return QueryStatus.NOT_FOUND;
711                     else
712                         return QueryStatus.FAILURE;
713
714                 } catch (Exception exc) {
715                     getLogger().warn("requestGenericVnfData", exc);
716                     return QueryStatus.FAILURE;
717                 }
718
719             } catch (Exception exc) {
720                 getLogger().warn("Failed delete - returning FAILURE", exc);
721                 return QueryStatus.FAILURE;
722             }
723         } else {
724             String resourceName = resource;
725             String identifier = null;
726
727             if(resourceName.contains(":")) {
728                 String[] tokens = resourceName.split(":");
729                 if(tokens != null && tokens.length > 0) {
730                     resourceName = tokens[0];
731                     identifier = tokens[1];
732                 }
733             }
734             if("relationship-list".equals(identifier) || "relationshipList".equals(identifier)) {
735 //                RelationshipRequest relationshipRequest = new RelationshipRequest();
736                 if("generic-vnf".equals(resourceName)){
737                     String vnfId = nameValues.get("vnf_id");
738                     String relatedTo  = nameValues.get("related_to");
739                     vnfId = vnfId.trim().replace("'", "").replace("$", "").replace("'", "");
740                     relatedTo = relatedTo.trim().replace("'", "").replace("$", "").replace("'", "");
741
742                     GenericVnf vnf;
743                     try {
744                         vnf = this.requestGenericVnfData(vnfId);
745                         if(vnf == null)
746                             return QueryStatus.NOT_FOUND;
747                     } catch (AAIServiceException exc) {
748                         getLogger().warn("Failed delete - returning NOT_FOUND", exc);
749                         return QueryStatus.NOT_FOUND;
750                     }
751                     boolean itemRemoved = false;
752                     RelationshipList relationshipList = vnf.getRelationshipList();
753                     List<Relationship> relationships = relationshipList.getRelationship();
754                     List<Relationship> iterableList = new LinkedList<>(relationships);
755                     for(Relationship relationship : iterableList) {
756                         if(relationship.getRelatedTo().equals(relatedTo)) {
757                             relationships.remove(relationship);
758                             itemRemoved = true;
759                         }
760                     }
761
762                     if(!itemRemoved)
763                         return QueryStatus.NOT_FOUND;
764
765 //                    AAIRequest masterRequest = new GenericVnfRequest();
766 //                    masterRequest.addRequestProperty(GenericVnfRequest.VNF_ID, vnfId);
767 //                    relationshipRequest.addMasterRequest(masterRequest);
768 //                    Map<String, String> attributes = objectToProperties(vnf);
769 //                    try {
770 //                        Boolean result = getExecutor().delete(relationshipRequest, attributes.get(AAIRequest.RESOURCE_VERSION));
771 //                    } catch (AAIServiceException e) {
772 //                        return QueryStatus.FAILURE;
773 //                    }
774
775                     try {
776                         this.postGenericVnfData(vnf.getVnfId(), vnf);
777                     } catch (AAIServiceException exc) {
778                         if(exc.getReturnCode() == 404){
779                             return QueryStatus.NOT_FOUND;
780                         } else {
781                             getLogger().warn("Failed delete - returning FAILURE", exc);
782                             return QueryStatus.FAILURE;
783                         }
784                     }
785                     return QueryStatus.SUCCESS;
786                 }
787             }
788         }
789         return QueryStatus.FAILURE;
790     }
791
792     @Override
793     public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException {
794         return query(resource, false, null, key, prefix, null, ctx);
795     }
796
797     @Override
798     public QueryStatus isAvailable(String arg0, String arg1, String arg2, SvcLogicContext arg3)
799             throws SvcLogicException {
800         // TODO Auto-generated method stub
801         throw new SvcLogicException("Method AAIService.isAvailable() has not been implemented yet");
802     }
803
804     @Override
805     public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx) throws SvcLogicException {
806         // TODO Auto-generated method stub
807         throw new SvcLogicException("Method AAIService.notify() has not been implemented yet");
808     }
809
810 //    @Override
811     public QueryStatus newModelQuery(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx) {
812
813         Object response = null;
814         QueryStatus retval = QueryStatus.SUCCESS;
815         String modifier = null;
816
817         HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
818         if(resource.contains(":")) {
819             modifier = resource.split(":")[1];
820         }
821
822         try {
823             AAIRequest request = AAIRequest.createRequest(resource, nameValues);
824             if(request == null) {
825                 return QueryStatus.FAILURE;
826             }
827
828             Map<String, String> params = new HashMap<>();
829
830             request.processRequestPathValues(nameValues);
831             if(nameValues.containsKey("prefix")){
832                 Map<String, String> tmpParams = ctxGetBeginsWith(ctx, nameValues.get("prefix"));
833                 if(!tmpParams.isEmpty()) {
834                     params.putAll(tmpParams);
835                 }
836                 if("named-query".equals(resource))
837                     request.setRequestObject(extractNamedQueryDataFromQueryPrefix(nameValues, params));
838             }
839             String rv = getExecutor().get(request);
840
841             retval = processResponseData(rv, resource, request, prefix,  ctx, nameValues, modifier);
842
843         } catch(AAIServiceException aaiexc) {
844             int errorCode = aaiexc.getReturnCode();
845             ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
846             if(errorCode >= 300) {
847                 ctx.setAttribute(prefix + ".error.http.response-code",
848                         Integer.toString(aaiexc.getReturnCode()));
849             }
850
851             if(aaiexc.getReturnCode() == 404)
852                 return QueryStatus.NOT_FOUND;
853
854             return QueryStatus.FAILURE;
855         } catch (Exception exc) {
856             getLogger().warn("requestGenericVnfData", exc);
857             ctx.setAttribute(prefix + ".error.message", exc.getMessage());
858             return QueryStatus.FAILURE;
859         }
860
861         return retval;
862     }
863
864     public QueryStatus processResponseData(String rv, String resource, AAIRequest request, String prefix,  SvcLogicContext ctx, HashMap<String, String> nameValues, String modifier) throws JsonParseException, JsonMappingException, IOException, AAIServiceException
865     {
866         Object response;
867
868             if(rv == null) {
869                 return QueryStatus.NOT_FOUND;
870             }
871
872             response = request.jsonStringToObject(rv);
873             if(response == null) {
874                 return QueryStatus.NOT_FOUND;
875             }
876
877             if("generic-query".equals(resource)) {
878                 SearchResults rd = SearchResults.class.cast(response);
879                 List<ResultData> rdList = rd.getResultData();
880                 if(rdList == null || rdList.isEmpty()) {
881                     return QueryStatus.NOT_FOUND;
882                 }
883                 ResultData rDatum = rdList.get(0);
884                 nameValues.put("selflink", rDatum.getResourceLink());
885                 AAIRequest req2 = AAIRequest.createRequest(rDatum.getResourceType(), nameValues);
886                 req2.processRequestPathValues(nameValues);
887                 rv = getExecutor().get(req2);
888                 if(rv == null) {
889                     return QueryStatus.NOT_FOUND;
890                 }
891
892                 response = req2.jsonStringToObject(rv);
893                 if(response == null) {
894                     return QueryStatus.NOT_FOUND;
895                 }
896             }
897
898             if("named-query".equals(resource)) {
899                 InventoryResponseItems rd = InventoryResponseItems.class.cast(response);
900                 List<InventoryResponseItem> iRIlist = rd.getInventoryResponseItem();
901                 if(iRIlist == null || iRIlist.isEmpty()) {
902                     return QueryStatus.NOT_FOUND;
903                 }
904             }
905
906             if("nodes-query".equals(resource)) {
907                 SearchResults rd = SearchResults.class.cast(response);
908                 List<ResultData> rdList = rd.getResultData();
909                 if(rdList == null || rdList.isEmpty()) {
910                     return QueryStatus.NOT_FOUND;
911                 }
912                 ResultData rDatum = rdList.get(0);
913                 response = rDatum;
914             }
915
916         if("formatted-query".equals(resource) || "custom-query".equals(resource)) {
917             FormattedQueryResultList rd = FormattedQueryResultList.class.cast(response);
918             List<Result> iRIlist = rd.getResults();
919             if(iRIlist == null || iRIlist.isEmpty()) {
920                 return QueryStatus.NOT_FOUND;
921             }
922         }
923
924         // process relationship list
925         // this is a temporary soluton to address the realationship handling changes added in Release 17.07
926         try {
927             Class<?> clazz = response.getClass();
928             Method getter = clazz.getMethod("getRelationshipList");
929             Object obj = getter.invoke(response);
930             if(obj != null && obj instanceof RelationshipList) {
931                 RelationshipList list = RelationshipList.class.cast(obj);
932                 AAIServiceUtils.populateRelationshipDataFromPath(list);
933             }
934         } catch(Exception exc) {
935             getLogger().debug("Retrofiting relationship data: " + exc.getMessage());
936         }
937
938             String preFix;
939             if(prefix == null || prefix.isEmpty()) {
940                 preFix = "";
941             } else {
942                 preFix = prefix + ".";
943             }
944
945             Map<String,Object> props = objectToProperties(response);
946             Set<String> keys = props.keySet();
947             for(String theKey: keys) {
948                 if(getLogger().isTraceEnabled())
949                     getLogger().trace(theKey);
950
951                 Object value = props.get(theKey);
952                 if(value == null)
953                     continue;
954                 Object type = value.getClass();
955                 if(value instanceof String) {
956                     ctx.setAttribute(preFix + theKey, value.toString());
957                     continue;
958                 }
959                 if(value instanceof Boolean) {
960                     ctx.setAttribute(preFix + theKey, value.toString());
961                     continue;
962                 }
963                 if(value instanceof Integer) {
964                     ctx.setAttribute(preFix + theKey, value.toString());
965                     continue;
966                 }
967                 if(value instanceof Long) {
968                     ctx.setAttribute(preFix + theKey, value.toString());
969                     continue;
970                 }
971
972                 if(value instanceof ArrayList) {
973                     ArrayList<?> array = ArrayList.class.cast(value);
974                     for(int i = 0; i < array.size(); i++) {
975                         writeList(array, String.format("%s.%s", prefix, theKey), ctx);
976                     }
977                     continue;
978                 }
979
980                 if("relationship-list".equals(theKey)){
981                     Map<String, Object> relationshipList = (Map<String, Object>)value;
982                     // we are interested in seeing just the selected relationship
983                     if(theKey.equals(modifier)) {
984                         List<?> relationships = (List<?>)relationshipList.get("relationship");
985                         if(relationships != null && !relationships.isEmpty()) {
986
987                             List newRelationships = new LinkedList();
988                             newRelationships.addAll(relationships);
989
990                             for(Object obj : newRelationships){
991                                 if(obj instanceof Map<?, ?>) {
992                                     Map<?, ?> relProperties = (Map<?, ?>)obj;
993                                     if(relProperties.containsKey("related-to")) {
994                                         Object relPropsRelatedTo = relProperties.get("related-to");
995
996                                         String relatedTo = nameValues.get("related_to");
997                                         if(relatedTo != null) {
998                                             relatedTo = relatedTo.trim().replace("'", "").replace("$", "").replace("'", "");
999                                             if(!relatedTo.equals(relPropsRelatedTo)) {
1000                                                 relationships.remove(relProperties);
1001                                             }
1002                                             continue;
1003                                         } else {
1004                                             continue;
1005                                         }
1006                                     }
1007                                 }
1008                             }
1009                         }
1010                     }
1011                     writeMap(relationshipList, String.format("%s.%s", prefix, theKey), ctx);
1012                     continue;
1013                 }
1014
1015                 if(value instanceof Map) {
1016                     Map<String, Object> subnetsList = (Map<String, Object>)value;
1017                     writeMap(subnetsList, String.format("%s.%s", prefix, theKey), ctx);
1018                     continue;
1019                 }
1020
1021             }
1022         return QueryStatus.SUCCESS;
1023     }
1024
1025
1026     public QueryStatus newModelBackupRequest(String resource,  Map<String, String> params,  String prefix,  SvcLogicContext ctx) {
1027
1028         QueryStatus retval = QueryStatus.SUCCESS;
1029         HashMap<String, String> nameValues = new HashMap<>();
1030
1031         try {
1032             AAIRequest request = AAIRequest.createRequest(resource, nameValues);
1033             if(request == null) {
1034                 return QueryStatus.FAILURE;
1035             }
1036
1037             boolean argsFound = false;
1038             String[] arguments = request.getArgsList();
1039             for(String name : arguments) {
1040                 String tmpName = name.replaceAll("-", "_");
1041                 String value = params.get(tmpName);
1042                 if(value != null && !value.isEmpty()) {
1043                     value = value.trim().replace("'", "").replace("$", "").replace("'", "");
1044                     request.addRequestProperty(name, value);
1045                     argsFound = true;
1046                 }
1047             }
1048             if(!argsFound) {
1049                 getLogger().warn("No arguments were found. Terminating backup request.");
1050                 return QueryStatus.FAILURE;
1051             }
1052
1053             String rv = getExecutor().get(request);
1054             ctx.setAttribute(prefix, rv);
1055         } catch(AAIServiceException aaiexc) {
1056             if(aaiexc.getReturnCode() == 404)
1057                 return QueryStatus.NOT_FOUND;
1058
1059             return QueryStatus.FAILURE;
1060         } catch (Exception exc) {
1061             getLogger().warn("newModelBackupRequest", exc);
1062             return QueryStatus.FAILURE;
1063         }
1064
1065         return retval;
1066     }
1067
1068     public AAIDatum newModelObjectRequest(String resource,  Map<String, String> params,  String prefix,  SvcLogicContext ctx)
1069             throws AAIServiceException {
1070
1071         AAIDatum response = null;
1072
1073         try {
1074             AAIRequest request = AAIRequest.createRequest(resource, params);
1075             if(request == null) {
1076                 return null;
1077             }
1078
1079             request.processRequestPathValues(params);
1080             String rv = getExecutor().get(request);
1081             response = request.jsonStringToObject(rv);
1082         } catch(AAIServiceException aaiexc) {
1083             throw aaiexc;
1084         } catch (Exception exc) {
1085             getLogger().warn("newModelBackupRequest", exc);
1086             throw new AAIServiceException(exc);
1087         }
1088
1089         return response;
1090     }
1091
1092
1093     @Override
1094     public QueryStatus release(String arg0, String arg1, SvcLogicContext arg2) throws SvcLogicException {
1095         // TODO Auto-generated method stub
1096         throw new SvcLogicException("Method AAIService.release() has not been implemented yet");
1097     }
1098
1099     @Override
1100     public QueryStatus reserve(String arg0, String arg1, String arg2, String arg3, SvcLogicContext arg4)
1101             throws SvcLogicException {
1102         // TODO Auto-generated method stub
1103         throw new SvcLogicException("Method AAIService.reserve() has not been implemented yet");
1104     }
1105
1106     private QueryStatus newModelSave(String resource, boolean force, String key, Map<String, String> params, String prefix, SvcLogicContext ctx) {
1107         getLogger().debug("Executing newModelSave for resource : " + resource);
1108         HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
1109
1110         try {
1111             ArrayList<String> subResources = new ArrayList<>();
1112             Set<String> set = params.keySet();
1113             Map<String, Method> setters = new HashMap<>();
1114             Map<String, Method> getters = new HashMap<>();
1115
1116             // 1. find class
1117             AAIRequest request = AAIRequest.createRequest(resource, nameValues);
1118             Class<? extends AAIDatum> resourceClass = request.getModelClass();
1119             getLogger().debug(resourceClass.getName());
1120             AAIDatum instance = resourceClass.newInstance();
1121
1122             {
1123                 Annotation[] annotations = resourceClass.getAnnotations();
1124                 for(Annotation annotation : annotations) {
1125                     Class<? extends Annotation> anotationType = annotation.annotationType();
1126                     String annotationName = anotationType.getName();
1127
1128                     // 2. find string property setters and getters for the lists
1129                     if("javax.xml.bind.annotation.XmlType".equals(annotationName)){
1130                         XmlType order = (XmlType)annotation;
1131                         String[]  values = order.propOrder();
1132                         for(String value : values) {
1133                             String id = AAIServiceUtils.camelCaseToDashedString(value);
1134                             Field field = resourceClass.getDeclaredField(value);
1135                             Class<?> type = field.getType();
1136                             Method setter = null;
1137                             try {
1138                                 setter = resourceClass.getMethod("set"+StringUtils.capitalize(value), type);
1139                                 if(type.getName().startsWith("java.lang") || "boolean".equals(type.getName()) || "long".equals(type.getName())) {
1140                                     try {
1141                                         setter.setAccessible(true);
1142                                         Object arglist[] = new Object[1];
1143                                         arglist[0] = params.get(id);
1144
1145                                         if(arglist[0] != null) {
1146                                             if(!type.getName().equals("java.lang.String")) {
1147 //                                            getLogger().debug(String.format("Processing %s with parameter %s", types[0].getName(), value));
1148                                                 if("boolean".equals(type.getName())) {
1149                                                     arglist[0] = valueOf(Boolean.class, params.get(id));
1150                                                 } else if("long".equals(type.getName())) {
1151                                                         arglist[0] = valueOf(Long.class, params.get(id));
1152                                                 } else {
1153                                                     arglist[0] = valueOf(type, params.get(id));
1154                                                 }
1155                                             }
1156                                             Object o = setter.invoke(instance, arglist);
1157                                         }
1158                                         set.remove(id);
1159
1160                                     } catch (Exception x) {
1161                                         Throwable cause = x.getCause();
1162                                         getLogger().warn("Failed process for " + resourceClass.getName(), x);
1163                                     }
1164                                 } else if(type.getName().equals("java.util.List")) {
1165                                     List<String> newValues = new ArrayList<>();
1166                                     String length = id+"_length";
1167                                     if(!params.isEmpty() && params.containsKey(length)) {
1168                                         String tmp = params.get(length);
1169                                         int count = Integer.parseInt(tmp);
1170                                         for(int i=0; i<count; i++) {
1171                                             String tmpValue = params.get(String.format("%s[%d]", id, i));
1172                                             newValues.add(tmpValue);
1173                                         }
1174                                         if(!newValues.isEmpty()) {
1175                                             Object o = setter.invoke(instance, newValues);
1176                                         }
1177                                     }
1178                                     set.remove(id);
1179                                 } else {
1180                                     setters.put(id, setter);
1181                                 }
1182                             } catch(Exception exc) {
1183
1184                             }
1185
1186                             Method getter;
1187                             try {
1188                                 getter = resourceClass.getMethod("get"+StringUtils.capitalize(value));
1189                                 if(!type.getName().equals("java.lang.String")) {
1190                                     getters.put(id, getter);
1191                                 }
1192                             } catch(Exception exc) {
1193
1194                             }
1195
1196                         }
1197                         subResources.addAll(Arrays.asList(values));
1198                     }
1199                 }
1200             }
1201
1202             // remove getters that have matching setter
1203             for(String setKey : setters.keySet()) {
1204                 if(getters.containsKey(setKey)) {
1205                     getters.remove(setKey);
1206                 }
1207             }
1208
1209             Set<String> relationshipKeys = new TreeSet<>();
1210             Set<String> vlansKeys = new TreeSet<>();
1211             Set<String> metadataKeys = new TreeSet<>();
1212
1213             for(String attribute : set) {
1214                 String value = params.get(attribute);
1215                 if(attribute.startsWith("relationship-list")) {
1216                     relationshipKeys.add(attribute);
1217                 } else if(attribute.startsWith("vlans")) {
1218                     vlansKeys.add(attribute);
1219                 } else if(attribute.startsWith("metadata")) {
1220                     metadataKeys.add(attribute);
1221                 }
1222             }
1223             // 3. find list property getters
1224             for(String attribute : set) {
1225                 String value = params.get(attribute);
1226                 Method method = getters.get(attribute);
1227                 if(method != null) {
1228                     try {
1229                         method.setAccessible(true);
1230                         Object arglist[] = new Object[0];
1231 //                        arglist[0] = value;
1232                         Class<?>[] types = method.getParameterTypes();
1233                         if(types.length == 0){
1234                             Object o = method.invoke(instance, arglist);
1235                             if(o instanceof ArrayList) {
1236                                 ArrayList<String> values = (ArrayList<String>)o;
1237 //                                getLogger().debug(String.format("Processing %s with parameter %s", types[0].getName(), value));
1238                                 value = value.replace("[", "").replace("]", "");
1239                                 List<String> items = Arrays.asList(value.split("\\s*,\\s*"));
1240                                 for(String s : items) {
1241                                     values.add(s.trim());
1242                                 }
1243                             }
1244                         }
1245                     } catch (Exception x) {
1246                         Throwable cause = x.getCause();
1247                         getLogger().warn("Failed process for " + resourceClass.getName(), x);
1248                     }
1249                 }
1250             }
1251             // 4. Process Relationships
1252             // add relationship list
1253             if( (subResources.contains("relationship-list") || subResources.contains("relationshipList")) &&  !relationshipKeys.isEmpty()) {
1254                 RelationshipList relationshipList = null;
1255                 Object obj = null;
1256                 Method getRelationshipListMethod = null;
1257                 try {
1258                      getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
1259                 } catch(Exception exc) {
1260                     getLogger().debug("Retrofiting relationship data: " + exc.getMessage());
1261                 }
1262
1263                 if(getRelationshipListMethod != null){
1264                     try {
1265                         getRelationshipListMethod.setAccessible(true);
1266                         obj = getRelationshipListMethod.invoke(instance);
1267                     } catch (InvocationTargetException x) {
1268                         Throwable cause = x.getCause();
1269                     }
1270                 }
1271                 if(obj != null && obj instanceof RelationshipList){
1272                     relationshipList = (RelationshipList)obj;
1273                 } else {
1274                     relationshipList = new RelationshipList();
1275                     Method setRelationshipListMethod = resourceClass.getMethod("setRelationshipList", RelationshipList.class);
1276                     if(setRelationshipListMethod != null){
1277                         try {
1278                             setRelationshipListMethod.setAccessible(true);
1279                             Object arglist[] = new Object[1];
1280                             arglist[0] = relationshipList;
1281
1282                             obj = setRelationshipListMethod.invoke(instance, arglist);
1283                         } catch (InvocationTargetException x) {
1284                             Throwable cause = x.getCause();
1285                         }
1286                     }
1287                 }
1288
1289                 List<Relationship> relationships = relationshipList.getRelationship();
1290
1291                 int i = 0;
1292                 while(true){
1293                     String searchKey = "relationship-list.relationship[" + i + "].related-to";
1294                     if(!params.containsKey(searchKey))
1295                         break;
1296                     int j = 0;
1297                     String relatedTo = params.get(searchKey);
1298                     String relatedLinkKey = "relationship-list.relationship[" + i + "].related-link";
1299                     String relatedLink = null;
1300                     if(params.containsKey(relatedLinkKey)) {
1301                         relatedLink = params.get(relatedLinkKey);
1302                     }
1303                     Relationship relationship = new Relationship();
1304                     relationships.add(relationship);
1305                     relationship.setRelatedTo(relatedTo);
1306                     if(relatedLink != null) {
1307                         relationship.setRelatedLink(relatedLink);
1308                     } else {
1309                         Map<String, String> relParams = new HashMap<>();
1310
1311                             while(true) {
1312                                 String searchRelationshipKey = "relationship-list.relationship[" + i + "].relationship-data[" + j + "].relationship-key";
1313                                 String searchRelationshipValue = "relationship-list.relationship[" + i + "].relationship-data[" + j + "].relationship-value";
1314                                     if(!params.containsKey(searchRelationshipKey))
1315                                     break;
1316
1317                                     relParams.put(params.get(searchRelationshipKey), params.get(searchRelationshipValue));
1318                                 j++;
1319                             }
1320                         AAIRequest rlRequest = AAIRequest.createRequest(relatedTo, relParams);
1321                         for(Map.Entry<String,String> entry : relParams.entrySet()) {
1322                             rlRequest.addRequestProperty(entry.getKey(), entry.getValue());
1323                         }
1324                         String path = rlRequest.updatePathDataValues(null);
1325                         relationship.setRelatedLink(path);
1326                     }
1327                                 {
1328                                         int k = 0;
1329                                         // process related to properties
1330                                         Map<String, String> relParams = new HashMap<String, String>();
1331
1332                                         while(true) {
1333                                                 String searchRelatedToKey = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-key";
1334                                                 String searchRelatedToValue = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-value";
1335                                                 if(!params.containsKey(searchRelatedToKey))
1336                                                         break;
1337
1338                                                 RelatedToProperty relDatum = new RelatedToProperty();
1339                                                 relDatum.setPropertyKey(params.get(searchRelatedToKey));
1340                                                 relDatum.setPropertyValue(params.get(searchRelatedToValue));
1341                                                 relationship.getRelatedToProperty().add(relDatum);
1342
1343                                                 relParams.put(params.get(searchRelatedToKey), params.get(searchRelatedToValue));
1344                                                 k++;
1345                                         }
1346                                 }
1347                     i++;
1348                 }
1349             }
1350
1351             // 4. vlans
1352             if(subResources.contains("vlans") &&  !vlansKeys.isEmpty()) {
1353                 Object obj = null;
1354                 Vlans vlanList = null;
1355                 Method getVLansMethod = resourceClass.getMethod("getVlans");
1356                 if(getVLansMethod != null){
1357                     try {
1358                         getVLansMethod.setAccessible(true);
1359                         obj = getVLansMethod.invoke(instance);
1360                     } catch (InvocationTargetException x) {
1361                         Throwable cause = x.getCause();
1362                     }
1363                 }
1364                 if(obj != null && obj instanceof Vlans){
1365                     vlanList = (Vlans)obj;
1366                 } else {
1367                     vlanList = new Vlans();
1368                     Method setVlansMethod = resourceClass.getMethod("setVlans", Vlans.class);
1369                     if(setVlansMethod != null){
1370                         try {
1371                             setVlansMethod.setAccessible(true);
1372                             Object arglist[] = new Object[1];
1373                             arglist[0] = vlanList;
1374
1375                             obj = setVlansMethod.invoke(instance, arglist);
1376                         } catch (InvocationTargetException x) {
1377                             Throwable cause = x.getCause();
1378                         }
1379                     }
1380                 }
1381
1382                 int i = 0;
1383                 while(true){
1384                     String searchKey = "vlans.vlan[" + i + "].vlan-interface";
1385                     if(!params.containsKey(searchKey))
1386                         break;
1387
1388                     String vlanInterface = params.get("vlans.vlan[" + i + "].vlan-interface");
1389                     String vlanIdInner    = params.get("vlans.vlan[" + i + "].vlan-id-inner");
1390                     String vlanIdOute     = params.get("vlans.vlan[" + i + "].vlan-id-outer");
1391                     String speedValue     = params.get("vlans.vlan[" + i + "].speed-value");
1392                     String speedUnits     = params.get("vlans.vlan[" + i + "].speed-units");
1393
1394                     Vlan vlan = new Vlan();
1395                     vlan.setVlanInterface(vlanInterface);
1396
1397                     if(vlanIdInner != null) {
1398                     Long iVlanIdInner = Long.parseLong(vlanIdInner);
1399                     vlan.setVlanIdInner(iVlanIdInner);
1400                     }
1401
1402                     if(vlanIdOute != null) {
1403                         Long iVlanIdOuter = Long.parseLong(vlanIdOute);
1404                     vlan.setVlanIdOuter(iVlanIdOuter);
1405                     }
1406
1407                     if(speedValue != null) {
1408                     vlan.setSpeedValue(speedValue);
1409                     vlan.setSpeedUnits(speedUnits);
1410                     }
1411
1412                     vlanList.getVlan().add(vlan);
1413                     i++;
1414                 }
1415             }
1416
1417             // 5. metadata
1418             if(subResources.contains("metadata") &&  !metadataKeys.isEmpty()) {
1419                 Object obj = null;
1420                 Metadata metadataList = null;
1421                 Method getMetadataMethod = resourceClass.getMethod("getMetadata");
1422                 if(getMetadataMethod != null){
1423                     try {
1424                         getMetadataMethod.setAccessible(true);
1425                         obj = getMetadataMethod.invoke(instance);
1426                     } catch (InvocationTargetException x) {
1427                         Throwable cause = x.getCause();
1428                     }
1429                 }
1430                 if(obj != null && obj instanceof Metadata){
1431                     metadataList = (Metadata)obj;
1432                 } else {
1433                     metadataList = new Metadata();
1434                     Method setMetadataMethod = resourceClass.getMethod("setMetadata", Metadata.class);
1435                     if(setMetadataMethod != null){
1436                         try {
1437                             setMetadataMethod.setAccessible(true);
1438                             Object arglist[] = new Object[1];
1439                             arglist[0] = metadataList;
1440
1441                             obj = setMetadataMethod.invoke(instance, arglist);
1442                         } catch (InvocationTargetException x) {
1443                             Throwable cause = x.getCause();
1444                         }
1445                     }
1446                 }
1447
1448                 if(metadataList.getMetadatum() == null) {
1449 //                    metadataList.setMetadatum(new ArrayList<Metadatum>());
1450                 }
1451
1452                 // process data
1453                 int i = 0;
1454                 while(true){
1455                     String metaKey = "metadata.metadatum[" + i + "].meta-key";
1456                     if(!params.containsKey(metaKey))
1457                         break;
1458
1459                     String metaValue = params.get("metadata.metadatum[" + i + "].meta-value");
1460
1461                     Metadatum vlan = new Metadatum();
1462                     vlan.setMetaname(metaKey);
1463                     vlan.setMetaval(metaValue);
1464
1465                     metadataList.getMetadatum().add(vlan);
1466                     i++;
1467                 }
1468
1469             }
1470
1471
1472             // 6. Prepare AAI request
1473             String[] args = request.getArgsList();
1474             for(String arg : args) {
1475                 String modifiedKey = arg.replaceAll("-", "_");
1476                 if(nameValues.containsKey(modifiedKey)) {
1477                     String argValue = nameValues.get(modifiedKey);
1478                     if(argValue != null) argValue = argValue.trim().replace("'", "").replace("$", "").replace("'", "");
1479                     request.addRequestProperty(arg, argValue);
1480                 }
1481             }
1482
1483             request.processRequestPathValues(nameValues);
1484             request.setRequestObject(instance);
1485                 Object response = getExecutor().post(request);
1486                 if(request.expectsDataFromPUTRequest()){
1487                     if(response != null && response instanceof String) {
1488                         String rv = response.toString();
1489                         QueryStatus retval = processResponseData(rv, resource, request, prefix,  ctx, nameValues, null);
1490                         getLogger().debug("newModelSave - returning " + retval.toString());
1491                         return retval;
1492                     }
1493                 }
1494
1495         } catch(AAIServiceException exc){
1496             ctx.setAttribute(prefix + ".error.message", exc.getMessage());
1497             int returnCode = exc.getReturnCode();
1498             if(returnCode >= 300) {
1499                 ctx.setAttribute(prefix + ".error.http.response-code",
1500                         Integer.toString(exc.getReturnCode()));
1501             }
1502
1503             if(returnCode == 400 || returnCode == 412)
1504                 return QueryStatus.FAILURE;
1505             else if(returnCode == 404)
1506                 return QueryStatus.NOT_FOUND;
1507             else {
1508                 getLogger().warn("Failed newModelSave - returning FAILURE", exc);
1509                 return QueryStatus.FAILURE;
1510             }
1511         } catch(Exception exc){
1512             getLogger().warn("Failed newModelSave - returning FAILURE", exc);
1513             ctx.setAttribute(prefix + ".error.message", exc.getMessage());
1514             return QueryStatus.FAILURE;
1515         }
1516
1517         getLogger().debug("newModelSave - returning SUCCESS");
1518         return QueryStatus.SUCCESS;
1519     }
1520
1521     private QueryStatus newModelProcessRelationshipList(Object instance, Map<String, String> params, String prefix, SvcLogicContext ctx) throws Exception {
1522
1523         Class resourceClass = instance.getClass();
1524
1525         Set<String> relationshipKeys = new TreeSet<>();
1526
1527         Set<String> set = params.keySet();
1528
1529         for(String attribute : set) {
1530             String value = params.get(attribute);
1531
1532             if(attribute.startsWith("relationship-list")) {
1533                 relationshipKeys.add(attribute);
1534             }
1535         }
1536
1537         // 3. Process Relationships
1538         // add relationship list
1539         if(!relationshipKeys.isEmpty()) {
1540             RelationshipList relationshipList;
1541             Object obj = null;
1542             Method getRelationshipListMethod = null;
1543             try {
1544                  getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
1545             } catch(Exception exc) {
1546                 getLogger().debug("Retrofiting relationship data: " + exc.getMessage());
1547             }
1548             if(getRelationshipListMethod != null){
1549                 try {
1550                     getRelationshipListMethod.setAccessible(true);
1551                     obj = getRelationshipListMethod.invoke(instance);
1552                 } catch (InvocationTargetException x) {
1553                     Throwable cause = x.getCause();
1554                 }
1555             }
1556             if(obj != null && obj instanceof RelationshipList){
1557                 relationshipList = (RelationshipList)obj;
1558             } else {
1559                 relationshipList = new RelationshipList();
1560                 Method setRelationshipListMethod = resourceClass.getMethod("setRelationshipList", RelationshipList.class);
1561                 if(setRelationshipListMethod != null){
1562                     try {
1563                         setRelationshipListMethod.setAccessible(true);
1564                         Object arglist[] = new Object[1];
1565                         arglist[0] = relationshipList;
1566
1567                         obj = setRelationshipListMethod.invoke(instance, arglist);
1568                     } catch (InvocationTargetException x) {
1569                         Throwable cause = x.getCause();
1570                     }
1571                 }
1572             }
1573
1574             boolean createdNewRelationships = false;
1575             List<Relationship> relationships = relationshipList.getRelationship();
1576             if(relationships == null) {
1577                 relationships = new ArrayList<>();
1578                 createdNewRelationships = true;
1579             }
1580
1581             int i = 0;
1582             while(true){
1583                 String searchKey = "relationship-list.relationship[" + i + "].related-to";
1584                 if(!params.containsKey(searchKey))
1585                     break;
1586
1587                 String relatedTo = params.get(searchKey);
1588                 String relatedLinkKey = "relationship-list.relationship[" + i + "].related-link";
1589                 String relatedLink = null;
1590                 if(params.containsKey(relatedLinkKey)) {
1591                     relatedLink = params.get(relatedLinkKey);
1592                 }
1593
1594                                 Relationship relationship = new Relationship();
1595                                 relationships.add(relationship);
1596                                 relationship.setRelatedTo(relatedTo);
1597                                 if (relatedLink != null) {
1598                                         relationship.setRelatedLink(relatedLink);
1599                                 } else {
1600                                         Map<String, String> relParams = new HashMap<>();
1601                                         int j = 0;
1602
1603                                         while (true) {
1604                                                 String searchRelationshipKey = "relationship-list.relationship[" + i + "].relationship-data["
1605                                                                 + j + "].relationship-key";
1606                                                 String searchRelationshipValue = "relationship-list.relationship[" + i + "].relationship-data["
1607                                                                 + j + "].relationship-value";
1608                                                 if (!params.containsKey(searchRelationshipKey))
1609                                                         break;
1610
1611                                                 RelationshipData relDatum = new RelationshipData();
1612                                                 relDatum.setRelationshipKey(params.get(searchRelationshipKey));
1613                                                 relDatum.setRelationshipValue(params.get(searchRelationshipValue));
1614                                                 relationship.getRelationshipData().add(relDatum);
1615
1616                                                 relParams.put(params.get(searchRelationshipKey), params.get(searchRelationshipValue));
1617                                                 j++;
1618                                         }
1619                                         AAIRequest rlRequest = AAIRequest.createRequest(relatedTo, relParams);
1620                                         for (Map.Entry<String, String> entry : relParams.entrySet()) {
1621                                                 rlRequest.addRequestProperty(entry.getKey(), entry.getValue());
1622                                         }
1623                                         String path = rlRequest.updatePathDataValues(null);
1624                                         relationship.setRelatedLink(path);
1625                                 }
1626                                 {
1627                                         int k = 0;
1628                                         // process related to properties
1629                                         Map<String, String> relParams = new HashMap<String, String>();
1630
1631                                         while(true) {
1632                                                 String searchRelatedToKey = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-key";
1633                                                 String searchRelatedToValue = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-value";
1634                                                 if(!params.containsKey(searchRelatedToKey))
1635                                                         break;
1636
1637                                                 RelatedToProperty relDatum = new RelatedToProperty();
1638                                                 relDatum.setPropertyKey(params.get(searchRelatedToKey));
1639                                                 relDatum.setPropertyValue(params.get(searchRelatedToValue));
1640                                                 relationship.getRelatedToProperty().add(relDatum);
1641
1642                                                 relParams.put(params.get(searchRelatedToKey), params.get(searchRelatedToValue));
1643                                                 k++;
1644                                         }
1645                                 }
1646
1647                                 i++;
1648                         }
1649         }
1650
1651         return QueryStatus.SUCCESS;
1652     }
1653
1654     private QueryStatus newModelProcessMetadata(Object instance, Map<String, String> params, String prefix, SvcLogicContext ctx) throws Exception {
1655
1656         if (!(instance instanceof ServiceInstance) && !(instance instanceof Image)) {
1657             throw new IllegalArgumentException("request is not applicable for selected request");
1658         }
1659
1660         Class resourceClass = instance.getClass();
1661         Set<String> metadataKeys = new TreeSet<String>();
1662         Set<String> set = params.keySet();
1663         for(String attribute : set) {
1664             if(attribute.startsWith("metadata")) {
1665                 metadataKeys.add(attribute);
1666             }
1667         }
1668
1669         // 3. Process Metadata
1670         // add metadata
1671         if(!metadataKeys.isEmpty()) {
1672             Metadata metadata = null;
1673             Object obj = null;
1674             Method getMetadataMethod = resourceClass.getMethod("getMetadata");
1675             if(getMetadataMethod != null){
1676                 try {
1677                     getMetadataMethod.setAccessible(true);
1678                     obj = getMetadataMethod.invoke(instance);
1679                 } catch (InvocationTargetException x) {
1680                     Throwable cause = x.getCause();
1681                 }
1682             }
1683             if(obj != null && obj instanceof Metadata){
1684                 metadata = (Metadata)obj;
1685             } else {
1686                 metadata = new Metadata();
1687                 Method setMetadataMethod = resourceClass.getMethod("setMetadata", Metadata.class);
1688                 if(setMetadataMethod != null){
1689                     try {
1690                         setMetadataMethod.setAccessible(true);
1691                         setMetadataMethod.invoke(instance, metadata);
1692                     } catch (InvocationTargetException x) {
1693                     }
1694                 }
1695             }
1696
1697             List<Metadatum> metadatumList = metadata.getMetadatum();
1698             int i = 0;
1699             while(true){
1700                 String metaNameKey = "metadata.metadatum[" + i + "].metaname";
1701                 String metaValueKey = "metadata.metadatum[" + i + "].metaval";
1702                 if(!params.containsKey(metaNameKey) || !params.containsKey(metaValueKey))
1703                     break;
1704
1705                 Metadatum metadatum = new Metadatum();
1706                 metadatum.setMetaname(params.get(metaNameKey));
1707                 metadatum.setMetaval(params.get(metaValueKey));
1708                 metadatumList.add(metadatum);
1709
1710                 i++;
1711             }
1712         }
1713
1714         return QueryStatus.SUCCESS;
1715     }
1716
1717     private Relationship findRelationship(List<Relationship> relationships, String relatedTo) {
1718         if(relatedTo == null)
1719             return null;
1720
1721         for(Relationship relationship : relationships) {
1722             if(relationship.getRelatedTo().equals(relatedTo)){
1723                 return relationship;
1724             }
1725         }
1726         return null;
1727     }
1728
1729
1730     public QueryStatus backup(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
1731         String resource = params.get("resource").toLowerCase();
1732         String prefix = params.get("data-key");
1733
1734         HashMap<String, String> nameValues = new HashMap<>();
1735         if(AAIRequest.createRequest(resource, nameValues) != null) {
1736
1737             try {
1738                 return newModelBackupRequest(resource, params, prefix, ctx);
1739             } catch (Exception exc) {
1740                 getLogger().warn("Failed backup - returning FAILURE", exc);
1741                 return QueryStatus.FAILURE;
1742             }
1743         }
1744
1745         return QueryStatus.NOT_FOUND;
1746     }
1747
1748     @Override
1749     public QueryStatus restore(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
1750
1751         QueryStatus retval = QueryStatus.SUCCESS;
1752         String resource = params.get("resource").toLowerCase();
1753         String prefix = params.get("data-key");
1754
1755         HashMap<String, String> nameValues = new HashMap<>();
1756         if(AAIRequest.createRequest(resource, nameValues) != null) {
1757
1758             try {
1759                 retval = newModelBackupRequest(resource, params, "tmpRestore", ctx);
1760                 if(retval == QueryStatus.SUCCESS) {
1761                     String current_json = ctx.getAttribute("tmpRestore");
1762                     ctx.  setAttribute("tmpRestore", null);
1763
1764                     String snapshot_json = ctx.getAttribute(prefix);
1765                 }
1766             } catch (Exception exc) {
1767                 getLogger().warn("Failed restore - returning FAILURE", exc);
1768                 return QueryStatus.FAILURE;
1769             }
1770         }
1771
1772         return QueryStatus.NOT_FOUND;
1773     }
1774
1775     protected Map<String, Object> objectToProperties(Object object) {
1776         ObjectMapper mapper = AAIService.getObjectMapper();
1777         return mapper.convertValue(object, Map.class);
1778     }
1779
1780     static <T> T valueOf(Class<T> klazz, String arg) {
1781         Exception cause = null;
1782         T ret = null;
1783         try {
1784             ret = klazz.cast(klazz.getDeclaredMethod("valueOf", String.class).invoke(null, arg));
1785         } catch (NoSuchMethodException exc) {
1786             LoggerFactory.getLogger(AAIService.class).warn("Wrong data type", exc);
1787             ret = klazz.cast(arg);
1788         } catch (IllegalAccessException e) {
1789             cause = e;
1790         } catch (InvocationTargetException e) {
1791             cause = e;
1792         }
1793         if (cause == null) {
1794             return ret;
1795         } else {
1796             throw new IllegalArgumentException(cause);
1797         }
1798     }
1799
1800     private QueryStatus processDeleteRelationshipList(String resource, String key, SvcLogicContext ctx, HashMap<String, String> nameValues) {
1801         try {
1802             AAIRequest request = AAIRequest.createRequest(resource, nameValues);
1803             if(request == null) {
1804                 return QueryStatus.FAILURE;
1805             }
1806
1807             request.processRequestPathValues(nameValues);
1808             URL url = request.getRequestUrl("GET", null);
1809
1810             Class resourceClass = request.getModelClass();
1811             Object instance = getResource(url.toString(), resourceClass);
1812             if(instance == null)
1813                 return QueryStatus.NOT_FOUND;
1814
1815             // get resource version
1816             String resourceVersion = null;
1817             Method getResourceVersionMethod = resourceClass.getMethod("getResourceVersion");
1818             if(getResourceVersionMethod != null){
1819                 try {
1820                     getResourceVersionMethod.setAccessible(true);
1821                     Object object = getResourceVersionMethod.invoke(instance);
1822                     if(object != null)
1823                         resourceVersion = object.toString();
1824                 } catch (InvocationTargetException x) {
1825                     Throwable cause = x.getCause();
1826                 }
1827             }
1828
1829             RelationshipList relationshipList = null;
1830             Object obj = null;
1831             Method getRelationshipListMethod = null;
1832             try {
1833                  getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
1834             } catch(Exception exc) {
1835                 getLogger().debug("Retrofiting relationship data: " + exc.getMessage());
1836             }
1837             if(getRelationshipListMethod != null){
1838                 try {
1839                     getRelationshipListMethod.setAccessible(true);
1840                     obj = getRelationshipListMethod.invoke(instance);
1841                 } catch (InvocationTargetException x) {
1842                     Throwable cause = x.getCause();
1843                 }
1844             }
1845             if(obj != null && obj instanceof RelationshipList){
1846                 relationshipList = (RelationshipList)obj;
1847             } else {
1848                 getLogger().debug("No relationships found to process.");
1849                 return QueryStatus.NOT_FOUND;
1850             }
1851
1852             if(relationshipList.getRelationship() == null || relationshipList.getRelationship().isEmpty()) {
1853                 return QueryStatus.NOT_FOUND;
1854             }
1855             String relatedTo = nameValues.get("related_to");
1856             if(relatedTo == null) {
1857                 return QueryStatus.FAILURE;
1858             }
1859
1860             relatedTo = relatedTo.replaceAll("_", "-");
1861
1862             String relatedLink = nameValues.get("relationship.related_link");
1863             if(relatedLink != null) {
1864                 relatedLink = URLDecoder.decode(relatedLink, "UTF-8");
1865             }
1866
1867             List<Relationship> relationships = relationshipList.getRelationship();
1868             List<Relationship> relationshipsToDelete = new LinkedList<>();
1869
1870             for(Relationship relationship : relationships) {
1871                 if(relatedTo.equals(relationship.getRelatedTo())) {
1872                     if(relatedLink != null) {
1873                         if(relationship.getRelatedLink() != null ) {
1874                             String localRelatedLink = relationship.getRelatedLink();
1875                             localRelatedLink = URLDecoder.decode(localRelatedLink, "UTF-8");
1876                             if(localRelatedLink.endsWith(relatedLink)) {
1877                                 getLogger().debug(String.format("Found relationship of '%s' to keyword '%s'", relationship.getRelatedTo(),  relatedTo));
1878                                 relationshipsToDelete.add(relationship);
1879                         }
1880                     }
1881                     } else {
1882                     getLogger().debug(String.format("Found relationship of '%s' to keyword '%s'", relationship.getRelatedTo(),  relatedTo));
1883                     relationshipsToDelete.add(relationship);
1884                 }
1885             }
1886             }
1887             if(relationshipsToDelete == null || relationshipsToDelete.isEmpty()) {
1888                 getLogger().info(String.format("Relationship has not been found for %s", key));
1889                 return QueryStatus.NOT_FOUND;
1890             }
1891
1892             String path = url.toString();
1893             path = path + "/relationship-list/relationship";
1894             URL deleteUrl = new URL(path);
1895
1896             ObjectMapper mapper = AAIService.getObjectMapper();
1897
1898             boolean cumulativeResponse = true;
1899
1900             for(Relationship targetRelationship : relationshipsToDelete) {
1901                 String json_text = mapper.writeValueAsString(targetRelationship);
1902                 boolean response = deleteList(deleteUrl, json_text);
1903                 if(!response)
1904                     cumulativeResponse = response;
1905
1906             }
1907
1908             if(!cumulativeResponse)
1909                 return QueryStatus.FAILURE;
1910
1911             return QueryStatus.SUCCESS;
1912
1913         } catch(Exception exc) {
1914             getLogger().warn("processDelete", exc);
1915             return QueryStatus.FAILURE;
1916         }
1917     }
1918
1919     private QueryStatus processDeleteMetadata(String resource, String key, SvcLogicContext ctx, HashMap<String, String> nameValues) {
1920         try {
1921             AAIRequest request = AAIRequest.createRequest(resource, nameValues);
1922             if(request == null) {
1923                 return QueryStatus.FAILURE;
1924             }
1925
1926             request.processRequestPathValues(nameValues);
1927             URL url = request.getRequestUrl("GET", null);
1928
1929             Class resourceClass = request.getModelClass();
1930             Object instance = getResource(url.toString(), resourceClass);
1931
1932             // get resource version
1933             String resourceVersion = null;
1934             Method getResourceVersionMethod = resourceClass.getMethod("getResourceVersion");
1935             if(getResourceVersionMethod != null){
1936                 try {
1937                     getResourceVersionMethod.setAccessible(true);
1938                     resourceVersion = (String) getResourceVersionMethod.invoke(instance);
1939                 } catch (InvocationTargetException x) {
1940                 }
1941             }
1942
1943             Metadata metadata = null;
1944             Object obj = null;
1945             Method getMetadataMethod = resourceClass.getMethod("getMetadata");
1946             if(getMetadataMethod != null){
1947                 try {
1948                     getMetadataMethod.setAccessible(true);
1949                     obj = getMetadataMethod.invoke(instance);
1950                 } catch (InvocationTargetException x) {
1951                     Throwable cause = x.getCause();
1952                 }
1953             }
1954             if(obj != null && obj instanceof Metadata){
1955                 metadata = (Metadata)obj;
1956             } else {
1957                 getLogger().debug("No metadata found to process.");
1958                 return QueryStatus.NOT_FOUND;
1959             }
1960
1961             if(metadata.getMetadatum() == null || metadata.getMetadatum().isEmpty()) {
1962                 return QueryStatus.NOT_FOUND;
1963             }
1964
1965             List<Metadatum> metadatumList = metadata.getMetadatum();
1966             Metadatum metadatumToDelete = null;
1967
1968             final String metaname = nameValues.get("metaname");
1969
1970             for(Metadatum metadatum : metadatumList) {
1971                 getLogger().debug(String.format("Comparing existing metadatum of '%s' to keyword '%s'", metadatum.getMetaname(),  metaname));
1972                 if(metaname.equals(metadatum.getMetaname())) {
1973                     metadatumToDelete = metadatum;
1974                     break;
1975                 }
1976             }
1977             if(metadatumToDelete == null) {
1978                 getLogger().info(String.format("Metadatum has not been found for %s", key));
1979                 return QueryStatus.NOT_FOUND;
1980             }
1981
1982             String path = url.toString();
1983             path = path + "/metadata/metadatum/" + encodeQuery( metadatumToDelete.getMetaname() ) +
1984                     "?resource-version=" + metadatumToDelete.getResourceVersion();
1985             URL deleteUrl = new URL(path);
1986             boolean response = deleteList(deleteUrl, null);
1987
1988             if(!response)
1989                 return QueryStatus.FAILURE;
1990
1991             return QueryStatus.SUCCESS;
1992
1993         } catch(Exception exc) {
1994             getLogger().warn("processDelete", exc);
1995             return QueryStatus.FAILURE;
1996         }
1997     }
1998
1999     protected String encodeQuery(String param) throws UnsupportedEncodingException {
2000         return URLEncoder.encode(param, "UTF-8").replace("+", "%20");
2001     }
2002
2003     static final Map<String, String> ctxGetBeginsWith( SvcLogicContext ctx, String prefix ) {
2004         Map<String, String> tmpPrefixMap = new HashMap<>();
2005
2006         if(prefix == null || prefix.isEmpty()){
2007             return tmpPrefixMap;
2008         }
2009
2010         for( String key : ctx.getAttributeKeySet() ) {
2011             if( key.startsWith(prefix) ) {
2012                 String tmpKey = key.substring(prefix.length() + 1);
2013                 tmpPrefixMap.put( tmpKey, ctx.getAttribute(key));
2014             }
2015         }
2016
2017         Map<String, String> prefixMap = new HashMap<>();
2018         Pattern p = Pattern.compile(".*\\[\\d\\]");
2019
2020         SortedSet<String> keys = new TreeSet(tmpPrefixMap.keySet () );
2021         for(String key : keys) {
2022             Matcher m = p.matcher(key);
2023             if(m.matches()) {
2024                 continue;
2025             } else if(key.endsWith("_length")) {
2026                 String listKey = key.substring(0, key.indexOf("_length"));
2027                 int max = Integer.parseInt(tmpPrefixMap.get(key));
2028
2029                 ArrayList<String> data = new ArrayList<>();
2030                 for(int x = 0; x < max; x++){
2031                     String tmpKey = String.format("%s[%d]", listKey, x);
2032                     String tmpValue = tmpPrefixMap.get(tmpKey);
2033                     if(tmpValue != null && !tmpValue.isEmpty()) {
2034                         data.add(tmpValue);
2035                     }
2036                 }
2037                 if(!data.isEmpty()) {
2038                     prefixMap.put(listKey, data.toString());
2039                 } else {
2040                     prefixMap.put(key, tmpPrefixMap.get(key));
2041                 }
2042             } else {
2043                 prefixMap.put(key, tmpPrefixMap.get(key));
2044             }
2045         }
2046
2047         return prefixMap;
2048     }
2049
2050     /**
2051     */
2052     protected NamedQueryData extractNamedQueryDataFromQueryPrefix(HashMap<String, String> nameValues, Map<String, String> parms) {
2053         if(parms.isEmpty()) {
2054             return null;
2055         }
2056
2057         NamedQueryData data = new NamedQueryData();
2058
2059         // query parameters
2060         if(data.getQueryParameters() == null) {
2061             data.setQueryParameters(new QueryParameters());
2062         }
2063         String namedQueryUuid = nameValues.get("named-query-uuid".replaceAll("-", "_"));
2064         if(namedQueryUuid == null) {
2065             namedQueryUuid = parms.get("query-parameters.named-query.named-query-uuid");
2066         }
2067         NamedQuery namedQuery = new NamedQuery();
2068         namedQuery.setNamedQueryUuid(namedQueryUuid);
2069         data.getQueryParameters().setNamedQuery(namedQuery);
2070
2071         // instance filters
2072         if(data.getInstanceFilters() == null) {
2073             data.setInstanceFilters(new InstanceFilters());
2074         }
2075
2076
2077         String quantity = parms.get("instance-filters.instance-filter_length");
2078         if(quantity != null && StringUtils.isNumeric(quantity)) {
2079             int max = Integer.parseInt(quantity);
2080             for(int i = 0; i < max; i++) {
2081                 String keyPattern = String.format("instance-filters.instance-filter[%d].", i);
2082                 Set<String> keys = parms.keySet();
2083                 for(String key: keys) {
2084                     if(key.startsWith(keyPattern)){
2085                         String value = parms.get(key);
2086                         String remainder = key.substring(keyPattern.length());
2087                         String[] split = remainder.split("\\.");
2088                         getLogger().debug(String.format("%s", remainder));
2089                         if("logical-link".equals(split[0])) {
2090                             InstanceFilter insf = null;
2091                             if(data.getInstanceFilters().getInstanceFilter().isEmpty()) {
2092                                 insf = new InstanceFilter();
2093                                 data.getInstanceFilters().getInstanceFilter().add(insf);
2094                             } else {
2095                                 insf = data.getInstanceFilters().getInstanceFilter().get(0);
2096                             }
2097                             LogicalLink logicalLink = insf.getLogicalLink();
2098                             if(logicalLink == null) {
2099                                 logicalLink = new LogicalLink();
2100                                 insf.setLogicalLink(logicalLink);
2101                             }
2102
2103                             switch(split[1]) {
2104                             case "link-name":
2105                                 logicalLink.setLinkName(value);
2106                                 break;
2107                             case "link-type":
2108                                 logicalLink.setLinkType(value);
2109                                 break;
2110                             case "operational-state":
2111                                 logicalLink.setOperationalStatus(value);
2112                                 break;
2113                             }
2114
2115                         } else if("pnf".equals(split[0])) {
2116                             Pnf pnf = new Pnf();
2117                             pnf.setPnfName(value);
2118
2119                             InstanceFilter insf = new InstanceFilter();
2120                             insf.setPnf(pnf);
2121                             data.getInstanceFilters().getInstanceFilter().add(insf);
2122
2123                         } else if("service-instance".equals(split[0])) {
2124                             ServiceInstance serviceInstance = new ServiceInstance();
2125                             serviceInstance.setServiceInstanceId(value);
2126
2127                             InstanceFilter insf = new InstanceFilter();
2128                             insf.setServiceInstance(serviceInstance);
2129                             data.getInstanceFilters().getInstanceFilter().add(insf);
2130
2131                         } else if("l3-network".equals(split[0])) {
2132                             L3Network l3Network = new L3Network();
2133                             if("network-role".equals(split[1])) {
2134                                 l3Network.setNetworkRole(value);
2135                             }
2136
2137                             InstanceFilter insf = new InstanceFilter();
2138                             insf.setL3Network(l3Network);
2139                             data.getInstanceFilters().getInstanceFilter().add(insf);
2140                         } else if("generic-vnf".equals(split[0])) {
2141                             GenericVnf vnf = new GenericVnf();
2142                             if("vnf-id".equals(split[1])) {
2143                                 vnf.setVnfId(value);
2144                             }
2145
2146                             InstanceFilter insf = new InstanceFilter();
2147                             insf.setGenericVnf(vnf);
2148                             data.getInstanceFilters().getInstanceFilter().add(insf);
2149                         }
2150                     }
2151                 }
2152             }
2153         }
2154
2155         return data;
2156     }
2157
2158     public abstract <T> T getResource(String key, Class<T> type) throws AAIServiceException ;
2159     protected abstract boolean deleteList(URL url, String caller) throws AAIServiceException;
2160 }