Isolate deprecated code in CCSDK aai-service
[ccsdk/sli/adaptors.git] / aai-service / provider / src / main / java / org / onap / ccsdk / sli / adaptors / aai / AAIService.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
25 import java.io.BufferedReader;
26 import java.io.ByteArrayInputStream;
27 import java.io.File;
28 import java.io.FileInputStream;
29 import java.io.InputStream;
30 import java.io.InputStreamReader;
31 import java.io.OutputStreamWriter;
32 import java.io.UnsupportedEncodingException;
33 import java.lang.reflect.Field;
34 import java.lang.reflect.Modifier;
35 import java.net.HttpURLConnection;
36 import java.net.MalformedURLException;
37 import java.net.URI;
38 import java.net.URISyntaxException;
39 import java.net.URL;
40 import java.net.URLEncoder;
41 import java.nio.charset.StandardCharsets;
42 import java.security.KeyManagementException;
43 import java.security.KeyStore;
44 import java.security.NoSuchAlgorithmException;
45 import java.text.SimpleDateFormat;
46 import java.util.Calendar;
47 import java.util.Enumeration;
48 import java.util.HashMap;
49 import java.util.LinkedList;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.Map.Entry;
53 import java.util.Properties;
54 import java.util.Set;
55 import java.util.TimeZone;
56 import java.util.UUID;
57 import java.util.regex.Matcher;
58 import java.util.regex.Pattern;
59
60 import javax.net.ssl.HostnameVerifier;
61 import javax.net.ssl.HttpsURLConnection;
62 import javax.net.ssl.KeyManagerFactory;
63 import javax.net.ssl.SSLContext;
64 import javax.net.ssl.SSLSession;
65 import javax.net.ssl.SSLSocketFactory;
66 import javax.ws.rs.HttpMethod;
67 import javax.xml.bind.annotation.XmlElement;
68
69 import org.apache.commons.codec.binary.Base64;
70 import org.apache.commons.lang3.StringUtils;
71 import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
72 import org.onap.ccsdk.sli.adaptors.aai.data.ErrorResponse;
73 import org.onap.ccsdk.sli.adaptors.aai.data.notify.NotifyEvent;
74 import org.onap.ccsdk.sli.core.sli.ConfigurationException;
75 import org.onap.ccsdk.sli.core.sli.MetricLogger;
76 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
77 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
78 import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
79 import org.openecomp.aai.inventory.v11.GenericVnf;
80 import org.openecomp.aai.inventory.v11.PhysicalLink;
81 import org.openecomp.aai.inventory.v11.ResultData;
82 import org.openecomp.aai.inventory.v11.SearchResults;
83 import org.openecomp.aai.inventory.v11.Vserver;
84 import org.slf4j.Logger;
85 import org.slf4j.LoggerFactory;
86 import org.slf4j.MDC;
87
88 import com.fasterxml.jackson.annotation.JsonInclude.Include;
89 import com.fasterxml.jackson.databind.AnnotationIntrospector;
90 import com.fasterxml.jackson.databind.DeserializationFeature;
91 import com.fasterxml.jackson.databind.ObjectMapper;
92 import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
93 import com.fasterxml.jackson.databind.type.TypeFactory;
94 import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
95 import com.sun.jersey.api.client.config.DefaultClientConfig;
96 import com.sun.jersey.client.urlconnection.HTTPSProperties;
97
98
99 public class AAIService extends AAIDeclarations implements AAIClient, SvcLogicResource {
100
101     public static final String AAICLIENT_PROPERTIES = "/aaiclient.properties";
102     public static final String PATH_PROPERTIES = "/aai-path.properties";
103
104     private static final Logger LOG = LoggerFactory.getLogger(AAIService.class);
105
106     private final String truststorePath;
107     private final String truststorePassword;
108     private final String keystorePath;
109     private final String keystorePassword;
110     private final Boolean ignoreCertificateHostError;
111
112     private final String targetUri;
113     private final String queryPath;
114
115     private final String networkVserverPath;
116
117     private final String svcInstancePath;
118     private final String svc_inst_qry_path;
119
120     private final String vnf_image_query_path;
121
122     private final String param_service_type;            //= "service-type";
123
124     private final String ubb_notify_path;
125     private final String selflinkAvpn;
126     private final String selflinkFqdn;
127
128     private final String pInterfacePath;
129
130     private final String servicePath;
131     private final String sitePairSetPath;
132
133     private final int connectionTimeout;
134     private final int readTimeout;
135
136     // 1602
137     private final String queryNodesPath;
138     private final String updatePath;
139
140     private final String applicationId;
141
142     // authentication credentials
143     private String userName;
144     private String userPassword;
145
146     // runtime
147     private final boolean runtimeOSGI;
148
149     private SSLContext CTX;
150
151     private final MetricLogger ml = new MetricLogger();
152
153     private AAIExecutorInterface executor;
154
155         public void setExecutor(AAIExecutorInterface executor) {
156                 this.executor = executor;
157         }
158
159     public AAIService(URL propURL) {
160         LOG.info("Entered AAIService.ctor");
161
162         String runtime = System.getProperty("aaiclient.runtime");
163         if("OSGI".equals(runtime)) {
164             runtimeOSGI = true;
165         } else {
166             runtimeOSGI = false;
167         }
168
169         Properties props = null;
170         try {
171             props = initialize(propURL);
172             AAIRequest.setProperties(props, this);
173
174         } catch(Exception exc){
175             LOG.error("AicAAIResource.static", exc);
176         }
177
178         executor = new AAIClientRESTExecutor(props);
179
180         userName            = props.getProperty(CLIENT_NAME);
181         userPassword        = props.getProperty(CLIENT_PWWD);
182
183         if(userName == null || userName.isEmpty()){
184             LOG.debug("Basic user name is not set");
185         }
186         if(userPassword == null || userPassword.isEmpty()) {
187             LOG.debug("Basic password is not set");
188         }
189
190         truststorePath     = props.getProperty(TRUSTSTORE_PATH);
191         truststorePassword = props.getProperty(TRUSTSTORE_PSSWD);
192         keystorePath         = props.getProperty(KEYSTORE_PATH);
193         keystorePassword     = props.getProperty(KEYSTORE_PSSWD);
194
195         targetUri             = props.getProperty(TARGET_URI);
196         queryPath             = props.getProperty(QUERY_PATH);
197         updatePath         = props.getProperty(UPDATE_PATH);
198
199         String tmpApplicationId = props.getProperty(APPLICATION_ID);
200         if(tmpApplicationId == null || tmpApplicationId.isEmpty()) {
201                 tmpApplicationId = "SDNC";
202         }
203         this.applicationId = tmpApplicationId;
204
205         // connection timeout
206         int tmpConnectionTimeout = 30000;
207         int tmpReadTimeout = 30000;
208
209         try {
210             String tmpValue = null;
211             tmpValue = props.getProperty(CONNECTION_TIMEOUT, "30000");
212             tmpConnectionTimeout = Integer.parseInt(tmpValue);
213             tmpValue = props.getProperty(READ_TIMEOUT, "30000");
214             tmpReadTimeout = Integer.parseInt(tmpValue);
215         } catch(Exception exc) {
216             LOG.error("Failed setting connection timeout", exc);
217             tmpConnectionTimeout = 30000;
218             tmpReadTimeout = 30000;
219         }
220         connectionTimeout = tmpConnectionTimeout;
221         readTimeout = tmpReadTimeout;
222
223         networkVserverPath =props.getProperty(NETWORK_VSERVER_PATH);
224
225         svcInstancePath    = props.getProperty(SVC_INSTANCE_PATH);
226         svc_inst_qry_path    = props.getProperty(SVC_INST_QRY_PATH);
227         param_service_type     = props.getProperty(PARAM_SERVICE_TYPE, "service-type");
228
229         // P-Interfaces
230         pInterfacePath   = props.getProperty(P_INTERFACE_PATH);
231
232         vnf_image_query_path    = props.getProperty(VNF_IMAGE_QUERY_PATH);
233
234         ubb_notify_path = props.getProperty(UBB_NOTIFY_PATH);
235         selflinkAvpn = props.getProperty(SELFLINK_AVPN);
236         selflinkFqdn = props.getProperty(SELFLINK_FQDN);
237
238         servicePath  = props.getProperty(SERVICE_PATH);
239
240         sitePairSetPath  = props.getProperty(SITE_PAIR_SET_PATH);
241
242         queryNodesPath = props.getProperty(QUERY_NODES_PATH);
243
244         String iche = props.getProperty(CERTIFICATE_HOST_ERROR);
245         boolean host_error = false;
246         if(iche != null && !iche.isEmpty()) {
247             host_error = Boolean.valueOf(iche);
248         }
249
250         ignoreCertificateHostError = host_error;
251
252         HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier(){
253             public boolean verify(String string,SSLSession ssls) {
254                 return ignoreCertificateHostError;
255             }
256         });
257
258         if(truststorePath != null && truststorePassword != null && (new File(truststorePath)).exists()) {
259             System.setProperty("javax.net.ssl.trustStore", truststorePath);
260             System.setProperty("javax.net.ssl.trustStorePassword", truststorePassword);
261         }
262
263         if(keystorePath != null && keystorePassword != null && (new File(keystorePath)).exists()) {
264         DefaultClientConfig config = new DefaultClientConfig();
265         //both jersey and HttpURLConnection can use this
266         SSLContext ctx = null;
267         try {
268             ctx = SSLContext.getInstance("TLS");
269
270             KeyManagerFactory kmf = null;
271             try (FileInputStream fin = new FileInputStream(keystorePath)){
272                 String def = "SunX509";
273                 String storeType = "PKCS12";
274                 def = KeyStore.getDefaultType();
275                 kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
276
277                 String extension = keystorePath.substring(keystorePath.lastIndexOf(".") + 1);
278                 if("JKS".equalsIgnoreCase(extension)) {
279                     storeType = "JKS";
280                 }
281                 KeyStore ks = KeyStore.getInstance(storeType);
282
283                 char[] pwd = keystorePassword.toCharArray();
284                 ks.load(fin, pwd);
285                 kmf.init(ks, pwd);
286             } catch (Exception ex) {
287                 LOG.error("AAIResource", ex);
288             }
289
290             ctx.init(kmf.getKeyManagers(), null, null);
291             config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties( new HostnameVerifier() {
292                     @Override
293                     public boolean verify( String s, SSLSession sslSession ) {
294                         return ignoreCertificateHostError;
295                     }
296             }, ctx));
297
298             CTX = ctx;
299                 LOG.debug("SSLContext created");
300
301         } catch (KeyManagementException | NoSuchAlgorithmException exc) {
302             LOG.error("AAIResource", exc);
303         }
304         }
305
306         LOG.info("AAIResource.ctor initialized.");
307
308         try {
309             Field methodsField = HttpURLConnection.class.getDeclaredField("methods");
310             methodsField.setAccessible(true);
311             // get the methods field modifiers
312             Field modifiersField = Field.class.getDeclaredField("modifiers");
313             // bypass the "private" modifier
314             modifiersField.setAccessible(true);
315
316             // remove the "final" modifier
317             modifiersField.setInt(methodsField, methodsField.getModifiers() & ~Modifier.FINAL);
318
319             /* valid HTTP methods */
320             String[] methods = {
321                        "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE", "PATCH"
322             };
323             // set the new methods - including patch
324             methodsField.set(null, methods);
325
326         } catch (SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchFieldException e) {
327          e.printStackTrace();
328         }
329
330     }
331
332     public void cleanUp() {
333
334     }
335
336     /**
337      *
338      * @param http_req_url
339      * @param method
340      * @return
341      * @throws Exception
342      */
343     protected HttpURLConnection getConfiguredConnection(URL http_req_url, String method) throws Exception {
344         HttpURLConnection con = (HttpURLConnection) http_req_url.openConnection();
345
346         // Set up the connection properties
347         con.setRequestProperty( "Connection", "close" );
348         con.setDoInput(true);
349         con.setDoOutput(true);
350         con.setUseCaches(false);
351         con.setConnectTimeout( connectionTimeout );
352         con.setReadTimeout( readTimeout );
353         con.setRequestMethod( method );
354         con.setRequestProperty( "Accept", "application/json" );
355         con.setRequestProperty( "Content-Type",  "PATCH".equalsIgnoreCase(method) ? "application/merge-patch+json" : "application/json" );
356         con.setRequestProperty("X-FromAppId", applicationId);
357         con.setRequestProperty("X-TransactionId",TransactionIdTracker.getNextTransactionId());
358         String mlId = ml.getRequestID();
359         if(mlId != null && !mlId.isEmpty()) {
360             LOG.debug(String.format("MetricLogger requestId = %s", mlId));
361             con.setRequestProperty(MetricLogger.REQUEST_ID, mlId);
362         } else {
363             LOG.debug("MetricLogger requestId is null");
364         }
365         con.setRequestProperty("Transfer-Encoding","chunked");
366
367         if(userName != null && !userName.isEmpty() && userPassword != null && !userPassword.isEmpty()) {
368             String basicAuth = "Basic " + new String(Base64.encodeBase64((userName + ":" + userPassword).getBytes()));
369             con.setRequestProperty ("Authorization", basicAuth);
370         }
371
372         if(con instanceof HttpsURLConnection && CTX != null) {
373             SSLSocketFactory sockFact = CTX.getSocketFactory();
374             HttpsURLConnection.class.cast(con).setSSLSocketFactory( sockFact );
375         }
376         return con;
377     }
378
379
380     @Override
381     public GenericVnf requestGenericVnfData(String vnf_id) throws AAIServiceException {
382         GenericVnf response = null;
383
384         try {
385             AAIRequest request = AAIRequest.getRequestFromResource("generic-vnf");
386             request.addRequestProperty("generic-vnf.vnf-id", vnf_id);
387             String rv = executor.get(request);
388             if(rv != null) {
389                 ObjectMapper mapper = getObjectMapper();
390                 response = mapper.readValue(rv, GenericVnf.class);
391             }
392         } catch(AAIServiceException aaiexc) {
393             throw aaiexc;
394         } catch (Exception exc) {
395             LOG.warn(Object.class.getClass().getEnclosingMethod().getName(), exc);
396             throw new AAIServiceException(exc);
397         }
398
399         return response;
400
401     }
402
403     @Override
404     public boolean postGenericVnfData(String vnf_id, GenericVnf data) throws AAIServiceException {
405         try {
406             AAIRequest request = AAIRequest.getRequestFromResource("generic-vnf");
407             request.addRequestProperty("generic-vnf.vnf-id", vnf_id);
408             request.setRequestObject(data);
409             Object response = executor.post(request);
410             return true;
411         } catch(AAIServiceException aaiexc) {
412             throw aaiexc;
413         } catch (Exception exc) {
414             LOG.warn("requestGenericVnfData", exc);
415             throw new AAIServiceException(exc);
416         }
417     }
418
419     @Override
420     public SearchResults requestServiceInstanceURL(String svc_instance_id) throws AAIServiceException {
421         SearchResults response = null;
422         InputStream inputStream = null;
423
424         try {
425             String path = svc_inst_qry_path;
426             path = path.replace("{svc-instance-id}", encodeQuery(svc_instance_id));
427
428             String request_url = targetUri+path;
429             URL http_req_url =    new URL(request_url);
430
431             HttpURLConnection con = getConfiguredConnection(http_req_url, HttpMethod.GET);
432
433             LOGwriteFirstTrace(HttpMethod.GET, http_req_url.toString());
434             LOGwriteDateTrace("svc_instance_id", svc_instance_id);
435
436             // Check for errors
437             int responseCode = con.getResponseCode();
438             if (responseCode == HttpURLConnection.HTTP_OK) {
439                 inputStream = con.getInputStream();
440             } else {
441                 inputStream = con.getErrorStream();
442             }
443
444             // Process the response
445             LOG.debug("HttpURLConnection result:" + responseCode);
446             if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
447             BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
448
449             ObjectMapper mapper = getObjectMapper();
450
451     if (responseCode == HttpURLConnection.HTTP_OK) {
452                 response = mapper.readValue(reader, SearchResults.class);
453                 LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, "SUCCESS", mapper.writeValueAsString(response));
454             } else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND ) {
455                 LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", "Entry does not exist.");
456                 return response;
457             } else {
458                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
459                 LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
460                 throw new AAIServiceException(responseCode, errorresponse);
461             }
462
463         } catch(AAIServiceException aaiexc) {
464             throw aaiexc;
465         } catch (Exception exc) {
466             LOG.warn("requestServiceInstanceURL", exc);
467             throw new AAIServiceException(exc);
468         } finally {
469             if(inputStream != null){
470                 try {
471                     inputStream.close();
472                 } catch(Exception exc) {
473                 }
474             }
475         }
476         return response;
477     }
478
479
480     private static Properties initialize(URL url ) throws ConfigurationException {
481
482         if(url ==  null) {
483             throw new NullPointerException();
484         }
485
486         InputStream is = null;
487         Properties props = new Properties();
488
489         try {
490             if(LOG.isDebugEnabled())
491                 LOG.info("Property file is: " + url.toString());
492
493             is = url.openStream();
494
495             props.load(is);
496             if(LOG.isDebugEnabled()) {
497                 LOG.info("Properties loaded: " + props.size());
498                 Enumeration<Object> en = props.keys();
499
500                 while(en.hasMoreElements()) {
501                     String key = (String)en.nextElement();
502                     String property = props.getProperty(key);
503                     LOG.debug(key + " : " + property);
504                 }
505             }
506         } catch (Exception e) {
507             throw new ConfigurationException("Could not load properties file.", e);
508         }
509         return props;
510     }
511
512     static class TransactionIdTracker {
513 //        protected static AtomicLong tracker = new AtomicLong();
514
515         public static String getNextTransactionId() {
516             // Check if RequestId exists as MDC. If not, create new.
517             String transactionId = MDC.get("RequestId");
518             if ("".equals(transactionId) || transactionId == null) {
519                 transactionId = UUID.randomUUID().toString();
520                 LOG.info("Missing requestID. Assigned " + transactionId);
521                 MDC.put("RequestId", transactionId);
522             }
523             return transactionId;
524         }
525
526     }
527
528     protected void LOGwriteFirstTrace(String method, String url) {
529         String time = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").format(System.currentTimeMillis());
530         LOG.info("A&AI transaction :");
531         LOG.info("Request Time : " + time + ", Method : " + method);
532         LOG.info("Request URL : "+ url);
533     }
534
535     protected void LOGwriteDateTrace(String name, String data) {
536         LOG.info("Input - " + name  + " : " + data);
537     }
538
539     protected void LOGwriteEndingTrace(int response_code, String comment, String data) {
540         LOG.info("Response code : " + response_code +", " + comment);
541         LOG.info(String.format("Response data : %s", data));
542     }
543
544     protected String encodeQuery(String param) throws UnsupportedEncodingException {
545         return URLEncoder.encode(param, "UTF-8").replace("+", "%20");
546     }
547
548     private String encodeCustomerURL(final String selection)
549     {
550         String encrypted_url = selection;
551         String apnpattern =
552                 "/aai/v11/business/customers/customer/(.+)/service-subscriptions/service-subscription/(.+)/service-instances/service-instance/(.+)/";
553         Pattern pattern = Pattern.compile(apnpattern);
554
555         try {
556             URL url =    new URL(selection);
557             String path = url.getPath();
558
559             LOG.info("Trying to match apn to <" + path + ">");
560
561             Matcher matcher = pattern.matcher(path);
562
563             while(matcher.find()) {
564                 String customer = matcher.group(1);
565                 String subscription = matcher.group(2);
566                 String service = matcher.group(3);
567
568                 encrypted_url = selection.replace(customer, encodeQuery(customer));
569                 encrypted_url = encrypted_url.replace(subscription, encodeQuery(subscription));
570                 encrypted_url = encrypted_url.replace(service, encodeQuery(service));
571             }
572         } catch (Exception e) {
573             LOG.warn("", e);
574         }
575
576         return encrypted_url;
577     }
578
579
580
581     /*
582      * (non-Javadoc)
583      * @see org.openecomp.sdnct.sli.aai.AAIClient#requestVServersData(java.lang.String, java.lang.String)
584      */
585     @Override
586     public Vserver requestVServerData(String tenantId, String vserverId, String cloudOwner, String cloudRegionId)    throws AAIServiceException {
587         Vserver response = null;
588
589         try {
590             AAIRequest request = AAIRequest.getRequestFromResource("vserver");
591             request.addRequestProperty("cloud-region.cloud-owner", cloudOwner);
592             request.addRequestProperty("cloud-region.cloud-region-id", cloudRegionId);
593             request.addRequestProperty("tenant.tenant-id", tenantId);
594             request.addRequestProperty("vserver.vserver-id", vserverId);
595
596             String rv = executor.get(request);
597             if(rv != null) {
598                 ObjectMapper mapper = getObjectMapper();
599                 response = mapper.readValue(rv, Vserver.class);
600             }
601         } catch(AAIServiceException aaiexc) {
602             throw aaiexc;
603         } catch (Exception exc) {
604             LOG.warn(Object.class.getClass().getEnclosingMethod().getName(), exc);
605             throw new AAIServiceException(exc);
606         }
607         return response;
608     }
609
610
611     //================== End of DvsSwitch =================
612     //==================== PhysicalLink ======================
613     @Override
614     public PhysicalLink  requestPhysicalLinkData(String linkName) throws AAIServiceException {
615         PhysicalLink response = null;
616
617         try {
618             AAIRequest request = AAIRequest.getRequestFromResource("physical-link");
619             request.addRequestProperty("physical-link.link-name", linkName);
620
621             String rv = executor.get(request);
622             if(rv != null) {
623                 ObjectMapper mapper = getObjectMapper();
624                 response = mapper.readValue(rv, PhysicalLink.class);
625             }
626         } catch(AAIServiceException aaiexc) {
627             throw aaiexc;
628         } catch (Exception exc) {
629             LOG.warn("requestPhysicalLinkData", exc);
630             throw new AAIServiceException(exc);
631         }
632         return response;
633     }
634
635     @Override
636     public boolean postPhysicalLinkData(String linkName, PhysicalLink data) throws AAIServiceException {
637         try {
638             AAIRequest request = AAIRequest.getRequestFromResource("physical-link");
639             request.addRequestProperty("physical-link.link-name", linkName);
640             request.setRequestObject(data);
641             Object response = executor.post(request);
642             return true;
643         } catch(AAIServiceException aaiexc) {
644             throw aaiexc;
645         } catch (Exception exc) {
646             LOG.warn(Object.class.getClass().getEnclosingMethod().getName(), exc);
647             throw new AAIServiceException(exc);
648         }
649     }
650
651     @Override
652     public boolean deletePhysicalLinkData(String linkName, String resourceVersion) throws AAIServiceException {
653         boolean response = false;
654
655         try {
656             AAIRequest request = AAIRequest.getRequestFromResource("physical-link");
657             request.addRequestProperty("physical-link.link-name", linkName);
658             response = executor.delete(request, resourceVersion);
659         } catch(AAIServiceException aaiexc) {
660             throw aaiexc;
661         } catch (Exception exc) {
662             LOG.warn("deletePhysicalLinkData", exc);
663             throw new AAIServiceException(exc);
664         }
665         return response;
666     }
667
668     public boolean deleteAAIEntity(URL url, String caller) throws AAIServiceException {
669
670         if(url ==  null) {
671             throw new NullPointerException();
672         }
673
674         boolean response = false;
675         InputStream inputStream = null;
676
677         try {
678             URL http_req_url =    url;
679
680             HttpURLConnection con = getConfiguredConnection(http_req_url, HttpMethod.DELETE);
681
682             LOGwriteFirstTrace("DELETE", http_req_url.toString());
683
684
685             // Check for errors
686             int responseCode = con.getResponseCode();
687             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
688                 inputStream = con.getInputStream();
689             } else {
690                 inputStream = con.getErrorStream();
691             }
692
693             // Process the response
694             LOG.debug("HttpURLConnection result:" + responseCode);
695             if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
696             BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
697             String line = null;
698
699             ObjectMapper mapper = getObjectMapper();
700
701             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
702                 StringBuilder stringBuilder = new StringBuilder();
703
704                 while( ( line = reader.readLine() ) != null ) {
705                     stringBuilder.append( line );
706                 }
707                 LOGwriteEndingTrace(responseCode, "SUCCESS", stringBuilder.toString());
708                 response = true;
709             } else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND ) {
710                 LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", "Entry does not exist.");
711                 response = false;
712             } else {
713                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
714                 LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
715                 throw new AAIServiceException(responseCode, errorresponse);
716             }
717
718         } catch(AAIServiceException aaiexc) {
719             throw aaiexc;
720         } catch (Exception exc) {
721             LOG.warn(caller, exc);
722             throw new AAIServiceException(exc);
723         } finally {
724             if(inputStream != null){
725                 try {
726                     inputStream.close();
727                 } catch(Exception exc) {
728
729                 }
730             }
731         }
732         return response;
733     }
734
735     /**
736      * Generic method to GET json data from an A&AI callback URL.
737      * Then convert that json to an Object.
738      * If successful the Object is attempted to be cast to the type parameter.
739      *
740      * @param key
741      *            callback url for A&AI
742      * @param type
743      *            the class of object that A&AI will return
744      * @return the object created from json or null if the response code is not 200
745      *
746      * @throws AAIServiceException
747      *             if empty or null key and or type or there's an error with processing
748      */
749     public <T> T dataChangeRequestAaiData(String key, Class<T> type) throws AAIServiceException {
750         if (StringUtils.isEmpty(key) || type == null) {
751             throw new AAIServiceException("Key is empty or null and or type is null");
752         }
753
754         T response = null;
755
756         SvcLogicContext ctx = new SvcLogicContext();
757         if(!key.contains(" = ") && isValidURL(key)) {
758             key = String.format("selflink = '%s'", key);
759         } else
760         if(!key.contains(" = ") && isValidURI(key)) {
761             key = String.format("resource-path = '%s'", key);
762         }
763
764         HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
765
766         SelfLinkRequest request = new SelfLinkRequest(type);
767         request.processRequestPathValues(nameValues);
768         Object obj = this.getExecutor().query(request, type);
769         response = type.cast(obj);
770
771         return response != null ? type.cast(response) : response;
772     }
773
774
775     public boolean sendNotify(NotifyEvent event, String serviceInstanceId, String pathCode) throws AAIServiceException {
776         InputStream inputStream = null;
777
778         try {
779
780             String selfLink = selflinkFqdn;
781             if(SELFLINK_AVPN != null && SELFLINK_AVPN.equals(pathCode)) {
782                 selfLink = selflinkAvpn;
783             }
784             selfLink = selfLink.replace("{service-instance-id}", encodeQuery(serviceInstanceId));
785             event.setSelflink(selfLink);
786
787             ObjectMapper mapper = getObjectMapper();
788             String json_text = mapper.writeValueAsString(event);
789
790             SSLSocketFactory sockFact = CTX.getSocketFactory();
791
792             String request_url = targetUri+ubb_notify_path;
793             URL http_req_url =    new URL(request_url);
794
795             HttpURLConnection con = getConfiguredConnection(http_req_url, HttpMethod.PUT);
796
797             if (json_text != null) {
798                 OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
799                 osw.write(json_text);
800                 osw.flush();
801                 osw.close();
802             }
803
804             LOGwriteFirstTrace("PUT", request_url);
805             LOGwriteDateTrace("NotifyEvent", json_text);
806
807             // Check for errors
808             int responseCode = con.getResponseCode();
809             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
810                 inputStream = con.getInputStream();
811             } else {
812                 inputStream = con.getErrorStream();
813             }
814
815             // Process the response
816             BufferedReader reader;
817             String line = null;
818             reader = new BufferedReader( new InputStreamReader( inputStream ) );
819
820             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
821                 StringBuilder stringBuilder = new StringBuilder();
822
823                 while( ( line = reader.readLine() ) != null ) {
824                     stringBuilder.append( line );
825                 }
826                 LOGwriteEndingTrace(responseCode, "SUCCESS", (stringBuilder.length() > 0) ? stringBuilder.toString() :
827                                                                                             "{no-data}");
828                 return true;
829             } else {
830                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
831                 LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
832
833                 throw new AAIServiceException(responseCode, errorresponse);
834             }
835         } catch(AAIServiceException aaiexc) {
836             throw aaiexc;
837         } catch (Exception exc) {
838             LOG.warn("sendNotify", exc);
839             throw new AAIServiceException(exc);
840         } finally {
841             try {
842                 if(inputStream != null)
843                 inputStream.close();
844             } catch (Exception exc) {
845
846             }
847         }
848     }
849
850     @Override
851     public SearchResults requestNodeQuery(String node_type, String entityIdentifier, String entityName) throws AAIServiceException {
852         SearchResults response = null;
853         InputStream inputStream = null;
854
855         try {
856             String request_url = targetUri+queryNodesPath;
857             request_url = request_url.replace("{node-type}", encodeQuery(node_type)) ;
858             request_url = request_url.replace("{entity-identifier}", entityIdentifier) ;
859             request_url = request_url.replace("{entity-name}", encodeQuery(entityName)) ;
860             URL http_req_url =    new URL(request_url);
861
862             HttpURLConnection con = getConfiguredConnection(http_req_url, HttpMethod.GET);
863
864             LOGwriteFirstTrace(HttpMethod.GET, http_req_url.toString());
865             LOGwriteDateTrace("node_type", node_type);
866             LOGwriteDateTrace("vnf_name", entityName);
867
868             // Check for errors
869             int responseCode = con.getResponseCode();
870             if (responseCode == HttpURLConnection.HTTP_OK) {
871                 inputStream = con.getInputStream();
872             } else {
873                 inputStream = con.getErrorStream();
874             }
875
876             // Process the response
877             LOG.debug("HttpURLConnection result:" + responseCode);
878             if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
879             BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
880
881             ObjectMapper mapper = getObjectMapper();
882
883             if (responseCode == HttpURLConnection.HTTP_OK) {
884                 response = mapper.readValue(reader, SearchResults.class);
885                 LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, "SUCCESS", mapper.writeValueAsString(response));
886             } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
887                 LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", "Entry does not exist.");
888                 return response;
889             } else {
890                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
891                 LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
892                 throw new AAIServiceException(responseCode, errorresponse);
893             }
894
895         } catch(AAIServiceException aaiexc) {
896             throw aaiexc;
897         } catch (Exception exc) {
898             LOG.warn("requestNodeQuery", exc);
899             throw new AAIServiceException(exc);
900         } finally {
901             if(inputStream != null){
902                 try {
903                     inputStream.close();
904                 } catch(Exception exc) {
905
906                 }
907             }
908         }
909         return response;
910
911     }
912
913
914     @Override
915     public String requestDataByURL(URL url) throws AAIServiceException {
916
917         if(url ==  null) {
918             throw new NullPointerException();
919         }
920
921         String response = null;
922         InputStream inputStream = null;
923
924         try {
925             URL http_req_url = url;
926
927             HttpURLConnection con = getConfiguredConnection(http_req_url, HttpMethod.GET);
928
929             LOGwriteFirstTrace(HttpMethod.GET, http_req_url.toString());
930
931             // Check for errors
932             int responseCode = con.getResponseCode();
933             if (responseCode == HttpURLConnection.HTTP_OK) {
934                 inputStream = con.getInputStream();
935             } else {
936                 inputStream = con.getErrorStream();
937             }
938
939             // Process the response
940             LOG.debug("HttpURLConnection result:" + responseCode);
941             if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
942             BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
943
944             ObjectMapper mapper = getObjectMapper();
945
946             if (responseCode == HttpURLConnection.HTTP_OK) {
947                 StringBuilder stringBuilder = new StringBuilder("\n");
948                 String line = null;
949                 while( ( line = reader.readLine() ) != null ) {
950                     stringBuilder.append( line );
951                 }
952                 LOG.info(stringBuilder.toString());
953 //                response = mapper.readValue(reader, String.class);
954                 response = stringBuilder.toString();
955                 LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, "SUCCESS", mapper.writeValueAsString(response));
956             } else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND ) {
957                 LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", "Entry does not exist.");
958                 response = null;
959             } else {
960                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
961                 LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
962                 throw new AAIServiceException(responseCode, errorresponse);
963             }
964
965         } catch(AAIServiceException aaiexc) {
966             throw aaiexc;
967         } catch (Exception exc) {
968             LOG.warn("requestNetworkVceData", exc);
969             throw new AAIServiceException(exc);
970         } finally {
971             if(inputStream != null){
972                 try {
973                     inputStream.close();
974                 } catch(Exception exc) {
975
976                 }
977             }
978         }
979         return response;
980     }
981
982
983     @Override
984     public GenericVnf requestGenericVnfeNodeQuery(String vnf_name) throws AAIServiceException {
985
986         if(vnf_name == null) {
987             throw new NullPointerException();
988         }
989
990         GenericVnf entity = null;
991         SearchResults resp = this.requestNodeQuery("generic-vnf", "vnf-name", vnf_name);
992
993         List<ResultData> resultDataList = resp.getResultData();
994
995         try {
996             for (ResultData datum : resultDataList) {
997                 String data_type = datum.getResourceType();
998                 URL url = new URL(datum.getResourceLink());
999                 entity = this.getResource(url.toString(), GenericVnf.class);
1000             }
1001         }
1002         catch (Exception e)
1003         {
1004             LOG.error("Caught exception", e);
1005         }
1006         return entity;
1007     }
1008
1009     @Override
1010     public Vserver requestVServerDataByURL(URL url) throws AAIServiceException {
1011
1012         if(url == null) {
1013             throw new NullPointerException();
1014         }
1015
1016         Vserver entity = null;
1017
1018         try {
1019                 entity = this.getResource(url.toString(), Vserver.class);
1020         } catch (AAIServiceException exc) {
1021             throw exc;
1022         } catch (Exception e) {
1023             throw new AAIServiceException(e);
1024         }
1025         return entity;
1026     }
1027
1028     @Override
1029     public URL requestVserverURLNodeQuery(String vserver_name) throws AAIServiceException {
1030
1031         if(vserver_name == null) {
1032             throw new NullPointerException();
1033         }
1034
1035         URL entity = null;
1036         SearchResults resp = this.requestNodeQuery("vserver", "vserver-name", vserver_name);
1037
1038         List<ResultData> resultDataList = resp.getResultData();
1039
1040         try {
1041             for (ResultData datum : resultDataList) {
1042                 String data_type = datum.getResourceType();
1043                 String resourceLink = datum.getResourceLink();
1044                 if(!resourceLink.isEmpty() && !resourceLink.toLowerCase().startsWith("http")) {
1045                     resourceLink = (new EchoRequest()).targetUri + resourceLink;
1046                 }
1047                 entity = new URL(resourceLink);
1048             }
1049         } catch (Exception e) {
1050             throw new AAIServiceException(e);
1051         }
1052         return entity;
1053     }
1054
1055     @Override
1056     public String getTenantIdFromVserverUrl(URL url) {
1057
1058         String path = url.getPath();
1059
1060         String[] split = path.split("/tenants/tenant/");
1061         if(split.length > 1) {
1062             split = split[1].split("/");
1063             return split[0];
1064         } else {
1065             return null;
1066         }
1067     }
1068
1069     @Override
1070     public String getCloudOwnerFromVserverUrl(URL url) {
1071
1072         String path = url.getPath();
1073
1074         String[] split = path.split("/cloud-regions/cloud-region/");
1075         if(split.length > 1) {
1076             split = split[1].split("/");
1077             return split[0];
1078         } else {
1079             return null;
1080         }
1081     }
1082
1083     @Override
1084     public String getCloudRegionFromVserverUrl(URL url) {
1085
1086         String path = url.getPath();
1087
1088         String[] split = path.split("/cloud-regions/cloud-region/");
1089         if(split.length > 1) {
1090             split = split[1].split("/");
1091             return split[1];
1092         } else {
1093             return null;
1094         }
1095     }
1096
1097     @Override
1098     public String getVServerIdFromVserverUrl(URL url, String tenantId) {
1099         String pattern =  networkVserverPath;
1100         pattern = pattern.replace("{tenant-id}", tenantId);
1101
1102         int end = pattern.indexOf("{vserver-id}");
1103         String prefix = pattern.substring(0, end);
1104
1105         String path = url.getPath();
1106
1107         if(path.startsWith(prefix)) {
1108             path = path.substring(prefix.length());
1109         }
1110
1111         return path;
1112     }
1113
1114     protected  Logger getLogger(){
1115         return LOG;
1116     }
1117
1118
1119     @Override
1120     public AAIExecutorInterface getExecutor() {
1121         return executor;
1122     }
1123
1124     /**
1125      * Creates a current time stamp in UTC i.e. 2016-03-08T22:15:13.343Z.
1126      * If there are any parameters the values are appended to the time stamp.
1127      *
1128      * @param parameters
1129      *            values to be appended to current time stamp
1130      * @param ctx
1131      *            used to set an attribute for a DG
1132      * @throws SvcLogicException
1133      */
1134     public void setStatusMethod(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
1135         if (ctx == null) {
1136             throw new SvcLogicException("SvcLogicContext is null.");
1137         }
1138
1139         StringBuilder sb = new StringBuilder();
1140         sb.append(String.format("%tFT%<tTZ", Calendar.getInstance(TimeZone.getTimeZone("Z")))).append(" - ");
1141
1142         for (Entry<String, String> entry : parameters.entrySet()) {
1143             sb.append(entry.getValue()).append("  ");
1144         }
1145
1146         if (sb.length() > 0) {
1147             sb.setLength(sb.length() - 2);
1148         }
1149
1150         ctx.setAttribute("aai-summary-status-message", sb.toString());
1151         LOG.info("aai-summary-status-message: " + sb.toString());
1152     }
1153
1154     /**
1155      * Generic method to GET json data from an A&AI using key structure.
1156      * Then convert that json to an Object.
1157      * If successful the Object is attempted to be cast to the type parameter.
1158      *
1159      * @param key
1160      *            key identifying the resource to be retrieved from AAI
1161      * @param type
1162      *            the class of object that A&AI will return
1163      * @return the object created from json or null if the response code is not 200
1164      *
1165      * @throws AAIServiceException
1166      *             if empty or null key and or type or there's an error with processing
1167      */
1168
1169     public <T> T getResource(String key, Class<T> type) throws AAIServiceException {
1170             if (StringUtils.isEmpty(key) || type == null) {
1171                 throw new AAIServiceException("Key is empty or null and or type is null");
1172             }
1173
1174             T response = null;
1175
1176             SvcLogicContext ctx = new SvcLogicContext();
1177             if(!key.contains(" = ")) {
1178                 if(isValidURL(key)) {
1179                     key = String.format("selflink = '%s'", key);
1180                 } else if(isValidURI(key)) {
1181                     key = String.format("resource-path = '%s'", key);
1182                 } else {
1183                     return response;
1184                 }
1185             }
1186
1187             HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
1188
1189             AAIRequest request = new SelfLinkRequest(type);
1190             if(nameValues.containsKey(PathRequest.RESOURCE_PATH.replaceAll("-", "_"))) {
1191                 request = new PathRequest(type);
1192             }
1193
1194             request.processRequestPathValues(nameValues);
1195             Object obj = this.getExecutor().query(request, type);
1196             response = type.cast(obj);
1197
1198             return response != null ? type.cast(response) : response;
1199      }
1200
1201      public boolean isValidURL(String url) {
1202
1203             URL u = null;
1204
1205             try {
1206                 u = new URL(url);
1207             } catch (MalformedURLException e) {
1208                 return false;
1209             }
1210
1211             try {
1212                 u.toURI();
1213             } catch (URISyntaxException e) {
1214                 return false;
1215             }
1216
1217             return true;
1218         }
1219
1220
1221     public boolean isValidURI(String url) {
1222
1223         URI u = null;
1224
1225         try {
1226             u = new URI(url);
1227         } catch (URISyntaxException e) {
1228             return false;
1229         }
1230
1231         return true;
1232     }
1233
1234
1235     protected boolean deleteList(URL httpReqUrl, String json_text) throws AAIServiceException {
1236         if(httpReqUrl ==  null) {
1237             throw new NullPointerException();
1238         }
1239
1240         boolean response = false;
1241         InputStream inputStream = null;
1242
1243         try {
1244             HttpURLConnection con = getConfiguredConnection(httpReqUrl, HttpMethod.DELETE);
1245
1246 //            SSLSocketFactory sockFact = CTX.getSocketFactory();
1247 //            con.setSSLSocketFactory( sockFact );
1248             if (json_text != null) {
1249                 OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
1250                 osw.write(json_text);
1251                 osw.flush();
1252                 osw.close();
1253             }
1254
1255             LOGwriteFirstTrace("DELETE", httpReqUrl.toString());
1256             LOGwriteDateTrace("data", json_text);
1257
1258             // Check for errors
1259             int responseCode = con.getResponseCode();
1260             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
1261                 inputStream = con.getInputStream();
1262             } else {
1263                 inputStream = con.getErrorStream();
1264             }
1265
1266             // Process the response
1267             LOG.debug("HttpURLConnection result:" + responseCode);
1268             if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
1269             BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
1270             String line = null;
1271
1272             ObjectMapper mapper = getObjectMapper();
1273
1274             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
1275                 StringBuilder stringBuilder = new StringBuilder();
1276
1277                 while( ( line = reader.readLine() ) != null ) {
1278                     stringBuilder.append( line );
1279                 }
1280                 LOGwriteEndingTrace(responseCode, "SUCCESS", stringBuilder.toString());
1281                 response = true;
1282             } else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND ) {
1283                 LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", "Entry does not exist.");
1284                 response = false;
1285             } else {
1286                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
1287                 LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
1288                 throw new AAIServiceException(responseCode, errorresponse);
1289             }
1290
1291         } catch(AAIServiceException aaiexc) {
1292             throw aaiexc;
1293         } catch (Exception exc) {
1294             LOG.warn("deleteList", exc);
1295             throw new AAIServiceException(exc);
1296         } finally {
1297             if(inputStream != null){
1298                 try {
1299                     inputStream.close();
1300                 } catch(Exception exc) {
1301
1302                 }
1303             }
1304         }
1305         return response;
1306     }
1307
1308     public static ObjectMapper getObjectMapper() {
1309         ObjectMapper mapper = new ObjectMapper();
1310         AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
1311         AnnotationIntrospector secondary = new JacksonAnnotationIntrospector();
1312         mapper.setAnnotationIntrospector(AnnotationIntrospector.pair(introspector, secondary));
1313         mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
1314         mapper.setSerializationInclusion(Include.NON_NULL);
1315         mapper.setSerializationInclusion(Include.NON_EMPTY);
1316         return mapper;
1317     }
1318
1319     public void logMetricRequest(String requestId, String targetServiceName, String msg, String path){
1320         String svcInstanceId = "";
1321         String svcName = null;
1322         String partnerName = null;
1323         String targetEntity = "A&AI";
1324         String targetVirtualEntity = null;
1325
1326         ml.logRequest(svcInstanceId, svcName, partnerName, targetEntity, targetServiceName, targetVirtualEntity, msg);
1327     }
1328
1329     public void logMetricResponse(String requestId, int responseCode, String responseDescription){
1330         ml.logResponse(responseCode < 400 ? "SUCCESS" : "FAILURE", Integer.toString(responseCode), responseDescription);
1331     }
1332
1333     public void logKeyError(String keys){
1334         LOG.error("Atleast one of the keys [" + keys + "] should have been populated. This will cause a NPE.");
1335     }
1336
1337
1338     /**
1339      * Retrofit code
1340      */
1341     @Override
1342     public QueryStatus save(String resource, boolean force, boolean localOnly, String key, Map<String, String> params, String prefix, SvcLogicContext ctx)
1343             throws SvcLogicException {
1344         String normResource = resource.split(":")[0];
1345
1346         switch(normResource){
1347         case "custom-query":
1348         case "formatted-query":
1349         case "generic-query":
1350         case "named-query":
1351         case "nodes-query":
1352         case "linterface":
1353         case "l2-bridge-sbg":
1354         case "l2-bridge-bgf":
1355         case "echo":
1356         case "test":
1357             break;
1358
1359         default:
1360             if(key.contains("selflink =")) {
1361                 break;
1362             }
1363             if(!key.contains(String.format("%s.", normResource))) {
1364                 key = rewriteKey(resource, key, ctx);
1365             }
1366         }
1367         return super.save(resource, force, localOnly, key, params, prefix, ctx);
1368     }
1369
1370     @Override
1371     public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx)
1372         throws SvcLogicException {
1373         String normResource = resource.split(":")[0];
1374
1375         switch(normResource){
1376                 case "custom-query":
1377         case "formatted-query":
1378         case "generic-query":
1379         case "named-query":
1380         case "nodes-query":
1381         case "linterface":
1382         case "l2-bridge-sbg":
1383         case "l2-bridge-bgf":
1384         case "echo":
1385         case "test":
1386             break;
1387
1388         default:
1389             if(key.contains("selflink =")) {
1390                 break;
1391             }
1392             if(!key.contains(String.format("%s.", normResource))) {
1393                 key = rewriteKey(resource, key, ctx);
1394             }
1395         }
1396
1397         return super.query(resource, localOnly, select, key, prefix, orderBy, ctx);
1398     }
1399
1400     @Override
1401     public QueryStatus delete(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
1402         String normResource = resource.split(":")[0];
1403
1404         switch(normResource){
1405                 case "custom-query":
1406         case "formatted-query":
1407         case "generic-query":
1408         case "named-query":
1409         case "nodes-query":
1410         case "linterface":
1411         case "l2-bridge-sbg":
1412         case "l2-bridge-bgf":
1413         case "echo":
1414         case "test":
1415             break;
1416
1417         default:
1418             if(key.contains("selflink =")) {
1419                 break;
1420             }
1421             if(!key.contains(String.format("%s.", normResource))) {
1422                 key = rewriteKey(resource, key, ctx);
1423             }
1424         }
1425
1426         return super.delete(resource, key, ctx);
1427     }
1428
1429     @Override
1430     public QueryStatus update(String resource, String key, Map<String, String> params, String prefix, SvcLogicContext ctx) throws SvcLogicException {
1431         String normResource = resource.split(":")[0];
1432
1433         switch(normResource){
1434                 case "custom-query":
1435         case "formatted-query":
1436         case "generic-query":
1437         case "named-query":
1438         case "nodes-query":
1439         case "linterface":
1440         case "l2-bridge-sbg":
1441         case "l2-bridge-bgf":
1442         case "echo":
1443         case "test":
1444             break;
1445
1446         default:
1447             if(key.contains("selflink =")) {
1448                 break;
1449             }
1450             if(!key.contains(String.format("%s.", normResource))) {
1451                 key = rewriteKey(resource, key, ctx);
1452             }
1453         }
1454
1455         return super.update(resource, key, params, prefix, ctx);
1456     }
1457
1458     private String rewriteKey(String resource, String key, SvcLogicContext ctx) {
1459         LOG.info("AAI Deprecation - the format of request key is no longer supported. Please rewrite this key : " + key);
1460
1461         String normResource = resource.split(":")[0];
1462         Class<? extends AAIDatum> clazz = null;
1463         try {
1464             clazz = AAIRequest.getClassFromResource(normResource) ;
1465         } catch (ClassNotFoundException e) {
1466             LOG.warn("AAIRequest does not support class: " + e.getMessage());
1467             return key;
1468         }
1469         if(clazz == null)
1470             return key;
1471
1472         List<String> fieldAnnotatedNames = new LinkedList<>();
1473
1474         Field[] fields = clazz.getDeclaredFields();
1475         for(Field field : fields) {
1476             String fieldName = field.getName();
1477             XmlElement annotation = field.getAnnotation(XmlElement.class);
1478             if(annotation == null)
1479                 continue;
1480             String primaryId = annotation.name();
1481             if("##default".equals(primaryId)) {
1482                 primaryId = fieldName;
1483             }
1484             fieldAnnotatedNames.add(primaryId);
1485         }
1486
1487         HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
1488         Set<String> keyset = nameValues.keySet();
1489         for(String keyName : keyset) {
1490             if(keyName.contains("."))
1491                 continue;
1492             else {
1493                 String tmpKeyName = keyName.replaceAll("_", "-");
1494                 String valueToSubstitute = String.format("%s =", tmpKeyName);
1495                 if(fieldAnnotatedNames.contains(tmpKeyName) && key.contains(valueToSubstitute)) {
1496                     key = key.replace(valueToSubstitute, String.format("%s.%s =", normResource, tmpKeyName));
1497                 }
1498             }
1499         }
1500
1501
1502         return key;
1503     }
1504
1505     @Override
1506     public String getPathTemplateForResource(String resoourceName, String keys, SvcLogicContext ctx) throws MalformedURLException {
1507         return AAIServiceUtils.getPathForResource(resoourceName, StringUtils.join(keys, " AND "), ctx);
1508     }
1509
1510     @Override
1511     public boolean isDeprecatedFormat(String resource, HashMap<String, String> nameValues) {
1512         return !AAIServiceUtils.isValidFormat(resource, nameValues);
1513     }
1514
1515     public AAIRequest getRequestFromResource(String resoourceName) {
1516         return AAIRequest.getRequestFromResource(resoourceName);
1517     }
1518
1519     /* (non-Javadoc)
1520      * @see org.onap.ccsdk.sli.core.sli.aai.haha#query(org.onap.ccsdk.sli.core.sli.aai.AAIRequest)
1521      */
1522     @Override
1523     public String query(AAIRequest request) throws AAIServiceException {
1524         return executor.get(request);
1525     }
1526
1527     /* (non-Javadoc)
1528      * @see org.onap.ccsdk.sli.core.sli.aai.haha#save(org.onap.ccsdk.sli.core.sli.aai.AAIRequest)
1529      */
1530     @Override
1531     public String save(AAIRequest request) throws AAIServiceException {
1532         return executor.post(request);
1533     }
1534
1535     public boolean update(AAIRequest request, String resourceVersion) throws AAIServiceException {
1536         return executor.patch(request, resourceVersion);
1537     }
1538
1539     /* (non-Javadoc)
1540      * @see org.onap.ccsdk.sli.core.sli.aai.haha#delete(org.onap.ccsdk.sli.core.sli.aai.AAIRequest, java.lang.String)
1541      */
1542     @Override
1543     public boolean delete(AAIRequest request, String resourceVersion) throws AAIServiceException {
1544         return executor.delete(request, resourceVersion);
1545     }
1546
1547 }