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