06834c11ff4979e32eaf92718120f64f66f8262a
[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 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.openecomp.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                 String data_type = datum.getResourceType();
1000                 URL url = new URL(datum.getResourceLink());
1001                 entity = this.getResource(url.toString(), GenericVnf.class);
1002             }
1003         }
1004         catch (Exception e)
1005         {
1006             LOG.error("Caught exception", e);
1007         }
1008         return entity;
1009     }
1010
1011     @Override
1012     public Vserver requestVServerDataByURL(URL url) throws AAIServiceException {
1013
1014         if(url == null) {
1015             throw new NullPointerException();
1016         }
1017
1018         Vserver entity = null;
1019
1020         try {
1021                 entity = this.getResource(url.toString(), Vserver.class);
1022         } catch (AAIServiceException exc) {
1023             throw exc;
1024         } catch (Exception e) {
1025             throw new AAIServiceException(e);
1026         }
1027         return entity;
1028     }
1029
1030     @Override
1031     public URL requestVserverURLNodeQuery(String vserver_name) throws AAIServiceException {
1032
1033         if(vserver_name == null) {
1034             throw new NullPointerException();
1035         }
1036
1037         URL entity = null;
1038         SearchResults resp = this.requestNodeQuery("vserver", "vserver-name", vserver_name);
1039
1040         List<ResultData> resultDataList = resp.getResultData();
1041
1042         try {
1043             for (ResultData datum : resultDataList) {
1044                 String data_type = datum.getResourceType();
1045                 String resourceLink = datum.getResourceLink();
1046                 if(!resourceLink.isEmpty() && !resourceLink.toLowerCase().startsWith("http")) {
1047                     resourceLink = (new EchoRequest()).targetUri + resourceLink;
1048                 }
1049                 entity = new URL(resourceLink);
1050             }
1051         } catch (Exception e) {
1052             throw new AAIServiceException(e);
1053         }
1054         return entity;
1055     }
1056
1057     @Override
1058     public String getTenantIdFromVserverUrl(URL url) {
1059
1060         String path = url.getPath();
1061
1062         String[] split = path.split("/tenants/tenant/");
1063         if(split.length > 1) {
1064             split = split[1].split("/");
1065             return split[0];
1066         } else {
1067             return null;
1068         }
1069     }
1070
1071     @Override
1072     public String getCloudOwnerFromVserverUrl(URL url) {
1073
1074         String path = url.getPath();
1075
1076         String[] split = path.split("/cloud-regions/cloud-region/");
1077         if(split.length > 1) {
1078             split = split[1].split("/");
1079             return split[0];
1080         } else {
1081             return null;
1082         }
1083     }
1084
1085     @Override
1086     public String getCloudRegionFromVserverUrl(URL url) {
1087
1088         String path = url.getPath();
1089
1090         String[] split = path.split("/cloud-regions/cloud-region/");
1091         if(split.length > 1) {
1092             split = split[1].split("/");
1093             return split[1];
1094         } else {
1095             return null;
1096         }
1097     }
1098
1099     @Override
1100     public String getVServerIdFromVserverUrl(URL url, String tenantId) {
1101         String pattern =  networkVserverPath;
1102         pattern = pattern.replace("{tenant-id}", tenantId);
1103
1104         int end = pattern.indexOf("{vserver-id}");
1105         String prefix = pattern.substring(0, end);
1106
1107         String path = url.getPath();
1108
1109         if(path.startsWith(prefix)) {
1110             path = path.substring(prefix.length());
1111         }
1112
1113         return path;
1114     }
1115
1116     protected  Logger getLogger(){
1117         return LOG;
1118     }
1119
1120
1121     @Override
1122     public AAIExecutorInterface getExecutor() {
1123         return executor;
1124     }
1125
1126     /**
1127      * Creates a current time stamp in UTC i.e. 2016-03-08T22:15:13.343Z.
1128      * If there are any parameters the values are appended to the time stamp.
1129      *
1130      * @param parameters
1131      *            values to be appended to current time stamp
1132      * @param ctx
1133      *            used to set an attribute for a DG
1134      * @throws SvcLogicException
1135      */
1136     public void setStatusMethod(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
1137         if (ctx == null) {
1138             throw new SvcLogicException("SvcLogicContext is null.");
1139         }
1140
1141         StringBuilder sb = new StringBuilder();
1142         sb.append(String.format("%tFT%<tTZ", Calendar.getInstance(TimeZone.getTimeZone("Z")))).append(" - ");
1143
1144         for (Entry<String, String> entry : parameters.entrySet()) {
1145             sb.append(entry.getValue()).append("  ");
1146         }
1147
1148         if (sb.length() > 0) {
1149             sb.setLength(sb.length() - 2);
1150         }
1151
1152         ctx.setAttribute("aai-summary-status-message", sb.toString());
1153         LOG.info("aai-summary-status-message: " + sb.toString());
1154     }
1155
1156     /**
1157      * Generic method to GET json data from an A&AI using key structure.
1158      * Then convert that json to an Object.
1159      * If successful the Object is attempted to be cast to the type parameter.
1160      *
1161      * @param key
1162      *            key identifying the resource to be retrieved from AAI
1163      * @param type
1164      *            the class of object that A&AI will return
1165      * @return the object created from json or null if the response code is not 200
1166      *
1167      * @throws AAIServiceException
1168      *             if empty or null key and or type or there's an error with processing
1169      */
1170
1171     public <T> T getResource(String key, Class<T> type) throws AAIServiceException {
1172             if (StringUtils.isEmpty(key) || type == null) {
1173                 throw new AAIServiceException("Key is empty or null and or type is null");
1174             }
1175
1176             T response = null;
1177
1178             SvcLogicContext ctx = new SvcLogicContext();
1179             if(!key.contains(" = ")) {
1180                 if(isValidURL(key)) {
1181                     key = String.format("selflink = '%s'", key);
1182                 } else if(isValidURI(key)) {
1183                     key = String.format("resource-path = '%s'", key);
1184                 } else {
1185                     return response;
1186                 }
1187             }
1188
1189             HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
1190
1191             AAIRequest request = new SelfLinkRequest(type);
1192             if(nameValues.containsKey(PathRequest.RESOURCE_PATH.replaceAll("-", "_"))) {
1193                 request = new PathRequest(type);
1194             }
1195
1196             request.processRequestPathValues(nameValues);
1197             Object obj = this.getExecutor().query(request, type);
1198             response = type.cast(obj);
1199
1200             return response != null ? type.cast(response) : response;
1201      }
1202
1203      public boolean isValidURL(String url) {
1204
1205             URL u = null;
1206
1207             try {
1208                 u = new URL(url);
1209             } catch (MalformedURLException e) {
1210                 return false;
1211             }
1212
1213             try {
1214                 u.toURI();
1215             } catch (URISyntaxException e) {
1216                 return false;
1217             }
1218
1219             return true;
1220         }
1221
1222
1223     public boolean isValidURI(String url) {
1224
1225         URI u = null;
1226
1227         try {
1228             u = new URI(url);
1229         } catch (URISyntaxException e) {
1230             return false;
1231         }
1232
1233         return true;
1234     }
1235
1236
1237     protected boolean deleteList(URL httpReqUrl, String json_text) throws AAIServiceException {
1238         if(httpReqUrl ==  null) {
1239             throw new NullPointerException();
1240         }
1241
1242         boolean response = false;
1243         InputStream inputStream = null;
1244
1245         try {
1246             HttpURLConnection con = getConfiguredConnection(httpReqUrl, HttpMethod.DELETE);
1247
1248 //            SSLSocketFactory sockFact = CTX.getSocketFactory();
1249 //            con.setSSLSocketFactory( sockFact );
1250             if (json_text != null) {
1251                 OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
1252                 osw.write(json_text);
1253                 osw.flush();
1254                 osw.close();
1255             }
1256
1257             LOGwriteFirstTrace("DELETE", httpReqUrl.toString());
1258             LOGwriteDateTrace("data", json_text);
1259
1260             // Check for errors
1261             int responseCode = con.getResponseCode();
1262             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
1263                 inputStream = con.getInputStream();
1264             } else {
1265                 inputStream = con.getErrorStream();
1266             }
1267
1268             // Process the response
1269             LOG.debug("HttpURLConnection result:" + responseCode);
1270             if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
1271             BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
1272             String line = null;
1273
1274             ObjectMapper mapper = getObjectMapper();
1275
1276             if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
1277                 StringBuilder stringBuilder = new StringBuilder();
1278
1279                 while( ( line = reader.readLine() ) != null ) {
1280                     stringBuilder.append( line );
1281                 }
1282                 LOGwriteEndingTrace(responseCode, "SUCCESS", stringBuilder.toString());
1283                 response = true;
1284             } else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND ) {
1285                 LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", "Entry does not exist.");
1286                 response = false;
1287             } else {
1288                 ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
1289                 LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
1290                 throw new AAIServiceException(responseCode, errorresponse);
1291             }
1292
1293         } catch(AAIServiceException aaiexc) {
1294             throw aaiexc;
1295         } catch (Exception exc) {
1296             LOG.warn("deleteList", exc);
1297             throw new AAIServiceException(exc);
1298         } finally {
1299             if(inputStream != null){
1300                 try {
1301                     inputStream.close();
1302                 } catch(Exception exc) {
1303
1304                 }
1305             }
1306         }
1307         return response;
1308     }
1309
1310     public static ObjectMapper getObjectMapper() {
1311         ObjectMapper mapper = new ObjectMapper();
1312         AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
1313         AnnotationIntrospector secondary = new JacksonAnnotationIntrospector();
1314         mapper.setAnnotationIntrospector(AnnotationIntrospector.pair(introspector, secondary));
1315         mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
1316         mapper.setSerializationInclusion(Include.NON_NULL);
1317         mapper.setSerializationInclusion(Include.NON_EMPTY);
1318         return mapper;
1319     }
1320
1321     public void logMetricRequest(String requestId, String targetServiceName, String msg, String path){
1322         String svcInstanceId = "";
1323         String svcName = null;
1324         String partnerName = null;
1325         String targetEntity = "A&AI";
1326         String targetVirtualEntity = null;
1327
1328         ml.logRequest(svcInstanceId, svcName, partnerName, targetEntity, targetServiceName, targetVirtualEntity, msg);
1329     }
1330
1331     public void logMetricResponse(String requestId, int responseCode, String responseDescription){
1332         ml.logResponse(responseCode < 400 ? "COMPLETE" : "ERROR", Integer.toString(responseCode), responseDescription);
1333     }
1334
1335     public void logKeyError(String keys){
1336         LOG.error("Atleast one of the keys [" + keys + "] should have been populated. This will cause a NPE.");
1337     }
1338
1339
1340     /**
1341      * Retrofit code
1342      */
1343     @Override
1344     public QueryStatus save(String resource, boolean force, boolean localOnly, String key, Map<String, String> params, String prefix, SvcLogicContext ctx)
1345             throws SvcLogicException {
1346         String normResource = resource.split(":")[0];
1347
1348         switch(normResource){
1349         case "custom-query":
1350         case "formatted-query":
1351         case "generic-query":
1352         case "named-query":
1353         case "nodes-query":
1354         case "linterface":
1355         case "l2-bridge-sbg":
1356         case "l2-bridge-bgf":
1357         case "echo":
1358         case "test":
1359             break;
1360
1361         default:
1362             if(key.contains("selflink =")) {
1363                 break;
1364             }
1365             if(!key.contains(String.format("%s.", normResource))) {
1366                 key = rewriteKey(resource, key, ctx);
1367             }
1368         }
1369         return super.save(resource, force, localOnly, key, params, prefix, ctx);
1370     }
1371
1372     @Override
1373     public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx)
1374         throws SvcLogicException {
1375         String normResource = resource.split(":")[0];
1376
1377         switch(normResource){
1378         case "custom-query":
1379         case "formatted-query":
1380         case "generic-query":
1381         case "named-query":
1382         case "nodes-query":
1383         case "linterface":
1384         case "l2-bridge-sbg":
1385         case "l2-bridge-bgf":
1386         case "echo":
1387         case "test":
1388             break;
1389
1390         default:
1391             if(key.contains("selflink =")) {
1392                 break;
1393             }
1394             if(!key.contains(String.format("%s.", normResource))) {
1395                 key = rewriteKey(resource, key, ctx);
1396             }
1397         }
1398
1399         return super.query(resource, localOnly, select, key, prefix, orderBy, ctx);
1400     }
1401
1402     @Override
1403     public QueryStatus delete(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
1404         String normResource = resource.split(":")[0];
1405
1406         switch(normResource){
1407         case "custom-query":
1408         case "formatted-query":
1409         case "generic-query":
1410         case "named-query":
1411         case "nodes-query":
1412         case "linterface":
1413         case "l2-bridge-sbg":
1414         case "l2-bridge-bgf":
1415         case "echo":
1416         case "test":
1417             break;
1418
1419         default:
1420             if(key.contains("selflink =")) {
1421                 break;
1422             }
1423             if(!key.contains(String.format("%s.", normResource))) {
1424                 key = rewriteKey(resource, key, ctx);
1425             }
1426         }
1427
1428         return super.delete(resource, key, ctx);
1429     }
1430
1431     @Override
1432     public QueryStatus update(String resource, String key, Map<String, String> params, String prefix, SvcLogicContext ctx) throws SvcLogicException {
1433         String normResource = resource.split(":")[0];
1434
1435         switch(normResource){
1436         case "custom-query":
1437         case "formatted-query":
1438         case "generic-query":
1439         case "named-query":
1440         case "nodes-query":
1441         case "linterface":
1442         case "l2-bridge-sbg":
1443         case "l2-bridge-bgf":
1444         case "echo":
1445         case "test":
1446             break;
1447
1448         default:
1449             if(key.contains("selflink =")) {
1450                 break;
1451             }
1452             if(!key.contains(String.format("%s.", normResource))) {
1453                 key = rewriteKey(resource, key, ctx);
1454             }
1455         }
1456
1457         return super.update(resource, key, params, prefix, ctx);
1458     }
1459
1460     private String rewriteKey(String resource, String key, SvcLogicContext ctx) {
1461         LOG.info("AAI Deprecation - the format of request key is no longer supported. Please rewrite this key : " + key);
1462
1463         String normResource = resource.split(":")[0];
1464         Class<? extends AAIDatum> clazz = AAIRequest.getClassFromResource(normResource) ;
1465
1466         if(clazz == null)
1467             return key;
1468
1469         List<String> fieldAnnotatedNames = new LinkedList<>();
1470
1471         Field[] fields = clazz.getDeclaredFields();
1472         for(Field field : fields) {
1473             String fieldName = field.getName();
1474             XmlElement annotation = field.getAnnotation(XmlElement.class);
1475             if(annotation == null)
1476                 continue;
1477             String primaryId = annotation.name();
1478             if("##default".equals(primaryId)) {
1479                 primaryId = fieldName;
1480             }
1481             fieldAnnotatedNames.add(primaryId);
1482         }
1483
1484         HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
1485         Set<String> keyset = nameValues.keySet();
1486         for(String keyName : keyset) {
1487             if(keyName.contains("."))
1488                 continue;
1489             else {
1490                 String tmpKeyName = keyName.replaceAll("_", "-");
1491                 String valueToSubstitute = String.format("%s =", tmpKeyName);
1492                 if(fieldAnnotatedNames.contains(tmpKeyName) && key.contains(valueToSubstitute)) {
1493                     key = key.replace(valueToSubstitute, String.format("%s.%s =", normResource, tmpKeyName));
1494                 }
1495             }
1496         }
1497
1498
1499         return key;
1500     }
1501
1502     @Override
1503     public String getPathTemplateForResource(String resoourceName, String keys, SvcLogicContext ctx) throws MalformedURLException {
1504         return AAIServiceUtils.getPathForResource(resoourceName, StringUtils.join(keys, " AND "), ctx);
1505     }
1506
1507     @Override
1508     public boolean isDeprecatedFormat(String resource, Map<String, String> nameValues) {
1509         return !AAIServiceUtils.isValidFormat(resource, nameValues);
1510     }
1511
1512     public AAIRequest getRequestFromResource(String resoourceName) {
1513         return AAIRequest.getRequestFromResource(resoourceName);
1514     }
1515
1516     /* (non-Javadoc)
1517      * @see org.onap.ccsdk.sli.core.sli.aai.haha#query(org.onap.ccsdk.sli.core.sli.aai.AAIRequest)
1518      */
1519     @Override
1520     public String query(AAIRequest request) throws AAIServiceException {
1521         return executor.get(request);
1522     }
1523
1524     /* (non-Javadoc)
1525      * @see org.onap.ccsdk.sli.core.sli.aai.haha#save(org.onap.ccsdk.sli.core.sli.aai.AAIRequest)
1526      */
1527     @Override
1528     public String save(AAIRequest request) throws AAIServiceException {
1529         return executor.post(request);
1530     }
1531
1532     public boolean update(AAIRequest request, String resourceVersion) throws AAIServiceException {
1533         return executor.patch(request, resourceVersion);
1534     }
1535
1536     /* (non-Javadoc)
1537      * @see org.onap.ccsdk.sli.core.sli.aai.haha#delete(org.onap.ccsdk.sli.core.sli.aai.AAIRequest, java.lang.String)
1538      */
1539     @Override
1540     public boolean delete(AAIRequest request, String resourceVersion) throws AAIServiceException {
1541         return executor.delete(request, resourceVersion);
1542     }
1543
1544 }