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