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: 'score'
120 total = suggestionsArray.length();
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);
128 } else if (apiKey.equalsIgnoreCase(ES_COUNT_API)) {
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);
137 } else if (apiKey.equalsIgnoreCase(ES_SEARCH_API)) {
139 JSONArray bucketsArray = (responseJson.getJSONObject("aggregations")
140 .getJSONObject("default").getJSONArray("buckets"));
142 for (int i=0; i< bucketsArray.length(); i++) {
143 count += bucketsArray.getJSONObject(i).getInt("doc_count");
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);
155 setServletResponse(false, resonseCode, response, finalOutputToFe.toString());
160 * Sets the servlet response.
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.
168 public static void setServletResponse(boolean isError, int responseCode,
169 HttpServletResponse response, String postPayload) throws IOException {
172 LOG.error(AaiUiMsgs.ERROR_PARSING_JSON_PAYLOAD_VERBOSE, postPayload);
175 response.setStatus(responseCode);
177 if (postPayload != null) {
178 response.setContentType(APP_JSON);
179 PrintWriter out = response.getWriter();
180 out.println(postPayload);
186 * Instantiates a new vnf search service.
188 public VnfSearchService() {
190 if (esConfig == null) {
191 esConfig = ElasticSearchConfig.getConfig();
194 if (search == null) {
195 search = new SearchAdapter();
197 } catch (Exception exc) {
198 LOG.error(AaiUiMsgs.CONFIGURATION_ERROR, "Search");
204 * Gets the suggestions results.
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.
212 public List<SuggestionEntity> getSuggestionsResults(QuerySearchEntity querySearchEntity, int resultCountLimit) throws IOException {
213 List<SuggestionEntity> returnList = new ArrayList<SuggestionEntity>();
215 /* Create suggestions query */
216 JsonObject vnfSearch = VnfSearchQueryBuilder.createSuggestionsQuery(String.valueOf(resultCountLimit), querySearchEntity.getQueryStr());
218 /* Parse suggestions response */
219 OperationResult opResult = search.doPost(getFullUrl(esConfig.getAutosuggestIndexname(), ES_SUGGEST_API), vnfSearch.toString(), APP_JSON);
221 String result = opResult.getResult();
223 if (!opResult.wasSuccessful()) {
224 LOG.error(AaiUiMsgs.ERROR_PARSING_JSON_PAYLOAD_VERBOSE, result);
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);
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
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() );
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
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() );
274 public HashQueryResponse getJSONPayloadFromHash(String hashId) {
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);
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());
296 return hashQueryResponse;
299 public void getEntityCountResults(HttpServletResponse response, Map<String, String> attributes)
301 // Create entity counts query
302 JsonObject vnfSearch = VnfSearchQueryBuilder.createEntityCountsQuery(attributes);
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);
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);
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);
324 public SearchAdapter getSearch() {
328 public void setSearch(SearchAdapter search) {
329 VnfSearchService.search = search;
332 public static ElasticSearchConfig getEsConfig() {
336 public static void setEsConfig(ElasticSearchConfig esConfig) {
337 VnfSearchService.esConfig = esConfig;
340 public static void main(String agrs[]) {
341 VnfSearchService vnfs = new VnfSearchService();
342 Date start = new Date();