Sonar Critical Fix
[dcaegen2/analytics/tca.git] / dcae-analytics-aai / src / main / java / org / openecomp / dcae / apod / analytics / aai / service / AAIEnrichmentClientImpl.java
1 /*
2  * ===============================LICENSE_START======================================
3  *  dcae-analytics
4  * ================================================================================
5  *    Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  *  Licensed under the Apache License, Version 2.0 (the "License");
8  *  you may not use this file except in compliance with the License.
9  *   You may obtain a copy of the License at
10  *
11  *          http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS,
15  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  *  ============================LICENSE_END===========================================
19  */
20
21 package org.openecomp.dcae.apod.analytics.aai.service;
22
23 import com.google.common.base.Optional;
24 import com.google.inject.Inject;
25 import com.google.inject.assistedinject.Assisted;
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.http.HttpEntity;
28 import org.apache.http.HttpResponse;
29 import org.apache.http.client.ResponseHandler;
30 import org.apache.http.client.methods.HttpGet;
31 import org.apache.http.client.utils.URIBuilder;
32 import org.apache.http.impl.client.CloseableHttpClient;
33 import org.apache.http.util.EntityUtils;
34 import org.openecomp.dcae.apod.analytics.aai.domain.config.AAIHttpClientConfig;
35 import org.openecomp.dcae.apod.analytics.common.utils.HTTPUtils;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 import java.io.IOException;
40 import java.net.URI;
41 import java.net.URISyntaxException;
42 import java.util.Iterator;
43 import java.util.Map;
44
45 import javax.annotation.Nonnull;
46
47
48 /**
49  * A concrete implementation for {@link AAIEnrichmentClient} which uses A&AI REST API to get A&AI Enrichment details
50  *
51  * @author Rajiv Singla . Creation Date: 9/18/2017.
52  */
53 public class AAIEnrichmentClientImpl implements AAIEnrichmentClient {
54
55     private static final Logger LOG = LoggerFactory.getLogger(AAIEnrichmentClientImpl.class);
56
57     private final CloseableHttpClient closeableHttpClient;
58     private final String aaiProtocol;
59     private final String aaiHost;
60     private final Integer aaiHostPortNumber;
61
62     @Inject
63     public AAIEnrichmentClientImpl(@Assisted final AAIHttpClientConfig aaiHttpClientConfig,
64                                    final AAIHttpClientFactory aaiHttpClientFactory) {
65         final AAIHttpClient aaiHttpClient = aaiHttpClientFactory.create(aaiHttpClientConfig);
66         closeableHttpClient = aaiHttpClient.getAAIHttpClient();
67         aaiProtocol = aaiHttpClientConfig.getAaiProtocol();
68         aaiHost = aaiHttpClientConfig.getAaiHost();
69         aaiHostPortNumber = aaiHttpClientConfig.getAaiHostPortNumber();
70     }
71
72
73     /**
74      * Provides enrichment details from A&AI API and returns them as string. If no enrichment lookup fails returns null
75      *
76      * @param aaiAPIPath A&AI API Path
77      * @param queryParams A&AI Query Params map
78      * @param headers A&AI HTTP Headers
79      *
80      * @return Enrichment details from A&AI API and returns them as string. If enrichment lookup fails returns null
81      */
82     @Override
83     public String getEnrichmentDetails(final String aaiAPIPath, final Map<String, String> queryParams,
84                                        final Map<String, String> headers) {
85
86         final URI enrichmentURI =
87                 createAAIEnrichmentURI(aaiProtocol, aaiHost, aaiHostPortNumber, aaiAPIPath, queryParams);
88
89         if (enrichmentURI == null) {
90             return null;
91         }
92
93         // create new get request
94         final HttpGet getRequest = new HttpGet(enrichmentURI);
95         // add http headers
96         for (Map.Entry<String, String> headersEntry : headers.entrySet()) {
97             getRequest.addHeader(headersEntry.getKey(), headersEntry.getValue());
98         }
99
100         Optional<String> enrichmentDetails = Optional.absent();
101         // execute http get request
102         try {
103             enrichmentDetails = closeableHttpClient.execute(getRequest, aaiResponseHandler());
104         } catch (IOException ex) {
105             LOG.error("Failed to get A&AI Enrichment Details for A&AI Enrichment URI: {} A&AI Error: {}",
106                     enrichmentURI, ex);
107         }
108
109         // return response
110         if (enrichmentDetails.isPresent()) {
111             return enrichmentDetails.get();
112         } else {
113             return null;
114         }
115     }
116
117     /**
118      * Create A&AI API Enrichment URI. If invalid URI - null will be returned
119      *
120      * @param protocol A&AI API protocol
121      * @param hostName A&AI API hostname
122      * @param portNumber A&AI API port number
123      * @param path A&AI API path
124      * @param queryParams A&AI API query parameters
125      *
126      * @return A&AI API Enrichment URI
127      */
128     private URI createAAIEnrichmentURI(final String protocol, final String hostName,
129                                        final Integer portNumber, final String path,
130                                        Map<String, String> queryParams) {
131
132         final URIBuilder uriBuilder = new URIBuilder().setScheme(protocol).setHost(hostName).setPort(portNumber)
133                 .setPath(path);
134
135         // creates custom query string which is not encoded
136         final String customQuery = createCustomQuery(queryParams);
137         if (StringUtils.isNoneBlank(customQuery)) {
138             uriBuilder.setCustomQuery(customQuery);
139         }
140
141         URI enrichmentURI = null;
142         try {
143             enrichmentURI = uriBuilder.build();
144         } catch (URISyntaxException e) {
145             LOG.error("URI Syntax Exception when creating A&AI Enrichment URI. " +
146                             "Protocol: {}, HostName: {}, Port: {}, Path: {}, Custom Query String: {}, Exception: {}",
147                     protocol, hostName, portNumber, path, customQuery, e);
148         }
149
150         LOG.trace("Created A&AI Enrichment URI: {}", enrichmentURI);
151         return enrichmentURI;
152     }
153
154     /**
155      * Creates Custom Query string to be used for A&AI API URI as A&AI currently does not expect encoded
156      * query params.
157      *
158      * @param queryParams query param map
159      *
160      * @return custom query string which does not encode query param values
161      */
162     private static String createCustomQuery(@Nonnull final Map<String, String> queryParams) {
163         final StringBuilder queryStringBuilder = new StringBuilder("");
164         final Iterator<Map.Entry<String, String>> queryParamIterator = queryParams.entrySet().iterator();
165         while (queryParamIterator.hasNext()) {
166             final Map.Entry<String, String> queryParamsEntry = queryParamIterator.next();
167             queryStringBuilder.append(queryParamsEntry.getKey());
168             queryStringBuilder.append("=");
169             queryStringBuilder.append(queryParamsEntry.getValue());
170             if (queryParamIterator.hasNext()) {
171                 queryStringBuilder.append("&");
172             }
173         }
174         return queryStringBuilder.toString();
175     }
176
177     /**
178      * Response Handler for A&AI Enrichment API
179      *
180      * @return Response Handler that
181      */
182     static ResponseHandler<Optional<String>> aaiResponseHandler() {
183         return new ResponseHandler<Optional<String>>() {
184             @Override
185             public Optional<String> handleResponse(final HttpResponse response) throws IOException {
186                 final int responseCode = response.getStatusLine().getStatusCode();
187                 final HttpEntity responseEntity = response.getEntity();
188                 if (HTTPUtils.isSuccessfulResponseCode(responseCode) && null != responseEntity) {
189                     final String aaiResponse = EntityUtils.toString(responseEntity);
190                     return Optional.of(aaiResponse);
191                 } else {
192                     String aaiResponse = responseEntity != null ? EntityUtils.toString(responseEntity) : "";
193                     LOG.error("Unable to fetch response from A&AI API. A&AI Response Code: {}, " +
194                             "A&AI Response Message: {}", responseCode, aaiResponse);
195                     return Optional.absent();
196                 }
197             }
198         };
199     }
200
201 }
202