Updated XSD Model and path properties
[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 resoourceName = resource;
714             String identifier = null;
715
716             if(resoourceName == null)
717                 return QueryStatus.FAILURE;
718
719             if(resoourceName.contains(":")) {
720                 String[] tokens = resoourceName.split(":");
721                 if(tokens != null && tokens.length > 0) {
722                     resoourceName = tokens[0];
723                     identifier = tokens[1];
724                 }
725             }
726             if("relationship-list".equals(identifier) || "relationshipList".equals(identifier)) {
727 //                RelationshipRequest relationshipRequest = new RelationshipRequest();
728                 if("generic-vnf".equals(resoourceName)){
729                     String vnfId = nameValues.get("vnf_id");
730                     String relatedTo  = nameValues.get("related_to");
731                     vnfId = vnfId.trim().replace("'", "").replace("$", "").replace("'", "");
732                     relatedTo = relatedTo.trim().replace("'", "").replace("$", "").replace("'", "");
733
734                     GenericVnf vnf;
735                     try {
736                         vnf = this.requestGenericVnfData(vnfId);
737                         if(vnf == null)
738                             return QueryStatus.NOT_FOUND;
739                     } catch (AAIServiceException exc) {
740                         getLogger().warn("Failed delete - returning NOT_FOUND", exc);
741                         return QueryStatus.NOT_FOUND;
742                     }
743                     boolean itemRemoved = false;
744                     RelationshipList relationshipList = vnf.getRelationshipList();
745                     List<Relationship> relationships = relationshipList.getRelationship();
746                     List<Relationship> iterableList = new LinkedList<Relationship>(relationships);
747                     for(Relationship relationship : iterableList) {
748                         if(relationship.getRelatedTo().equals(relatedTo)) {
749                             relationships.remove(relationship);
750                             itemRemoved = true;
751                         }
752                     }
753
754                     if(!itemRemoved)
755                         return QueryStatus.NOT_FOUND;
756
757 //                    AAIRequest masterRequest = new GenericVnfRequest();
758 //                    masterRequest.addRequestProperty(GenericVnfRequest.VNF_ID, vnfId);
759 //                    relationshipRequest.addMasterRequest(masterRequest);
760 //                    Map<String, String> attributes = objectToProperties(vnf);
761 //                    try {
762 //                        Boolean result = getExecutor().delete(relationshipRequest, attributes.get(AAIRequest.RESOURCE_VERSION));
763 //                    } catch (AAIServiceException e) {
764 //                        return QueryStatus.FAILURE;
765 //                    }
766
767                     try {
768                         this.postGenericVnfData(vnf.getVnfId(), vnf);
769                     } catch (AAIServiceException exc) {
770                         if(exc.getReturnCode() == 404){
771                             return QueryStatus.NOT_FOUND;
772                         } else {
773                             getLogger().warn("Failed delete - returning FAILURE", exc);
774                             return QueryStatus.FAILURE;
775                         }
776                     }
777                     return QueryStatus.SUCCESS;
778                 }
779             }
780         }
781         return QueryStatus.FAILURE;
782     }
783
784     @Override
785     public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException {
786         return query(resource, false, null, key, prefix, null, ctx);
787     }
788
789     @Override
790     public QueryStatus isAvailable(String arg0, String arg1, String arg2, SvcLogicContext arg3)
791             throws SvcLogicException {
792         // TODO Auto-generated method stub
793         throw new SvcLogicException("Method AAIService.isAvailable() has not been implemented yet");
794     }
795
796     @Override
797     public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx) throws SvcLogicException {
798         // TODO Auto-generated method stub
799         throw new SvcLogicException("Method AAIService.notify() has not been implemented yet");
800     }
801
802 //    @Override
803     public QueryStatus newModelQuery(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx) {
804
805         Object response = null;
806         QueryStatus retval = QueryStatus.SUCCESS;
807         String modifier = null;
808
809         HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
810         if(resource.contains(":")) {
811             modifier = resource.split(":")[1];
812         }
813
814         try {
815             AAIRequest request = AAIRequest.createRequest(resource, nameValues);
816             if(request == null) {
817                 return QueryStatus.FAILURE;
818             }
819
820             Map<String, String> params = new HashMap<>();
821
822             request.processRequestPathValues(nameValues);
823             if(nameValues.containsKey("prefix")){
824                 Map<String, String> tmpParams = ctxGetBeginsWith(ctx, nameValues.get("prefix"));
825                 if(!tmpParams.isEmpty()) {
826                     params.putAll(tmpParams);
827                 }
828                 if("named-query".equals(resource))
829                     request.setRequestObject(extractNamedQueryDataFromQueryPrefix(nameValues, params));
830             }
831             String rv = getExecutor().get(request);
832
833             retval = processResponseData(rv, resource, request, prefix,  ctx, nameValues, modifier);
834
835         } catch(AAIServiceException aaiexc) {
836             int errorCode = aaiexc.getReturnCode();
837             ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
838             if(errorCode >= 300) {
839                 ctx.setAttribute(prefix + ".error.http.response-code",
840                         Integer.toString(aaiexc.getReturnCode()));
841             }
842
843             if(aaiexc.getReturnCode() == 404)
844                 return QueryStatus.NOT_FOUND;
845
846             return QueryStatus.FAILURE;
847         } catch (Exception exc) {
848             getLogger().warn("requestGenericVnfData", exc);
849             ctx.setAttribute(prefix + ".error.message", exc.getMessage());
850             return QueryStatus.FAILURE;
851         }
852
853         return retval;
854     }
855
856     public QueryStatus processResponseData(String rv, String resource, AAIRequest request, String prefix,  SvcLogicContext ctx, HashMap<String, String> nameValues, String modifier) throws JsonParseException, JsonMappingException, IOException, AAIServiceException
857     {
858         Object response;
859
860             if(rv == null) {
861                 return QueryStatus.NOT_FOUND;
862             }
863
864             response = request.jsonStringToObject(rv);
865             if(response == null) {
866                 return QueryStatus.NOT_FOUND;
867             }
868
869             if("generic-query".equals(resource)) {
870                 SearchResults rd = SearchResults.class.cast(response);
871                 List<ResultData> rdList = rd.getResultData();
872                 if(rdList == null || rdList.isEmpty()) {
873                     return QueryStatus.NOT_FOUND;
874                 }
875                 ResultData rDatum = rdList.get(0);
876                 nameValues.put("selflink", rDatum.getResourceLink());
877                 AAIRequest req2 = AAIRequest.createRequest(rDatum.getResourceType(), nameValues);
878                 req2.processRequestPathValues(nameValues);
879                 rv = getExecutor().get(req2);
880                 if(rv == null) {
881                     return QueryStatus.NOT_FOUND;
882                 }
883
884                 response = req2.jsonStringToObject(rv);
885                 if(response == null) {
886                     return QueryStatus.NOT_FOUND;
887                 }
888             }
889
890             if("named-query".equals(resource)) {
891                 InventoryResponseItems rd = InventoryResponseItems.class.cast(response);
892                 List<InventoryResponseItem> iRIlist = rd.getInventoryResponseItem();
893                 if(iRIlist == null || iRIlist.isEmpty()) {
894                     return QueryStatus.NOT_FOUND;
895                 }
896             }
897
898             if("nodes-query".equals(resource)) {
899                 SearchResults rd = SearchResults.class.cast(response);
900                 List<ResultData> rdList = rd.getResultData();
901                 if(rdList == null || rdList.isEmpty()) {
902                     return QueryStatus.NOT_FOUND;
903                 }
904                 ResultData rDatum = rdList.get(0);
905                 response = rDatum;
906             }
907
908         if("formatted-query".equals(resource) || "custom-query".equals(resource)) {
909             FormattedQueryResultList rd = FormattedQueryResultList.class.cast(response);
910             List<Result> iRIlist = rd.getResults();
911             if(iRIlist == null || iRIlist.isEmpty()) {
912                 return QueryStatus.NOT_FOUND;
913             }
914         }
915
916         // process relationship list
917         // this is a temporary soluton to address the realationship handling changes added in Release 17.07
918         try {
919             Class<?> clazz = response.getClass();
920             Method getter = clazz.getMethod("getRelationshipList");
921             Object obj = getter.invoke(response);
922             if(obj != null && obj instanceof RelationshipList) {
923                 RelationshipList list = RelationshipList.class.cast(obj);
924                 AAIServiceUtils.populateRelationshipDataFromPath(list);
925             }
926         } catch(Exception exc) {
927             getLogger().debug("Retrofiting relationship data: " + exc.getMessage());
928         }
929
930             String preFix;
931             if(prefix == null || prefix.isEmpty()) {
932                 preFix = "";
933             } else {
934                 preFix = prefix + ".";
935             }
936
937             Map<String,Object> props = objectToProperties(response);
938             Set<String> keys = props.keySet();
939             for(String theKey: keys) {
940                 if(getLogger().isTraceEnabled())
941                     getLogger().trace(theKey);
942
943                 Object value = props.get(theKey);
944                 if(value == null)
945                     continue;
946                 Object type = value.getClass();
947                 if(value instanceof String) {
948                     ctx.setAttribute(preFix + theKey, value.toString());
949                     continue;
950                 }
951                 if(value instanceof Boolean) {
952                     ctx.setAttribute(preFix + theKey, value.toString());
953                     continue;
954                 }
955                 if(value instanceof Integer) {
956                     ctx.setAttribute(preFix + theKey, value.toString());
957                     continue;
958                 }
959                 if(value instanceof Long) {
960                     ctx.setAttribute(preFix + theKey, value.toString());
961                     continue;
962                 }
963
964                 if(value instanceof ArrayList) {
965                     ArrayList<?> array = ArrayList.class.cast(value);
966                     for(int i = 0; i < array.size(); i++) {
967                         writeList(array, String.format("%s.%s", prefix, theKey), ctx);
968                     }
969                     continue;
970                 }
971
972                 if("relationship-list".equals(theKey)){
973                     Map<String, Object> relationshipList = (Map<String, Object>)value;
974                     // we are interested in seeing just the selected relationship
975                     if(theKey.equals(modifier)) {
976                         List<?> relationships = (List<?>)relationshipList.get("relationship");
977                         if(relationships != null && !relationships.isEmpty()) {
978
979                             List newRelationships = new LinkedList();
980                             newRelationships.addAll(relationships);
981
982                             for(Object obj : newRelationships){
983                                 if(obj instanceof Map<?, ?>) {
984                                     Map<?, ?> relProperties = (Map<?, ?>)obj;
985                                     if(relProperties.containsKey("related-to")) {
986                                         Object relPropsRelatedTo = relProperties.get("related-to");
987
988                                         String relatedTo = nameValues.get("related_to");
989                                         if(relatedTo != null) {
990                                             relatedTo = relatedTo.trim().replace("'", "").replace("$", "").replace("'", "");
991                                             if(!relatedTo.equals(relPropsRelatedTo)) {
992                                                 relationships.remove(relProperties);
993                                             }
994                                             continue;
995                                         } else {
996                                             continue;
997                                         }
998                                     }
999                                 }
1000                             }
1001                         }
1002                     }
1003                     writeMap(relationshipList, String.format("%s.%s", prefix, theKey), ctx);
1004                     continue;
1005                 }
1006
1007                 if(value instanceof Map) {
1008                     Map<String, Object> subnetsList = (Map<String, Object>)value;
1009                     writeMap(subnetsList, String.format("%s.%s", prefix, theKey), ctx);
1010                     continue;
1011                 }
1012
1013             }
1014         return QueryStatus.SUCCESS;
1015     }
1016
1017
1018     public QueryStatus newModelBackupRequest(String resource,  Map<String, String> params,  String prefix,  SvcLogicContext ctx) {
1019
1020         QueryStatus retval = QueryStatus.SUCCESS;
1021         HashMap<String, String> nameValues = new HashMap<>();
1022
1023         try {
1024             AAIRequest request = AAIRequest.createRequest(resource, nameValues);
1025             if(request == null) {
1026                 return QueryStatus.FAILURE;
1027             }
1028
1029             boolean argsFound = false;
1030             String[] arguments = request.getArgsList();
1031             for(String name : arguments) {
1032                 String tmpName = name.replaceAll("-", "_");
1033                 String value = params.get(tmpName);
1034                 if(value != null && !value.isEmpty()) {
1035                     value = value.trim().replace("'", "").replace("$", "").replace("'", "");
1036                     request.addRequestProperty(name, value);
1037                     argsFound = true;
1038                 }
1039             }
1040             if(!argsFound) {
1041                 getLogger().warn("No arguments were found. Terminating backup request.");
1042                 return QueryStatus.FAILURE;
1043             }
1044
1045             String rv = getExecutor().get(request);
1046             ctx.setAttribute(prefix, rv);
1047         } catch(AAIServiceException aaiexc) {
1048             if(aaiexc.getReturnCode() == 404)
1049                 return QueryStatus.NOT_FOUND;
1050
1051             return QueryStatus.FAILURE;
1052         } catch (Exception exc) {
1053             getLogger().warn("newModelBackupRequest", exc);
1054             return QueryStatus.FAILURE;
1055         }
1056
1057         return retval;
1058     }
1059
1060     public AAIDatum newModelObjectRequest(String resource,  Map<String, String> params,  String prefix,  SvcLogicContext ctx)
1061             throws AAIServiceException {
1062
1063         AAIDatum response = null;
1064
1065         try {
1066             AAIRequest request = AAIRequest.createRequest(resource, params);
1067             if(request == null) {
1068                 return null;
1069             }
1070
1071             request.processRequestPathValues(params);
1072             String rv = getExecutor().get(request);
1073             response = request.jsonStringToObject(rv);
1074         } catch(AAIServiceException aaiexc) {
1075             throw aaiexc;
1076         } catch (Exception exc) {
1077             getLogger().warn("newModelBackupRequest", exc);
1078             throw new AAIServiceException(exc);
1079         }
1080
1081         return response;
1082     }
1083
1084
1085     @Override
1086     public QueryStatus release(String arg0, String arg1, SvcLogicContext arg2) throws SvcLogicException {
1087         // TODO Auto-generated method stub
1088         throw new SvcLogicException("Method AAIService.release() has not been implemented yet");
1089     }
1090
1091     @Override
1092     public QueryStatus reserve(String arg0, String arg1, String arg2, String arg3, SvcLogicContext arg4)
1093             throws SvcLogicException {
1094         // TODO Auto-generated method stub
1095         throw new SvcLogicException("Method AAIService.reserve() has not been implemented yet");
1096     }
1097
1098     private QueryStatus newModelSave(String resource, boolean force, String key, Map<String, String> params, String prefix, SvcLogicContext ctx) {
1099         getLogger().debug("Executing newModelSave for resource : " + resource);
1100         HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
1101
1102         try {
1103             ArrayList<String> subResources = new ArrayList<>();
1104             Set<String> set = params.keySet();
1105             Map<String, Method> setters = new HashMap<>();
1106             Map<String, Method> getters = new HashMap<>();
1107
1108             // 1. find class
1109             AAIRequest request = AAIRequest.createRequest(resource, nameValues);
1110             Class<? extends AAIDatum> resourceClass = request.getModelClass();
1111             getLogger().debug(resourceClass.getName());
1112             AAIDatum instance = resourceClass.newInstance();
1113
1114             {
1115                 Annotation[] annotations = resourceClass.getAnnotations();
1116                 for(Annotation annotation : annotations) {
1117                     Class<? extends Annotation> anotationType = annotation.annotationType();
1118                     String annotationName = anotationType.getName();
1119
1120                     // 2. find string property setters and getters for the lists
1121                     if("javax.xml.bind.annotation.XmlType".equals(annotationName)){
1122                         XmlType order = (XmlType)annotation;
1123                         String[]  values = order.propOrder();
1124                         for(String value : values) {
1125                             String id = AAIServiceUtils.camelCaseToDashedString(value);
1126                             Field field = resourceClass.getDeclaredField(value);
1127                             Class<?> type = field.getType();
1128                             Method setter = null;
1129                             try {
1130                                 setter = resourceClass.getMethod("set"+StringUtils.capitalize(value), type);
1131                                 if(type.getName().startsWith("java.lang") || "boolean".equals(type.getName()) || "long".equals(type.getName())) {
1132                                     try {
1133                                         setter.setAccessible(true);
1134                                         Object arglist[] = new Object[1];
1135                                         arglist[0] = params.get(id);
1136
1137                                         if(arglist[0] != null) {
1138                                             if(!type.getName().equals("java.lang.String")) {
1139 //                                            getLogger().debug(String.format("Processing %s with parameter %s", types[0].getName(), value));
1140                                                 if("boolean".equals(type.getName())) {
1141                                                     arglist[0] = valueOf(Boolean.class, params.get(id));
1142                                                 } else if("long".equals(type.getName())) {
1143                                                         arglist[0] = valueOf(Long.class, params.get(id));
1144                                                 } else {
1145                                                     arglist[0] = valueOf(type, params.get(id));
1146                                                 }
1147                                             }
1148                                             Object o = setter.invoke(instance, arglist);
1149                                         }
1150                                         set.remove(id);
1151
1152                                     } catch (Exception x) {
1153                                         Throwable cause = x.getCause();
1154                                         getLogger().warn("Failed process for " + resourceClass.getName(), x);
1155                                     }
1156                                 } else if(type.getName().equals("java.util.List")) {
1157                                     List<String> newValues = new ArrayList<>();
1158                                     String length = id+"_length";
1159                                     if(!params.isEmpty() && params.containsKey(length)) {
1160                                         String tmp = params.get(length).toString();
1161                                         int count = Integer.parseInt(tmp);
1162                                         for(int i=0; i<count; i++) {
1163                                             String tmpValue = params.get(String.format("%s[%d]", id, i));
1164                                             newValues.add(tmpValue);
1165                                         }
1166                                         if(!newValues.isEmpty()) {
1167                                             Object o = setter.invoke(instance, newValues);
1168                                         }
1169                                     }
1170                                     set.remove(id);
1171                                 } else {
1172                                     setters.put(id, setter);
1173                                 }
1174                             } catch(Exception exc) {
1175
1176                             }
1177
1178                             Method getter;
1179                             try {
1180                                 getter = resourceClass.getMethod("get"+StringUtils.capitalize(value));
1181                                 if(!type.getName().equals("java.lang.String")) {
1182                                     getters.put(id, getter);
1183                                 }
1184                             } catch(Exception exc) {
1185
1186                             }
1187
1188                         }
1189                         subResources.addAll(Arrays.asList(values));
1190                     }
1191                 }
1192             }
1193
1194             // remove getters that have matching setter
1195             for(String setKey : setters.keySet()) {
1196                 if(getters.containsKey(setKey)) {
1197                     getters.remove(setKey);
1198                 }
1199             }
1200
1201             Set<String> relationshipKeys = new TreeSet<>();
1202             Set<String> vlansKeys = new TreeSet<>();
1203             Set<String> metadataKeys = new TreeSet<>();
1204
1205             for(String attribute : set) {
1206                 String value = params.get(attribute);
1207                 if(attribute.startsWith("relationship-list")) {
1208                     relationshipKeys.add(attribute);
1209                 } else if(attribute.startsWith("vlans")) {
1210                     vlansKeys.add(attribute);
1211                 } else if(attribute.startsWith("metadata")) {
1212                     metadataKeys.add(attribute);
1213                 }
1214             }
1215             // 3. find list property getters
1216             for(String attribute : set) {
1217                 String value = params.get(attribute);
1218                 Method method = getters.get(attribute);
1219                 if(method != null) {
1220                     try {
1221                         method.setAccessible(true);
1222                         Object arglist[] = new Object[0];
1223 //                        arglist[0] = value;
1224                         Class<?>[] types = method.getParameterTypes();
1225                         if(types.length == 0){
1226                             Object o = method.invoke(instance, arglist);
1227                             if(o instanceof ArrayList) {
1228                                 ArrayList<String> values = (ArrayList<String>)o;
1229 //                                getLogger().debug(String.format("Processing %s with parameter %s", types[0].getName(), value));
1230                                 value = value.replace("[", "").replace("]", "");
1231                                 List<String> items = Arrays.asList(value.split("\\s*,\\s*"));
1232                                 for(String s : items) {
1233                                     values.add(s.trim());
1234                                 }
1235                             }
1236                         }
1237                     } catch (Exception x) {
1238                         Throwable cause = x.getCause();
1239                         getLogger().warn("Failed process for " + resourceClass.getName(), x);
1240                     }
1241                 }
1242             }
1243             // 4. Process Relationships
1244             // add relationship list
1245             if( (subResources.contains("relationship-list") || subResources.contains("relationshipList")) &&  !relationshipKeys.isEmpty()) {
1246                 RelationshipList relationshipList = null;
1247                 Object obj = null;
1248                 Method getRelationshipListMethod = null;
1249                 try {
1250                      getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
1251                 } catch(Exception exc) {
1252                     getLogger().debug("Retrofiting relationship data: " + exc.getMessage());
1253                 }
1254
1255                 if(getRelationshipListMethod != null){
1256                     try {
1257                         getRelationshipListMethod.setAccessible(true);
1258                         obj = getRelationshipListMethod.invoke(instance);
1259                     } catch (InvocationTargetException x) {
1260                         Throwable cause = x.getCause();
1261                     }
1262                 }
1263                 if(obj != null && obj instanceof RelationshipList){
1264                     relationshipList = (RelationshipList)obj;
1265                 } else {
1266                     relationshipList = new RelationshipList();
1267                     Method setRelationshipListMethod = resourceClass.getMethod("setRelationshipList", RelationshipList.class);
1268                     if(setRelationshipListMethod != null){
1269                         try {
1270                             setRelationshipListMethod.setAccessible(true);
1271                             Object arglist[] = new Object[1];
1272                             arglist[0] = relationshipList;
1273
1274                             obj = setRelationshipListMethod.invoke(instance, arglist);
1275                         } catch (InvocationTargetException x) {
1276                             Throwable cause = x.getCause();
1277                         }
1278                     }
1279                 }
1280
1281                 List<Relationship> relationships = relationshipList.getRelationship();
1282
1283                 int i = 0;
1284                 while(true){
1285                     String searchKey = "relationship-list.relationship[" + i + "].related-to";
1286                     if(!params.containsKey(searchKey))
1287                         break;
1288                     int j = 0;
1289                     String relatedTo = params.get(searchKey);
1290                     String relatedLinkKey = "relationship-list.relationship[" + i + "].related-link";
1291                     String relatedLink = null;
1292                     if(params.containsKey(relatedLinkKey)) {
1293                         relatedLink = params.get(relatedLinkKey);
1294                     }
1295                     Relationship relationship = new Relationship();
1296                     relationships.add(relationship);
1297                     relationship.setRelatedTo(relatedTo);
1298                     if(relatedLink != null) {
1299                         relationship.setRelatedLink(relatedLink);
1300                     } else {
1301 //                        List<RelationshipData> relData = relationship.getRelationshipData();
1302                         Map<String, String> relParams = new HashMap<String, String>();
1303
1304                     while(true) {
1305                         String searchRelationshipKey = "relationship-list.relationship[" + i + "].relationship-data[" + j + "].relationship-key";
1306                         String searchRelationshipValue = "relationship-list.relationship[" + i + "].relationship-data[" + j + "].relationship-value";
1307                             if(!params.containsKey(searchRelationshipKey))
1308                             break;
1309
1310                             relParams.put(params.get(searchRelationshipKey), params.get(searchRelationshipValue));
1311                         j++;
1312                     }
1313                         AAIRequest rlRequest = AAIRequest.createRequest(relatedTo, relParams);
1314                         for(Map.Entry<String,String> entry : relParams.entrySet()) {
1315                             rlRequest.addRequestProperty(entry.getKey(), entry.getValue());
1316                         }
1317                         String path = rlRequest.updatePathDataValues(null);
1318                         relationship.setRelatedLink(path);
1319                     }
1320                     i++;
1321                 }
1322             }
1323
1324             // 4. vlans
1325             if(subResources.contains("vlans") &&  !vlansKeys.isEmpty()) {
1326                 Object obj = null;
1327                 Vlans vlanList = null;
1328                 Method getVLansMethod = resourceClass.getMethod("getVlans");
1329                 if(getVLansMethod != null){
1330                     try {
1331                         getVLansMethod.setAccessible(true);
1332                         obj = getVLansMethod.invoke(instance);
1333                     } catch (InvocationTargetException x) {
1334                         Throwable cause = x.getCause();
1335                     }
1336                 }
1337                 if(obj != null && obj instanceof Vlans){
1338                     vlanList = (Vlans)obj;
1339                 } else {
1340                     vlanList = new Vlans();
1341                     Method setVlansMethod = resourceClass.getMethod("setVlans", Vlans.class);
1342                     if(setVlansMethod != null){
1343                         try {
1344                             setVlansMethod.setAccessible(true);
1345                             Object arglist[] = new Object[1];
1346                             arglist[0] = vlanList;
1347
1348                             obj = setVlansMethod.invoke(instance, arglist);
1349                         } catch (InvocationTargetException x) {
1350                             Throwable cause = x.getCause();
1351                         }
1352                     }
1353                 }
1354
1355                 int i = 0;
1356                 while(true){
1357                     String searchKey = "vlans.vlan[" + i + "].vlan-interface";
1358                     if(!params.containsKey(searchKey))
1359                         break;
1360
1361                     String vlanInterface = params.get("vlans.vlan[" + i + "].vlan-interface");
1362                     String vlanIdInner    = params.get("vlans.vlan[" + i + "].vlan-id-inner");
1363                     String vlanIdOute     = params.get("vlans.vlan[" + i + "].vlan-id-outer");
1364                     String speedValue     = params.get("vlans.vlan[" + i + "].speed-value");
1365                     String speedUnits     = params.get("vlans.vlan[" + i + "].speed-units");
1366
1367                     Vlan vlan = new Vlan();
1368                     vlan.setVlanInterface(vlanInterface);
1369
1370                     if(vlanIdInner != null) {
1371                     Long iVlanIdInner = Long.parseLong(vlanIdInner);
1372                     vlan.setVlanIdInner(iVlanIdInner);
1373                     }
1374
1375                     if(vlanIdOute != null) {
1376                         Long iVlanIdOuter = Long.parseLong(vlanIdOute);
1377                     vlan.setVlanIdOuter(iVlanIdOuter);
1378                     }
1379
1380                     if(speedValue != null) {
1381                     vlan.setSpeedValue(speedValue);
1382                     vlan.setSpeedUnits(speedUnits);
1383                     }
1384
1385                     vlanList.getVlan().add(vlan);
1386                     i++;
1387                 }
1388             }
1389
1390             // 5. metadata
1391             if(subResources.contains("metadata") &&  !metadataKeys.isEmpty()) {
1392                 Object obj = null;
1393                 Metadata metadataList = null;
1394                 Method getMetadataMethod = resourceClass.getMethod("getMetadata");
1395                 if(getMetadataMethod != null){
1396                     try {
1397                         getMetadataMethod.setAccessible(true);
1398                         obj = getMetadataMethod.invoke(instance);
1399                     } catch (InvocationTargetException x) {
1400                         Throwable cause = x.getCause();
1401                     }
1402                 }
1403                 if(obj != null && obj instanceof Metadata){
1404                     metadataList = (Metadata)obj;
1405                 } else {
1406                     metadataList = new Metadata();
1407                     Method setMetadataMethod = resourceClass.getMethod("setMetadata", Metadata.class);
1408                     if(setMetadataMethod != null){
1409                         try {
1410                             setMetadataMethod.setAccessible(true);
1411                             Object arglist[] = new Object[1];
1412                             arglist[0] = metadataList;
1413
1414                             obj = setMetadataMethod.invoke(instance, arglist);
1415                         } catch (InvocationTargetException x) {
1416                             Throwable cause = x.getCause();
1417                         }
1418                     }
1419                 }
1420
1421                 if(metadataList.getMetadatum() == null) {
1422 //                    metadataList.setMetadatum(new ArrayList<Metadatum>());
1423                 }
1424
1425                 // process data
1426                 int i = 0;
1427                 while(true){
1428                     String metaKey = "metadata.metadatum[" + i + "].meta-key";
1429                     if(!params.containsKey(metaKey))
1430                         break;
1431
1432                     String metaValue = params.get("metadata.metadatum[" + i + "].meta-value");
1433
1434                     Metadatum vlan = new Metadatum();
1435                     vlan.setMetaname(metaKey);
1436                     vlan.setMetaval(metaValue);
1437
1438                     metadataList.getMetadatum().add(vlan);
1439                     i++;
1440                 }
1441
1442             }
1443
1444
1445             // 6. Prepare AAI request
1446             String[] args = request.getArgsList();
1447             for(String arg : args) {
1448                 String modifiedKey = arg.replaceAll("-", "_");
1449                 if(nameValues.containsKey(modifiedKey)) {
1450                     String argValue = nameValues.get(modifiedKey);
1451                     if(argValue != null) argValue = argValue.trim().replace("'", "").replace("$", "").replace("'", "");
1452                     request.addRequestProperty(arg, argValue);
1453                 }
1454             }
1455
1456             request.processRequestPathValues(nameValues);
1457             request.setRequestObject(instance);
1458                 Object response = getExecutor().post(request);
1459                 if(request.expectsDataFromPUTRequest()){
1460                     if(response != null && response instanceof String) {
1461                         String rv = response.toString();
1462                         QueryStatus retval = processResponseData(rv, resource, request, prefix,  ctx, nameValues, null);
1463                         getLogger().debug("newModelSave - returning " + retval.toString());
1464                         return retval;
1465                     }
1466                 }
1467
1468         } catch(AAIServiceException exc){
1469             ctx.setAttribute(prefix + ".error.message", exc.getMessage());
1470             int returnCode = exc.getReturnCode();
1471             if(returnCode >= 300) {
1472                 ctx.setAttribute(prefix + ".error.http.response-code",
1473                         Integer.toString(exc.getReturnCode()));
1474             }
1475
1476             if(returnCode == 400 || returnCode == 412)
1477                 return QueryStatus.FAILURE;
1478             else if(returnCode == 404)
1479                 return QueryStatus.NOT_FOUND;
1480             else {
1481                 getLogger().warn("Failed newModelSave - returning FAILURE", exc);
1482                 return QueryStatus.FAILURE;
1483             }
1484         } catch(Exception exc){
1485             getLogger().warn("Failed newModelSave - returning FAILURE", exc);
1486             ctx.setAttribute(prefix + ".error.message", exc.getMessage());
1487             return QueryStatus.FAILURE;
1488         }
1489
1490         getLogger().debug("newModelSave - returning SUCCESS");
1491         return QueryStatus.SUCCESS;
1492     }
1493
1494     private QueryStatus newModelProcessRelationshipList(Object instance, Map<String, String> params, String prefix, SvcLogicContext ctx) throws Exception {
1495
1496         Class resourceClass = instance.getClass();
1497
1498         Set<String> relationshipKeys = new TreeSet<>();
1499
1500         Set<String> set = params.keySet();
1501
1502         for(String attribute : set) {
1503             String value = params.get(attribute);
1504
1505             if(attribute.startsWith("relationship-list")) {
1506                 relationshipKeys.add(attribute);
1507             }
1508         }
1509
1510         // 3. Process Relationships
1511         // add relationship list
1512         if(!relationshipKeys.isEmpty()) {
1513             RelationshipList relationshipList;
1514             Object obj = null;
1515             Method getRelationshipListMethod = null;
1516             try {
1517                  getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
1518             } catch(Exception exc) {
1519                 getLogger().debug("Retrofiting relationship data: " + exc.getMessage());
1520             }
1521             if(getRelationshipListMethod != null){
1522                 try {
1523                     getRelationshipListMethod.setAccessible(true);
1524                     obj = getRelationshipListMethod.invoke(instance);
1525                 } catch (InvocationTargetException x) {
1526                     Throwable cause = x.getCause();
1527                 }
1528             }
1529             if(obj != null && obj instanceof RelationshipList){
1530                 relationshipList = (RelationshipList)obj;
1531             } else {
1532                 relationshipList = new RelationshipList();
1533                 Method setRelationshipListMethod = resourceClass.getMethod("setRelationshipList", RelationshipList.class);
1534                 if(setRelationshipListMethod != null){
1535                     try {
1536                         setRelationshipListMethod.setAccessible(true);
1537                         Object arglist[] = new Object[1];
1538                         arglist[0] = relationshipList;
1539
1540                         obj = setRelationshipListMethod.invoke(instance, arglist);
1541                     } catch (InvocationTargetException x) {
1542                         Throwable cause = x.getCause();
1543                     }
1544                 }
1545             }
1546
1547             boolean createdNewRelationships = false;
1548             List<Relationship> relationships = relationshipList.getRelationship();
1549             if(relationships == null) {
1550                 relationships = new ArrayList<Relationship>();
1551                 createdNewRelationships = true;
1552             }
1553
1554             int i = 0;
1555             while(true){
1556                 String searchKey = "relationship-list.relationship[" + i + "].related-to";
1557                 if(!params.containsKey(searchKey))
1558                     break;
1559
1560                 int j = 0;
1561                 String relatedTo = params.get(searchKey);
1562                 String relatedLinkKey = "relationship-list.relationship[" + i + "].related-link";
1563                 String relatedLink = null;
1564                 if(params.containsKey(relatedLinkKey)) {
1565                     relatedLink = params.get(relatedLinkKey);
1566                 }
1567
1568                 Relationship relationship = new Relationship();
1569                     relationships.add(relationship);
1570                     relationship.setRelatedTo(relatedTo);
1571                     if(relatedLink != null) {
1572                         relationship.setRelatedLink(relatedLink);
1573                 } else  {
1574                     Map<String, String> relParams = new HashMap<>();
1575
1576                 while(true) {
1577                     String searchRelationshipKey = "relationship-list.relationship[" + i + "].relationship-data[" + j + "].relationship-key";
1578                     String searchRelationshipValue = "relationship-list.relationship[" + i + "].relationship-data[" + j + "].relationship-value";
1579                     if(!params.containsKey(searchRelationshipKey))
1580                         break;
1581
1582                         relParams.put(params.get(searchRelationshipKey), params.get(searchRelationshipValue));
1583                     j++;
1584                 }
1585                     AAIRequest rlRequest = AAIRequest.createRequest(relatedTo, relParams);
1586                     for(String key : relParams.keySet()) {
1587                         rlRequest.addRequestProperty(key, relParams.get(key));
1588                     }
1589                     String path = rlRequest.updatePathDataValues(null);
1590                     relationship.setRelatedLink(path);
1591                 }
1592
1593                 i++;
1594             }
1595         }
1596
1597         return QueryStatus.SUCCESS;
1598     }
1599
1600     private Relationship findRelationship(List<Relationship> relationships, String relatedTo) {
1601         if(relatedTo == null)
1602             return null;
1603
1604         for(Relationship relationship : relationships) {
1605             if(relationship.getRelatedTo().equals(relatedTo)){
1606                 return relationship;
1607             }
1608         }
1609         return null;
1610     }
1611
1612
1613     public QueryStatus backup(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
1614         String resource = params.get("resource").toLowerCase();
1615         String prefix = params.get("data-key");
1616
1617         HashMap<String, String> nameValues = new HashMap<>();
1618         if(AAIRequest.createRequest(resource, nameValues) != null) {
1619
1620             try {
1621                 return newModelBackupRequest(resource, params, prefix, ctx);
1622             } catch (Exception exc) {
1623                 getLogger().warn("Failed backup - returning FAILURE", exc);
1624                 return QueryStatus.FAILURE;
1625             }
1626         }
1627
1628         return QueryStatus.NOT_FOUND;
1629     }
1630
1631     @Override
1632     public QueryStatus restore(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
1633
1634         QueryStatus retval = QueryStatus.SUCCESS;
1635         String resource = params.get("resource").toLowerCase();
1636         String prefix = params.get("data-key");
1637
1638         HashMap<String, String> nameValues = new HashMap<>();
1639         if(AAIRequest.createRequest(resource, nameValues) != null) {
1640
1641             try {
1642                 retval = newModelBackupRequest(resource, params, "tmpRestore", ctx);
1643                 if(retval == QueryStatus.SUCCESS) {
1644                     String current_json = ctx.getAttribute("tmpRestore");
1645                     ctx.  setAttribute("tmpRestore", null);
1646
1647                     String snapshot_json = ctx.getAttribute(prefix);
1648                 }
1649             } catch (Exception exc) {
1650                 getLogger().warn("Failed restore - returning FAILURE", exc);
1651                 return QueryStatus.FAILURE;
1652             }
1653         }
1654
1655         return QueryStatus.NOT_FOUND;
1656     }
1657
1658     protected Map<String, Object> objectToProperties(Object object) {
1659         ObjectMapper mapper = AAIService.getObjectMapper();
1660         return mapper.convertValue(object, Map.class);
1661     }
1662
1663     static <T> T valueOf(Class<T> klazz, String arg) {
1664         Exception cause = null;
1665         T ret = null;
1666         try {
1667             ret = klazz.cast(klazz.getDeclaredMethod("valueOf", String.class).invoke(null, arg));
1668         } catch (NoSuchMethodException exc) {
1669             LoggerFactory.getLogger(AAIService.class).warn("Wrong data type", exc);
1670             ret = klazz.cast(arg);
1671         } catch (IllegalAccessException e) {
1672             cause = e;
1673         } catch (InvocationTargetException e) {
1674             cause = e;
1675         }
1676         if (cause == null) {
1677             return ret;
1678         } else {
1679             throw new IllegalArgumentException(cause);
1680         }
1681     }
1682
1683     private QueryStatus processDeleteRelationshipList(String resource, String key, SvcLogicContext ctx, HashMap<String, String> nameValues) {
1684         try {
1685             AAIRequest request = AAIRequest.createRequest(resource, nameValues);
1686             if(request == null) {
1687                 return QueryStatus.FAILURE;
1688             }
1689
1690             request.processRequestPathValues(nameValues);
1691             URL url = request.getRequestUrl("GET", null);
1692
1693             Class resourceClass = request.getModelClass();
1694             Object instance = getResource(url.toString(), resourceClass);
1695             if(instance == null)
1696                 return QueryStatus.NOT_FOUND;
1697
1698             // get resource version
1699             String resourceVersion = null;
1700             Method getResourceVersionMethod = resourceClass.getMethod("getResourceVersion");
1701             if(getResourceVersionMethod != null){
1702                 try {
1703                     getResourceVersionMethod.setAccessible(true);
1704                     Object object = getResourceVersionMethod.invoke(instance);
1705                     if(object != null)
1706                         resourceVersion = object.toString();
1707                 } catch (InvocationTargetException x) {
1708                     Throwable cause = x.getCause();
1709                 }
1710             }
1711
1712             RelationshipList relationshipList = null;
1713             Object obj = null;
1714             Method getRelationshipListMethod = null;
1715             try {
1716                  getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
1717             } catch(Exception exc) {
1718                 getLogger().debug("Retrofiting relationship data: " + exc.getMessage());
1719             }
1720             if(getRelationshipListMethod != null){
1721                 try {
1722                     getRelationshipListMethod.setAccessible(true);
1723                     obj = getRelationshipListMethod.invoke(instance);
1724                 } catch (InvocationTargetException x) {
1725                     Throwable cause = x.getCause();
1726                 }
1727             }
1728             if(obj != null && obj instanceof RelationshipList){
1729                 relationshipList = (RelationshipList)obj;
1730             } else {
1731                 getLogger().debug("No relationships found to process.");
1732                 return QueryStatus.NOT_FOUND;
1733             }
1734
1735             if(relationshipList.getRelationship() == null || relationshipList.getRelationship().isEmpty()) {
1736                 return QueryStatus.NOT_FOUND;
1737             }
1738             String relatedTo = nameValues.get("related_to");
1739             if(relatedTo == null) {
1740                 return QueryStatus.FAILURE;
1741             }
1742
1743             relatedTo = relatedTo.replaceAll("_", "-");
1744
1745             String relatedLink = nameValues.get("relationship.related_link");
1746             if(relatedLink != null) {
1747                 relatedLink = URLDecoder.decode(relatedLink, "UTF-8");
1748             }
1749
1750             List<Relationship> relationships = relationshipList.getRelationship();
1751             List<Relationship> relationshipsToDelete = new LinkedList<Relationship>();
1752
1753             for(Relationship relationship : relationships) {
1754                 if(relatedTo.equals(relationship.getRelatedTo())) {
1755                     if(relatedLink != null) {
1756                         if(relationship.getRelatedLink() != null ) {
1757                             String localRelatedLink = relationship.getRelatedLink();
1758                             localRelatedLink = URLDecoder.decode(localRelatedLink, "UTF-8");
1759                             if(localRelatedLink.endsWith(relatedLink)) {
1760                                 getLogger().debug(String.format("Found relationship of '%s' to keyword '%s'", relationship.getRelatedTo(),  relatedTo));
1761                                 relationshipsToDelete.add(relationship);
1762                         }
1763                     }
1764                     } else {
1765                     getLogger().debug(String.format("Found relationship of '%s' to keyword '%s'", relationship.getRelatedTo(),  relatedTo));
1766                     relationshipsToDelete.add(relationship);
1767                 }
1768             }
1769             }
1770             if(relationshipsToDelete == null || relationshipsToDelete.isEmpty()) {
1771                 getLogger().info(String.format("Relationship has not been found for %s", key));
1772                 return QueryStatus.NOT_FOUND;
1773             }
1774
1775             String path = url.toString();
1776             path = path + "/relationship-list/relationship";
1777             URL deleteUrl = new URL(path);
1778
1779             ObjectMapper mapper = AAIService.getObjectMapper();
1780
1781             boolean cumulativeResponse = true;
1782
1783             for(Relationship targetRelationship : relationshipsToDelete) {
1784                 String json_text = mapper.writeValueAsString(targetRelationship);
1785                 boolean response = deleteRelationshipList(deleteUrl, json_text);
1786                 if(!response)
1787                     cumulativeResponse = response;
1788
1789             }
1790
1791             if(!cumulativeResponse)
1792                 return QueryStatus.FAILURE;
1793
1794             return QueryStatus.SUCCESS;
1795
1796         } catch(Exception exc) {
1797             getLogger().warn("processDelete", exc);
1798             return QueryStatus.FAILURE;
1799         }
1800     }
1801
1802     static final Map<String, String> ctxGetBeginsWith( SvcLogicContext ctx, String prefix ) {
1803         Map<String, String> tmpPrefixMap = new HashMap<>();
1804
1805         if(prefix == null || prefix.isEmpty()){
1806             return tmpPrefixMap;
1807         }
1808
1809         for( String key : ctx.getAttributeKeySet() ) {
1810             if( key.startsWith(prefix) ) {
1811                 String tmpKey = key.substring(prefix.length() + 1);
1812                 tmpPrefixMap.put( tmpKey, ctx.getAttribute(key));
1813             }
1814         }
1815
1816         Map<String, String> prefixMap = new HashMap<>();
1817         Pattern p = Pattern.compile(".*\\[\\d\\]");
1818
1819         SortedSet<String> keys = new TreeSet(tmpPrefixMap.keySet () );
1820         for(String key : keys) {
1821             Matcher m = p.matcher(key);
1822             if(m.matches()) {
1823                 continue;
1824             } else if(key.endsWith("_length")) {
1825                 String listKey = key.substring(0, key.indexOf("_length"));
1826                 int max = Integer.parseInt(tmpPrefixMap.get(key));
1827
1828                 ArrayList<String> data = new ArrayList<>();
1829                 for(int x = 0; x < max; x++){
1830                     String tmpKey = String.format("%s[%d]", listKey, x);
1831                     String tmpValue = tmpPrefixMap.get(tmpKey);
1832                     if(tmpValue != null && !tmpValue.isEmpty()) {
1833                         data.add(tmpValue);
1834                     }
1835                 }
1836                 if(!data.isEmpty()) {
1837                     prefixMap.put(listKey, data.toString());
1838                 } else {
1839                     prefixMap.put(key, tmpPrefixMap.get(key));
1840                 }
1841             } else {
1842                 prefixMap.put(key, tmpPrefixMap.get(key));
1843             }
1844         }
1845
1846         return prefixMap;
1847     }
1848
1849     /**
1850     */
1851     protected NamedQueryData extractNamedQueryDataFromQueryPrefix(HashMap<String, String> nameValues, Map<String, String> parms) {
1852         if(parms.isEmpty()) {
1853             return null;
1854         }
1855
1856         NamedQueryData data = new NamedQueryData();
1857
1858         // query parameters
1859         if(data.getQueryParameters() == null) {
1860             data.setQueryParameters(new QueryParameters());
1861         }
1862         String namedQueryUuid = nameValues.get("named-query-uuid".replaceAll("-", "_"));
1863         if(namedQueryUuid == null) {
1864             namedQueryUuid = parms.get("query-parameters.named-query.named-query-uuid");
1865         }
1866         NamedQuery namedQuery = new NamedQuery();
1867         namedQuery.setNamedQueryUuid(namedQueryUuid);
1868         data.getQueryParameters().setNamedQuery(namedQuery);
1869
1870         // instance filters
1871         if(data.getInstanceFilters() == null) {
1872             data.setInstanceFilters(new InstanceFilters());
1873         }
1874
1875
1876         String quantity = parms.get("instance-filters.instance-filter_length");
1877         if(quantity != null && StringUtils.isNumeric(quantity)) {
1878             int max = Integer.parseInt(quantity);
1879             for(int i = 0; i < max; i++) {
1880                 String keyPattern = String.format("instance-filters.instance-filter[%d].", i);
1881                 Set<String> keys = parms.keySet();
1882                 for(String key: keys) {
1883                     if(key.startsWith(keyPattern)){
1884                         String value = parms.get(key);
1885                         String remainder = key.substring(keyPattern.length());
1886                         String[] split = remainder.split("\\.");
1887                         getLogger().debug(String.format("%s", remainder));
1888                         if("logical-link".equals(split[0])) {
1889                             InstanceFilter insf = null;
1890                             if(data.getInstanceFilters().getInstanceFilter().isEmpty()) {
1891                                 insf = new InstanceFilter();
1892                                 data.getInstanceFilters().getInstanceFilter().add(insf);
1893                             } else {
1894                                 insf = data.getInstanceFilters().getInstanceFilter().get(0);
1895                             }
1896                             LogicalLink logicalLink = insf.getLogicalLink();
1897                             if(logicalLink == null) {
1898                                 logicalLink = new LogicalLink();
1899                                 insf.setLogicalLink(logicalLink);
1900                             }
1901
1902                             switch(split[1]) {
1903                             case "link-name":
1904                                 logicalLink.setLinkName(value);
1905                                 break;
1906                             case "link-type":
1907                                 logicalLink.setLinkType(value);
1908                                 break;
1909                             case "operational-state":
1910                                 logicalLink.setOperationalStatus(value);
1911                                 break;
1912                             }
1913
1914                         } else if("pnf".equals(split[0])) {
1915                             Pnf pnf = new Pnf();
1916                             pnf.setPnfName(value);
1917
1918                             InstanceFilter insf = new InstanceFilter();
1919                             insf.setPnf(pnf);
1920                             data.getInstanceFilters().getInstanceFilter().add(insf);
1921
1922                         } else if("service-instance".equals(split[0])) {
1923                             ServiceInstance serviceInstance = new ServiceInstance();
1924                             serviceInstance.setServiceInstanceId(value);
1925
1926                             InstanceFilter insf = new InstanceFilter();
1927                             insf.setServiceInstance(serviceInstance);
1928                             data.getInstanceFilters().getInstanceFilter().add(insf);
1929
1930                         } else if("l3-network".equals(split[0])) {
1931                             L3Network l3Network = new L3Network();
1932                             if("network-role".equals(split[1])) {
1933                                 l3Network.setNetworkRole(value);
1934                             }
1935
1936                             InstanceFilter insf = new InstanceFilter();
1937                             insf.setL3Network(l3Network);
1938                             data.getInstanceFilters().getInstanceFilter().add(insf);
1939                         } else if("generic-vnf".equals(split[0])) {
1940                             GenericVnf vnf = new GenericVnf();
1941                             if("vnf-id".equals(split[1])) {
1942                                 vnf.setVnfId(value);
1943                             }
1944
1945                             InstanceFilter insf = new InstanceFilter();
1946                             insf.setGenericVnf(vnf);
1947                             data.getInstanceFilters().getInstanceFilter().add(insf);
1948                         }
1949                     }
1950                 }
1951             }
1952         }
1953
1954         return data;
1955     }
1956
1957     public abstract <T> T getResource(String key, Class<T> type) throws AAIServiceException ;
1958     protected abstract boolean deleteRelationshipList(URL url, String caller) throws AAIServiceException;
1959 }