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