2 * ============LICENSE_START=======================================================
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23 package org.onap.aai.sparky.search;
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;
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;
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;
54 * From the given HTTP request, create vnf-search query for document store, and process document
58 public class VnfSearchService {
60 private static final String APP_JSON = MediaType.APPLICATION_JSON;
62 private static ElasticSearchConfig esConfig = null;
64 private static final Logger LOG = LoggerFactory.getInstance().getLogger(VnfSearchService.class);
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;
71 private static final String ENTITY_TYPE = "generic-vnf";
74 * Get Full URL for search using elastic search configuration.
77 * @return the full url
79 private static String getFullUrl(String indexName, String api) {
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);
87 * Process operation result.
90 * @param response the response
91 * @param opResult the op result
92 * @throws IOException Signals that an I/O exception has occurred.
94 private static void buildVnfQuerySearchResponse(String apiKey, HttpServletResponse response,
95 OperationResult opResult) throws IOException {
96 int resonseCode = opResult.getResultCode();
97 String result = opResult.getResult();
99 if (resonseCode > 300) {
100 setServletResponse(true, resonseCode, response, result);
104 if (result != null) {
105 JSONObject finalOutputToFe = new JSONObject();
106 JSONObject responseJson = new JSONObject(result);
108 if (apiKey.equalsIgnoreCase(ES_SUGGEST_API)) { // process suggestion results
110 String suggestionsKey = "vnfs";
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:
121 total = suggestionsArray.length();
123 finalOutputToFe.put("totalFound", total);
124 finalOutputToFe.put("suggestions", suggestionsArray);
125 } catch (Exception e) {
126 LOG.error(AaiUiMsgs.ERROR_GENERIC,
127 "Error parsing response from suggestions index. Response: " + result);
129 } else if (apiKey.equalsIgnoreCase(ES_COUNT_API)) {
131 String shardsKey = "_shards";
132 responseJson.remove(shardsKey);
133 finalOutputToFe = responseJson;
134 } catch (Exception e) {
135 LOG.error(AaiUiMsgs.ERROR_GENERIC,
136 "Error fetching total count response from aggregation index. Response: " + result);
138 } else if (apiKey.equalsIgnoreCase(ES_SEARCH_API)) {
140 JSONArray bucketsArray = (responseJson.getJSONObject("aggregations")
141 .getJSONObject("default").getJSONArray("buckets"));
143 for (int i = 0; i < bucketsArray.length(); i++) {
144 count += bucketsArray.getJSONObject(i).getInt("doc_count");
146 JSONObject content = new JSONObject();
147 content.put("totalChartHits", count);
148 content.put("buckets", bucketsArray);
149 finalOutputToFe.put("groupby_aggregation", content);
150 } catch (Exception e) {
151 LOG.error(AaiUiMsgs.ERROR_GENERIC,
152 "Error fetching group-by query response from aggregation index. Response: " + result);
156 setServletResponse(false, resonseCode, response, finalOutputToFe.toString());
161 * Sets the servlet response.
163 * @param isError the is error
164 * @param responseCode the response code
165 * @param response the response
166 * @param postPayload the post payload
167 * @throws IOException Signals that an I/O exception has occurred.
169 public static void setServletResponse(boolean isError, int responseCode,
170 HttpServletResponse response, String postPayload) throws IOException {
173 LOG.error(AaiUiMsgs.ERROR_PARSING_JSON_PAYLOAD_VERBOSE, postPayload);
176 response.setStatus(responseCode);
178 if (postPayload != null) {
179 response.setContentType(APP_JSON);
180 PrintWriter out = response.getWriter();
181 out.println(postPayload);
187 * Instantiates a new vnf search service.
189 public VnfSearchService() {
191 if (esConfig == null) {
192 esConfig = ElasticSearchConfig.getConfig();
195 if (search == null) {
196 search = new SearchAdapter();
198 } catch (Exception exc) {
199 LOG.error(AaiUiMsgs.CONFIGURATION_ERROR, "Search");
205 * Gets the suggestions results.
207 * @param response the response
208 * @param maxResults maximum number of suggestions
209 * @param queryStr query string
210 * @return the suggestions results
211 * @throws IOException Signals that an I/O exception has occurred.
213 public List<SuggestionEntity> getSuggestionsResults(QuerySearchEntity querySearchEntity,
214 int resultCountLimit) throws IOException {
215 List<SuggestionEntity> returnList = new ArrayList<SuggestionEntity>();
217 /* Create suggestions query */
218 JsonObject vnfSearch = VnfSearchQueryBuilder
219 .createSuggestionsQuery(String.valueOf(resultCountLimit), querySearchEntity.getQueryStr());
221 /* Parse suggestions response */
222 OperationResult opResult =
223 search.doPost(getFullUrl(esConfig.getAutosuggestIndexname(), ES_SUGGEST_API),
224 vnfSearch.toString(), APP_JSON);
226 String result = opResult.getResult();
228 if (!opResult.wasSuccessful()) {
229 LOG.error(AaiUiMsgs.ERROR_PARSING_JSON_PAYLOAD_VERBOSE, result);
233 JSONObject responseJson = new JSONObject(result);
234 String suggestionsKey = "vnfs";
235 JSONArray suggestionsArray = new JSONArray();
236 JSONArray suggestions = responseJson.getJSONArray(suggestionsKey);
237 if (suggestions.length() > 0) {
238 suggestionsArray = suggestions.getJSONObject(0).getJSONArray("options");
239 for (int i = 0; i < suggestionsArray.length(); i++) {
240 JSONObject querySuggestion = suggestionsArray.getJSONObject(i);
241 if (querySuggestion != null) {
242 SuggestionEntity responseSuggestion = new SuggestionEntity();
243 responseSuggestion.setText(querySuggestion.getString("text"));
244 responseSuggestion.setRoute("vnfSearch"); // TODO -> Read route from
245 // suggestive-search.properties instead of hard
248 .setHashId(NodeUtils.generateUniqueShaDigest(querySuggestion.getString("text")));
249 returnList.add(responseSuggestion);
258 * This method sets server response if lookup in ES has 0 count TODO: Change the response code to
259 * appropriate when FE-BE contract is finalized
263 public void setZeroCountResponse(HttpServletResponse response) throws IOException {
264 JSONObject payload = new JSONObject();
265 payload.put("count", 0);
266 setServletResponse(false, 200, response, payload.toString());
270 * This method sets server response if lookup in ES for an aggregation has 0 results TODO: Change
271 * the response code to appropriate when FE-BE contract is finalized
275 public void setEmptyAggResponse(HttpServletResponse response) throws IOException {
276 JSONObject aggPayload = new JSONObject();
277 aggPayload.put("totalChartHits", 0);
278 aggPayload.put("buckets", new JSONArray());
279 JSONObject payload = new JSONObject();
280 payload.append("groupby_aggregation", aggPayload);
281 setServletResponse(false, 200, response, payload.toString());
284 public HashQueryResponse getJSONPayloadFromHash(String hashId) {
286 HashQueryResponse hashQueryResponse = new HashQueryResponse();
287 JsonObjectBuilder hashSearch = Json.createObjectBuilder();
288 VnfSearchQueryBuilder.buildSingleTermCountQuery(hashSearch, "_id", hashId);
289 String hashSearchQuery = hashSearch.build().toString();
290 OperationResult opResult = search.doPost(
291 getFullUrl(esConfig.getAutosuggestIndexname(), ES_SEARCH_API), hashSearchQuery, APP_JSON);
292 hashQueryResponse.setOpResult(opResult);
294 if (opResult != null && opResult.wasSuccessful()) {
295 String result = opResult.getResult();
296 if (result != null) {
297 JSONObject responseJson = new JSONObject(result);
298 JSONArray hits = responseJson.getJSONObject("hits").getJSONArray("hits");
299 if (hits != null && hits.length() > 0) {
300 hashQueryResponse.setJsonPayload(hits.getJSONObject(0).getJSONObject("_source")
301 .getJSONObject("entity_suggest").toString());
305 return hashQueryResponse;
308 public void getEntityCountResults(HttpServletResponse response, Map<String, String> attributes)
310 // Create entity counts query
311 JsonObject vnfSearch = VnfSearchQueryBuilder.createEntityCountsQuery(attributes);
313 // Parse response for entity counts query
314 OperationResult opResult = search.doPost(
315 getFullUrl(TierSupportUiConstants.getAggregationIndexName(ENTITY_TYPE), ES_COUNT_API),
316 vnfSearch.toString(), APP_JSON);
317 buildVnfQuerySearchResponse(ES_COUNT_API, response, opResult);
320 public void getSummaryByEntityType(HttpServletResponse response, Map<String, String> attributes,
321 String groupByKey) throws IOException {
322 // Create query for summary by entity type
323 JsonObject vnfSearch =
324 VnfSearchQueryBuilder.createSummaryByEntityTypeQuery(attributes, groupByKey);
326 // Parse response for summary by entity type query
327 OperationResult opResult = search.doPost(
328 getFullUrl(TierSupportUiConstants.getAggregationIndexName(ENTITY_TYPE), ES_SEARCH_API),
329 vnfSearch.toString(), APP_JSON);
330 buildVnfQuerySearchResponse(ES_SEARCH_API, response, opResult);
333 public SearchAdapter getSearch() {
337 public void setSearch(SearchAdapter search) {
338 VnfSearchService.search = search;
341 public static ElasticSearchConfig getEsConfig() {
345 public static void setEsConfig(ElasticSearchConfig esConfig) {
346 VnfSearchService.esConfig = esConfig;