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