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