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