Merge "Fix Blocker/Critical sonar issues"
[aai/sparky-be.git] / src / main / java / org / onap / aai / sparky / search / VnfSearchService.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017 Amdocs
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  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  */
23 package org.onap.aai.sparky.search;
24
25 import java.io.IOException;
26 import java.io.PrintWriter;
27 import java.util.ArrayList;
28 import java.util.Date;
29 import java.util.List;
30 import java.util.Map;
31
32 import javax.json.Json;
33 import javax.json.JsonObject;
34 import javax.json.JsonObjectBuilder;
35 import javax.servlet.http.HttpServletResponse;
36 import javax.ws.rs.core.MediaType;
37
38 import org.json.JSONArray;
39 import org.json.JSONObject;
40 import org.onap.aai.sparky.dal.elasticsearch.HashQueryResponse;
41 import org.onap.aai.sparky.dal.elasticsearch.SearchAdapter;
42 import org.onap.aai.sparky.dal.elasticsearch.config.ElasticSearchConfig;
43 import org.onap.aai.sparky.dal.rest.OperationResult;
44 import org.onap.aai.sparky.logging.AaiUiMsgs;
45 import org.onap.aai.sparky.suggestivesearch.SuggestionEntity;
46 import org.onap.aai.sparky.util.NodeUtils;
47 import org.onap.aai.sparky.viewandinspect.config.TierSupportUiConstants;
48 import org.onap.aai.sparky.viewandinspect.entity.QuerySearchEntity;
49 import org.onap.aai.cl.api.Logger;
50 import org.onap.aai.cl.eelf.LoggerFactory;
51
52
53 /**
54  * From the given HTTP request, create vnf-search query for document store, and process document
55  * store response.
56  */
57
58 public class VnfSearchService {
59
60   private static final String APP_JSON = MediaType.APPLICATION_JSON;
61
62   private static ElasticSearchConfig esConfig = null;
63
64   private static final Logger LOG = LoggerFactory.getInstance().getLogger(VnfSearchService.class);
65
66   private static SearchAdapter search = null;
67   private static final String ES_SUGGEST_API = TierSupportUiConstants.ES_SUGGEST_API;
68   private static final String ES_COUNT_API = TierSupportUiConstants.ES_COUNT_API;
69   private static final String ES_SEARCH_API = TierSupportUiConstants.ES_SEARCH_API;
70
71   private static final String ENTITY_TYPE = "generic-vnf";
72
73   /**
74    * Get Full URL for search using elastic search configuration.
75    *
76    * @param api the api
77    * @return the full url
78    */
79   private static String getFullUrl(String indexName, String api) {
80
81     final String host = esConfig.getIpAddress();
82     final String port = esConfig.getHttpPort();
83     return String.format("http://%s:%s/%s/%s", host, port, indexName, api);
84   }
85
86   /**
87    * Process operation result.
88    *
89    * @param api the api
90    * @param response the response
91    * @param opResult the op result
92    * @throws IOException Signals that an I/O exception has occurred.
93    */
94   private static void buildVnfQuerySearchResponse(String apiKey, HttpServletResponse response,
95       OperationResult opResult) throws IOException {
96     int resonseCode = opResult.getResultCode();
97     String result = opResult.getResult();
98
99     if (resonseCode > 300) {
100       setServletResponse(true, resonseCode, response, result);
101       return;
102     }
103
104     if (result != null) {
105       JSONObject finalOutputToFe = new JSONObject();
106       JSONObject responseJson = new JSONObject(result);
107
108       if (apiKey.equalsIgnoreCase(ES_SUGGEST_API)) { // process suggestion results
109         try {
110           String suggestionsKey = "vnfs";
111           int total = 0;
112           JSONArray suggestionsArray = new JSONArray();
113           JSONArray suggestions = responseJson.getJSONArray(suggestionsKey);
114           if (suggestions.length() > 0) {
115             suggestionsArray = suggestions.getJSONObject(0).getJSONArray("options");
116             for (int i = 0; i < suggestionsArray.length(); i++) {
117               suggestionsArray.getJSONObject(i).remove("score"); // FE doesn't like this noise: 'score'
118             }
119
120             total = suggestionsArray.length();
121           }
122           finalOutputToFe.put("totalFound", total);
123           finalOutputToFe.put("suggestions", suggestionsArray);
124         } catch (Exception e) {
125           LOG.error(AaiUiMsgs.ERROR_GENERIC,
126               "Error parsing response from suggestions index. Response: " + result);
127         }
128       } else if (apiKey.equalsIgnoreCase(ES_COUNT_API)) {
129         try {
130           String shardsKey = "_shards";
131           responseJson.remove(shardsKey);
132           finalOutputToFe = responseJson;
133         } catch (Exception e) {
134           LOG.error(AaiUiMsgs.ERROR_GENERIC,
135               "Error fetching total count response from aggregation index. Response: " + result);
136         }
137       } else if (apiKey.equalsIgnoreCase(ES_SEARCH_API)) {
138         try {
139           JSONArray bucketsArray = (responseJson.getJSONObject("aggregations")
140               .getJSONObject("default").getJSONArray("buckets"));
141           int count = 0;
142           for (int i=0; i< bucketsArray.length(); i++) {
143             count += bucketsArray.getJSONObject(i).getInt("doc_count");
144           }
145           JSONObject content = new JSONObject();
146           content.put("totalChartHits", count);
147           content.put("buckets", bucketsArray);
148           finalOutputToFe.put("groupby_aggregation", content);
149         } catch (Exception e) {
150           LOG.error(AaiUiMsgs.ERROR_GENERIC,
151               "Error fetching group-by query response from aggregation index. Response: " + result);
152         }
153       }
154
155       setServletResponse(false, resonseCode, response, finalOutputToFe.toString());
156     }
157   }
158
159   /**
160    * Sets the servlet response.
161    *
162    * @param isError the is error
163    * @param responseCode the response code
164    * @param response the response
165    * @param postPayload the post payload
166    * @throws IOException Signals that an I/O exception has occurred.
167    */
168   public static void setServletResponse(boolean isError, int responseCode,
169       HttpServletResponse response, String postPayload) throws IOException {
170
171     if (isError) {
172       LOG.error(AaiUiMsgs.ERROR_PARSING_JSON_PAYLOAD_VERBOSE, postPayload);
173     }
174
175     response.setStatus(responseCode);
176
177     if (postPayload != null) {
178       response.setContentType(APP_JSON);
179       PrintWriter out = response.getWriter();
180       out.println(postPayload);
181       out.close();
182     }
183   }
184
185   /**
186    * Instantiates a new vnf search service.
187    */
188   public VnfSearchService() {
189     try {
190       if (esConfig == null) {
191         esConfig = ElasticSearchConfig.getConfig();
192       }
193
194       if (search == null) {
195         search = new SearchAdapter();
196       }
197     } catch (Exception exc) {
198       LOG.error(AaiUiMsgs.CONFIGURATION_ERROR, "Search");
199     }
200   }
201
202
203   /**
204    * Gets the suggestions results.
205    *
206    * @param response the response
207    * @param maxResults maximum number of suggestions
208    * @param queryStr query string
209    * @return the suggestions results
210    * @throws IOException Signals that an I/O exception has occurred.
211    */
212   public List<SuggestionEntity> getSuggestionsResults(QuerySearchEntity querySearchEntity, int resultCountLimit) throws IOException {
213     List<SuggestionEntity> returnList = new ArrayList<SuggestionEntity>();
214     
215     /* Create suggestions query */
216     JsonObject vnfSearch = VnfSearchQueryBuilder.createSuggestionsQuery(String.valueOf(resultCountLimit), querySearchEntity.getQueryStr());
217     
218     /* Parse suggestions response */
219     OperationResult opResult = search.doPost(getFullUrl(esConfig.getAutosuggestIndexname(), ES_SUGGEST_API), vnfSearch.toString(), APP_JSON);
220
221     String result = opResult.getResult();
222     
223     if (!opResult.wasSuccessful()) {
224       LOG.error(AaiUiMsgs.ERROR_PARSING_JSON_PAYLOAD_VERBOSE, result);
225       return returnList;
226     }
227     
228     JSONObject responseJson = new JSONObject(result);
229     String suggestionsKey = "vnfs";
230     JSONArray suggestionsArray = new JSONArray();
231     JSONArray suggestions = responseJson.getJSONArray(suggestionsKey);
232     if (suggestions.length() > 0) {
233       suggestionsArray = suggestions.getJSONObject(0).getJSONArray("options");
234       for (int i = 0; i < suggestionsArray.length(); i++) {
235         JSONObject querySuggestion = suggestionsArray.getJSONObject(i);
236         if (querySuggestion != null) {
237           SuggestionEntity responseSuggestion = new SuggestionEntity();
238           responseSuggestion.setText(querySuggestion.getString("text"));
239           responseSuggestion.setRoute("vnfSearch"); // TODO -> Read route from suggestive-search.properties instead of hard coding
240           responseSuggestion.setHashId(NodeUtils.generateUniqueShaDigest(querySuggestion.getString("text")));
241           returnList.add(responseSuggestion);
242         } 
243       }
244     }
245     return returnList;
246   }
247   
248   
249   /**
250    * This method sets server response if lookup in ES has 0 count
251    * TODO: Change the response code to appropriate when FE-BE contract is finalized
252  * @param response
253  */
254   public void setZeroCountResponse(HttpServletResponse response) throws IOException {
255           JSONObject payload = new JSONObject();
256           payload.put("count", 0);
257           setServletResponse(false, 200, response, payload.toString() );
258   }
259   
260   /**
261    * This method sets server response if lookup in ES for an aggregation has 0 results
262    * TODO: Change the response code to appropriate when FE-BE contract is finalized
263  * @param response
264  */
265   public void setEmptyAggResponse(HttpServletResponse response) throws IOException {
266     JSONObject aggPayload = new JSONObject(); 
267     aggPayload.put("totalChartHits", 0);
268     aggPayload.put("buckets", new JSONArray());
269     JSONObject payload = new JSONObject();
270     payload.append("groupby_aggregation", aggPayload);
271     setServletResponse(false, 200, response, payload.toString() );
272   }
273   
274   public HashQueryResponse getJSONPayloadFromHash(String hashId) {
275     
276     HashQueryResponse hashQueryResponse = new HashQueryResponse();
277     JsonObjectBuilder hashSearch = Json.createObjectBuilder();
278     VnfSearchQueryBuilder.buildSingleTermCountQuery(hashSearch, "_id", hashId);
279     String hashSearchQuery = hashSearch.build().toString();
280     OperationResult opResult = search.doPost(
281         getFullUrl(esConfig.getAutosuggestIndexname(), ES_SEARCH_API),
282         hashSearchQuery, APP_JSON);
283     hashQueryResponse.setOpResult(opResult);
284     
285     if(opResult != null && opResult.wasSuccessful()){
286       String result = opResult.getResult();
287       if (result != null) {
288         JSONObject responseJson = new JSONObject(result);
289         JSONArray hits =  responseJson.getJSONObject("hits").getJSONArray("hits");
290         if(hits != null && hits.length() > 0){
291           hashQueryResponse.setJsonPayload (hits.getJSONObject(0).getJSONObject("_source")
292               .getJSONObject("entity_suggest").toString());  
293         }
294       }
295     }
296     return hashQueryResponse;
297   }
298   
299   public void getEntityCountResults(HttpServletResponse response, Map<String, String> attributes)
300       throws IOException {
301     // Create entity counts query
302     JsonObject vnfSearch = VnfSearchQueryBuilder.createEntityCountsQuery(attributes);
303     
304     // Parse response for entity counts query
305     OperationResult opResult = search.doPost(
306         getFullUrl(TierSupportUiConstants.getAggregationIndexName(ENTITY_TYPE), ES_COUNT_API),
307         vnfSearch.toString(), APP_JSON);
308     buildVnfQuerySearchResponse(ES_COUNT_API, response, opResult);
309   }
310
311   public void getSummaryByEntityType(HttpServletResponse response, Map<String, String> attributes,
312       String groupByKey) throws IOException {
313     // Create query for summary by entity type
314     JsonObject vnfSearch =
315         VnfSearchQueryBuilder.createSummaryByEntityTypeQuery(attributes, groupByKey);
316     
317     // Parse response for summary by entity type query
318     OperationResult opResult = search.doPost(
319         getFullUrl(TierSupportUiConstants.getAggregationIndexName(ENTITY_TYPE), ES_SEARCH_API),
320         vnfSearch.toString(), APP_JSON);
321     buildVnfQuerySearchResponse(ES_SEARCH_API, response, opResult);
322   }
323
324   public SearchAdapter getSearch() {
325     return search;
326   }
327
328   public void setSearch(SearchAdapter search) {
329     VnfSearchService.search = search;
330   }
331
332   public static ElasticSearchConfig getEsConfig() {
333     return esConfig;
334   }
335
336   public static void setEsConfig(ElasticSearchConfig esConfig) {
337     VnfSearchService.esConfig = esConfig;
338   }
339
340   public static void main(String agrs[]) {
341     VnfSearchService vnfs = new VnfSearchService();
342     Date start = new Date();
343     Date end = start;
344   }
345
346 }