2 * ============LICENSE_START===================================================
3 * SPARKY (AAI UI service)
4 * ============================================================================
5 * Copyright © 2017 AT&T Intellectual Property.
6 * Copyright © 2017 Amdocs
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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=====================================================
22 * ECOMP and OpenECOMP are trademarks
23 * and service marks of AT&T Intellectual Property.
25 package org.openecomp.sparky.search;
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;
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;
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;
56 * From the given HTTP request, create vnf-search query for document store, and process document
60 public class VnfSearchService {
62 private static final String APP_JSON = MediaType.APPLICATION_JSON;
64 private static ElasticSearchConfig esConfig = null;
66 private static final Logger LOG = LoggerFactory.getInstance().getLogger(VnfSearchService.class);
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;
73 private static final String ENTITY_TYPE = "generic-vnf";
76 * Get Full URL for search using elastic search configuration.
79 * @return the full url
81 private static String getFullUrl(String indexName, String api) {
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);
89 * Process operation result.
92 * @param response the response
93 * @param opResult the op result
94 * @throws IOException Signals that an I/O exception has occurred.
96 private static void buildVnfQuerySearchResponse(String apiKey, HttpServletResponse response,
97 OperationResult opResult) throws IOException {
98 int resonseCode = opResult.getResultCode();
99 String result = opResult.getResult();
101 if (resonseCode > 300) {
102 setServletResponse(true, resonseCode, response, result);
106 if (result != null) {
107 JSONObject finalOutputToFe = new JSONObject();
108 JSONObject responseJson = new JSONObject(result);
110 if (apiKey.equalsIgnoreCase(ES_SUGGEST_API)) { // process suggestion results
112 String suggestionsKey = "vnfs";
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'
122 total = suggestionsArray.length();
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);
130 } else if (apiKey.equalsIgnoreCase(ES_COUNT_API)) {
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);
139 } else if (apiKey.equalsIgnoreCase(ES_SEARCH_API)) {
141 JSONArray bucketsArray = (responseJson.getJSONObject("aggregations")
142 .getJSONObject("default").getJSONArray("buckets"));
144 for (int i=0; i< bucketsArray.length(); i++) {
145 count += bucketsArray.getJSONObject(i).getInt("doc_count");
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);
157 setServletResponse(false, resonseCode, response, finalOutputToFe.toString());
162 * Sets the servlet response.
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.
170 public static void setServletResponse(boolean isError, int responseCode,
171 HttpServletResponse response, String postPayload) throws IOException {
174 LOG.error(AaiUiMsgs.ERROR_PARSING_JSON_PAYLOAD_VERBOSE, postPayload);
177 response.setStatus(responseCode);
179 if (postPayload != null) {
180 response.setContentType(APP_JSON);
181 PrintWriter out = response.getWriter();
182 out.println(postPayload);
188 * Instantiates a new vnf search service.
190 public VnfSearchService() {
192 if (esConfig == null) {
193 esConfig = ElasticSearchConfig.getConfig();
196 if (search == null) {
197 search = new SearchAdapter();
199 } catch (Exception exc) {
200 LOG.error(AaiUiMsgs.CONFIGURATION_ERROR, "Search");
206 * Gets the suggestions results.
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.
214 public List<SuggestionEntity> getSuggestionsResults(QuerySearchEntity querySearchEntity, int resultCountLimit) throws IOException {
215 List<SuggestionEntity> returnList = new ArrayList<SuggestionEntity>();
217 /* Create suggestions query */
218 JsonObject vnfSearch = VnfSearchQueryBuilder.createSuggestionsQuery(String.valueOf(resultCountLimit), querySearchEntity.getQueryStr());
220 /* Parse suggestions response */
221 OperationResult opResult = search.doPost(getFullUrl(esConfig.getAutosuggestIndexname(), ES_SUGGEST_API), vnfSearch.toString(), APP_JSON);
223 String result = opResult.getResult();
225 if (!opResult.wasSuccessful()) {
226 LOG.error(AaiUiMsgs.ERROR_PARSING_JSON_PAYLOAD_VERBOSE, result);
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);
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
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() );
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
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() );
276 public HashQueryResponse getJSONPayloadFromHash(String hashId) {
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);
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());
298 return hashQueryResponse;
301 public void getEntityCountResults(HttpServletResponse response, Map<String, String> attributes)
303 // Create entity counts query
304 JsonObject vnfSearch = VnfSearchQueryBuilder.createEntityCountsQuery(attributes);
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);
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);
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);
326 public SearchAdapter getSearch() {
330 public void setSearch(SearchAdapter search) {
331 VnfSearchService.search = search;
334 public static ElasticSearchConfig getEsConfig() {
338 public static void setEsConfig(ElasticSearchConfig esConfig) {
339 VnfSearchService.esConfig = esConfig;
342 public static void main(String agrs[]) {
343 VnfSearchService vnfs = new VnfSearchService();
344 Date start = new Date();