enable suggestions to use search data service 49/36749/4
authorrenealr <reneal.rogers@amdocs.com>
Mon, 19 Mar 2018 14:48:51 +0000 (10:48 -0400)
committerrenealr <reneal.rogers@amdocs.com>
Mon, 19 Mar 2018 18:23:00 +0000 (14:23 -0400)
Added logic to ensure that suggestions are enabled using the search data
service

Issue-ID: AAI-895

Change-Id: If0bc6a56a4700a0f96584048676ee1a15db63592
Signed-off-by: renealr <reneal.rogers@amdocs.com>
src/main/java/org/onap/aai/sparky/aggregatevnf/search/AggregateSummaryProcessor.java
src/main/java/org/onap/aai/sparky/aggregatevnf/search/AggregateVnfSearchProvider.java
src/main/java/org/onap/aai/sparky/aggregatevnf/search/VnfSearchQueryBuilder.java
src/main/java/org/onap/aai/sparky/search/SearchServiceAdapter.java
src/test/java/org/onap/aai/sparky/aggregatevnf/search/AggregateVnfSearchProviderTest.java [new file with mode: 0644]
src/test/java/org/onap/aai/sparky/search/SearchServiceAdapterTest.java

index 12443e4..e98ffd5 100644 (file)
@@ -48,32 +48,37 @@ import org.restlet.data.Status;
 
 public class AggregateSummaryProcessor {
 
-  private static final Logger LOG = LoggerFactory.getInstance().getLogger(AggregateSummaryProcessor.class);
+  private static final Logger LOG =
+      LoggerFactory.getInstance().getLogger(AggregateSummaryProcessor.class);
 
   private static final String KEY_FILTERS = "filters";
 
   private ElasticSearchAdapter elasticSearchAdapter = null;
-  
+
   private String vnfAggregationIndexName;
   private FiltersConfig filtersConfig;
-  
-  public AggregateSummaryProcessor(ElasticSearchAdapter elasticSearchAdapter, FiltersConfig filtersConfig) {
+
+  public AggregateSummaryProcessor(ElasticSearchAdapter elasticSearchAdapter,
+      FiltersConfig filtersConfig) {
     this.elasticSearchAdapter = elasticSearchAdapter;
     this.filtersConfig = filtersConfig;
   }
-  
+
   public void setVnfAggregationIndexName(String vnfAggregationIndexName) {
     this.vnfAggregationIndexName = vnfAggregationIndexName;
   }
-  
+
   public void getFilteredAggregation(Exchange exchange) {
-    
-    Response response = exchange.getIn().getHeader(RestletConstants.RESTLET_RESPONSE, Response.class);
+
+    Response response =
+        exchange.getIn().getHeader(RestletConstants.RESTLET_RESPONSE, Response.class);
 
     Request request = exchange.getIn().getHeader(RestletConstants.RESTLET_REQUEST, Request.class);
 
-    /* Disables automatic Apache Camel Restlet component logging which prints out an undesirable log entry
-       which includes client (e.g. browser) information */
+    /*
+     * Disables automatic Apache Camel Restlet component logging which prints out an undesirable log
+     * entry which includes client (e.g. browser) information
+     */
     request.setLoggable(false);
 
     try {
@@ -95,29 +100,29 @@ public class AggregateSummaryProcessor {
         if (parameters.has(KEY_FILTERS)) {
           requestFilters = parameters.getJSONArray(KEY_FILTERS);
         } else {
-          
+
           JSONObject zeroResponsePayload = new JSONObject();
           zeroResponsePayload.put("count", 0);
           response.setStatus(Status.SUCCESS_OK);
           response.setEntity(zeroResponsePayload.toString(), MediaType.APPLICATION_JSON);
           exchange.getOut().setBody(response);
-          
+
           LOG.error(AaiUiMsgs.ERROR_FILTERS_NOT_FOUND);
           return;
         }
-      
+
         if (requestFilters != null && requestFilters.length() > 0) {
           List<JSONObject> filtersToQuery = new ArrayList<JSONObject>();
-          for(int i = 0; i < requestFilters.length(); i++) {
+          for (int i = 0; i < requestFilters.length(); i++) {
             JSONObject filterEntry = requestFilters.getJSONObject(i);
             filtersToQuery.add(filterEntry);
           }
-          
+
           String jsonResponsePayload = getVnfFilterAggregations(filtersToQuery);
           response.setStatus(Status.SUCCESS_OK);
           response.setEntity(jsonResponsePayload, MediaType.APPLICATION_JSON);
           exchange.getOut().setBody(response);
-          
+
         } else {
           String emptyResponse = getEmptyAggResponse();
           response.setStatus(Status.SUCCESS_OK);
@@ -127,10 +132,11 @@ public class AggregateSummaryProcessor {
         }
       }
     } catch (Exception exc) {
-      LOG.error(AaiUiMsgs.ERROR_GENERIC, "FilterProcessor failed to get filter list due to error = " + exc.getMessage());
+      LOG.error(AaiUiMsgs.ERROR_GENERIC,
+          "FilterProcessor failed to get filter list due to error = " + exc.getMessage());
     }
   }
-  
+
   private String getEmptyAggResponse() {
     JSONObject aggPayload = new JSONObject();
     aggPayload.put("totalChartHits", 0);
@@ -139,66 +145,65 @@ public class AggregateSummaryProcessor {
     payload.append("groupby_aggregation", aggPayload);
 
     return payload.toString();
-  }  
-  
+  }
+
   private static final String FILTER_ID_KEY = "filterId";
   private static final String FILTER_VALUE_KEY = "filterValue";
   private static final int DEFAULT_SHOULD_MATCH_SCORE = 1;
   private static final String VNF_FILTER_AGGREGATION = "vnfFilterAggregation";
 
-  
   private String getVnfFilterAggregations(List<JSONObject> filtersToQuery) throws IOException {
-    
+
     List<SearchFilter> searchFilters = new ArrayList<SearchFilter>();
-    for(JSONObject filterEntry : filtersToQuery) {
-      
+    for (JSONObject filterEntry : filtersToQuery) {
+
       String filterId = filterEntry.getString(FILTER_ID_KEY);
-      if(filterId != null) {
+      if (filterId != null) {
         SearchFilter filter = new SearchFilter();
         filter.setFilterId(filterId);
-        
-        if(filterEntry.has(FILTER_VALUE_KEY)) {
+
+        if (filterEntry.has(FILTER_VALUE_KEY)) {
           String filterValue = filterEntry.getString(FILTER_VALUE_KEY);
           filter.addValue(filterValue);
         }
-        
+
         searchFilters.add(filter);
       }
     }
-    
+
     // Create query for summary by entity type
-    JsonObject vnfSearch = FilterQueryBuilder.createCombinedBoolAndAggQuery(filtersConfig, searchFilters, DEFAULT_SHOULD_MATCH_SCORE);
+    JsonObject vnfSearch = FilterQueryBuilder.createCombinedBoolAndAggQuery(filtersConfig,
+        searchFilters, DEFAULT_SHOULD_MATCH_SCORE);
 
     // Parse response for summary by entity type query
     OperationResult opResult = elasticSearchAdapter.doPost(
         elasticSearchAdapter.buildElasticSearchUrlForApi(vnfAggregationIndexName,
             SparkyConstants.ES_SEARCH_API),
         vnfSearch.toString(), javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE);
-    
+
     return buildAggregateVnfResponseJson(opResult.getResult());
-    
+
   }
-  
+
   private String buildAggregateVnfResponseJson(String responseJsonStr) {
-    
+
     JSONObject finalOutputToFe = new JSONObject();
     JSONObject responseJson = new JSONObject(responseJsonStr);
-    
-    
+
     JSONObject hits = responseJson.getJSONObject("hits");
     int totalHits = hits.getInt("total");
     finalOutputToFe.put("total", totalHits);
-    
+
     JSONObject aggregations = responseJson.getJSONObject("aggregations");
     String[] aggKeys = JSONObject.getNames(aggregations);
     JSONObject aggregationsList = new JSONObject();
-    
-    for(String aggName : aggKeys) {
+
+    for (String aggName : aggKeys) {
       JSONObject aggregation = aggregations.getJSONObject(aggName);
       JSONArray buckets = aggregation.getJSONArray("buckets");
       aggregationsList.put(aggName, buckets);
     }
-    
+
     finalOutputToFe.put("aggregations", aggregationsList);
 
     return finalOutputToFe.toString();
index 6ff779d..3a1f5c4 100644 (file)
  */
 package org.onap.aai.sparky.aggregatevnf.search;
 
+import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
-import javax.json.JsonObject;
-import javax.ws.rs.core.MediaType;
-
-import org.json.JSONArray;
-import org.json.JSONObject;
 import org.onap.aai.cl.api.Logger;
 import org.onap.aai.cl.eelf.LoggerFactory;
 import org.onap.aai.restclient.client.OperationResult;
 import org.onap.aai.sparky.common.search.CommonSearchSuggestion;
-import org.onap.aai.sparky.dal.ElasticSearchAdapter;
 import org.onap.aai.sparky.logging.AaiUiMsgs;
+import org.onap.aai.sparky.search.SearchServiceAdapter;
 import org.onap.aai.sparky.search.api.SearchProvider;
 import org.onap.aai.sparky.search.entity.QuerySearchEntity;
 import org.onap.aai.sparky.search.entity.SearchSuggestion;
 import org.onap.aai.sparky.search.filters.entity.UiFilterValueEntity;
 import org.onap.aai.sparky.util.NodeUtils;
-import org.onap.aai.sparky.viewandinspect.config.SparkyConstants;
 
+import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
 
 public class AggregateVnfSearchProvider implements SearchProvider {
-  
-  private static final Logger LOG = LoggerFactory.getInstance().getLogger(AggregateVnfSearchProvider.class);
+
+  private static final Logger LOG =
+      LoggerFactory.getInstance().getLogger(AggregateVnfSearchProvider.class);
 
   private ObjectMapper mapper;
-  private ElasticSearchAdapter elasticSearchAdapter = null;
+  private SearchServiceAdapter searchServiceAdapter = null;
   private String autoSuggestIndexName;
   private String vnfSearchSuggestionRoute;
 
-  public AggregateVnfSearchProvider(ElasticSearchAdapter elasticSearchAdapter,
+  private static final String AUTO_SUGGEST_TEMPLATE = "{ " + "\"results-size\": %d,"
+      + "\"suggest-text\": \"%s\"," + "\"suggest-field\": \"%s\"" + "}";
+
+  private static final String KEY_SEARCH_RESULT = "searchResult";
+  private static final String KEY_HITS = "hits";
+  private static final String KEY_DOCUMENT = "document";
+  private static final String KEY_CONTENT = "content";
+  private static final String KEY_TEXT = "text";
+  private static final String KEY_FILTER_LIST = "filterList";
+
+  public AggregateVnfSearchProvider(SearchServiceAdapter searchServiceAdapter,
       String autoSuggestIndexName, String vnfSearchSuggestionRoute) {
     mapper = new ObjectMapper();
-    this.elasticSearchAdapter = elasticSearchAdapter;
+    this.searchServiceAdapter = searchServiceAdapter;
     this.autoSuggestIndexName = autoSuggestIndexName;
     this.vnfSearchSuggestionRoute = vnfSearchSuggestionRoute;
   }
-  
+
   public void setAutoSuggestIndexName(String autoSuggestIndexName) {
     this.autoSuggestIndexName = autoSuggestIndexName;
   }
@@ -70,58 +79,96 @@ public class AggregateVnfSearchProvider implements SearchProvider {
   public List<SearchSuggestion> search(QuerySearchEntity queryRequest) {
 
     List<SearchSuggestion> returnList = new ArrayList<SearchSuggestion>();
-
     try {
 
-      /* Create suggestions query */
-      JsonObject vnfSearch = VnfSearchQueryBuilder.createSuggestionsQuery(String.valueOf(queryRequest.getMaxResults()), queryRequest.getQueryStr());
+      final String fullUrlStr =
+          searchServiceAdapter.buildSuggestServiceQueryUrl(autoSuggestIndexName);
+      String postBody =
+          String.format(AUTO_SUGGEST_TEMPLATE, Integer.parseInt(queryRequest.getMaxResults()),
+              queryRequest.getQueryStr(), "entity_suggest");
+      OperationResult opResult =
+          searchServiceAdapter.doPost(fullUrlStr, postBody, "application/json");
+      if (opResult.getResultCode() == 200) {
+        returnList = generateSuggestionsForSearchResponse(opResult.getResult());
+      } else {
+        LOG.error(AaiUiMsgs.ERROR_PARSING_JSON_PAYLOAD_VERBOSE, opResult.getResult());
+        return returnList;
+      }
+    } catch (Exception exc) {
+      LOG.error(AaiUiMsgs.ERROR_GENERIC, "Search failed due to error = " + exc.getMessage());
+    }
 
-      /* Parse suggestions response */
-      OperationResult opResult = elasticSearchAdapter.doPost(
-          elasticSearchAdapter.buildElasticSearchUrlForApi(autoSuggestIndexName,
-              SparkyConstants.ES_SUGGEST_API),
-          vnfSearch.toString(), MediaType.APPLICATION_JSON_TYPE);
+    return returnList;
+  }
 
-      String result = opResult.getResult();
+  private List<SearchSuggestion> generateSuggestionsForSearchResponse(String operationResult) {
 
-      if (!opResult.wasSuccessful()) {
-        LOG.error(AaiUiMsgs.ERROR_PARSING_JSON_PAYLOAD_VERBOSE, result);
-        return returnList;
-      }
+    if (operationResult == null || operationResult.length() == 0) {
+      return null;
+    }
 
-      JSONObject responseJson = new JSONObject(result);
-      String suggestionsKey = "vnfs";
-      JSONArray suggestionsArray = new JSONArray();
-      JSONArray suggestions = responseJson.getJSONArray(suggestionsKey);
-      if (suggestions.length() > 0) {
-        suggestionsArray = suggestions.getJSONObject(0).getJSONArray("options");
-        for (int i = 0; i < suggestionsArray.length(); i++) {
-          JSONObject querySuggestion = suggestionsArray.getJSONObject(i);
-          if (querySuggestion != null) {
-            CommonSearchSuggestion responseSuggestion = new CommonSearchSuggestion();
-            responseSuggestion.setText(querySuggestion.getString("text"));
-            responseSuggestion.setRoute(vnfSearchSuggestionRoute);
-            responseSuggestion.setHashId(NodeUtils.generateUniqueShaDigest(querySuggestion.getString("text")));
-
-            // Extract filter list from JSON and add to response suggestion
-            JSONObject payload = querySuggestion.getJSONObject("payload");
-            if (payload.length() > 0) {
-              JSONArray filterList = payload.getJSONArray("filterList");
-              for (int filter = 0; filter < filterList.length(); filter++) {
-                String filterValueString = filterList.getJSONObject(filter).toString();
-                UiFilterValueEntity filterValue = mapper.readValue(filterValueString, UiFilterValueEntity.class);
-                responseSuggestion.getFilterValues().add(filterValue);
-              }
+    ObjectMapper mapper = new ObjectMapper();
+    JsonNode rootNode = null;
+    List<SearchSuggestion> suggestionEntityList = new ArrayList<SearchSuggestion>();
+
+    try {
+      rootNode = mapper.readTree(operationResult);
+      JsonNode hitsNode = rootNode.get(KEY_SEARCH_RESULT);
+      // Check if there are hits that are coming back
+      if (hitsNode.has(KEY_HITS)) {
+        ArrayNode hitsArray = (ArrayNode) hitsNode.get(KEY_HITS);
+
+        /*
+         * next we iterate over the values in the hit array elements
+         */
+        Iterator<JsonNode> nodeIterator = hitsArray.elements();
+        JsonNode entityNode = null;
+        CommonSearchSuggestion responseSuggestion = null;
+        JsonNode sourceNode = null;
+
+        while (nodeIterator.hasNext()) {
+          entityNode = nodeIterator.next();
+          String responseText = getValueFromNode(entityNode, KEY_TEXT);
+          // do the point transformation as we build the response?
+          responseSuggestion = new CommonSearchSuggestion();
+          responseSuggestion.setRoute(vnfSearchSuggestionRoute);
+          responseSuggestion.setText(responseText);
+          responseSuggestion.setHashId(NodeUtils.generateUniqueShaDigest(responseText));
+
+          sourceNode = entityNode.get(KEY_DOCUMENT).get(KEY_CONTENT);
+          if (sourceNode.has(KEY_FILTER_LIST)) {
+            ArrayNode filtersArray = (ArrayNode) sourceNode.get(KEY_FILTER_LIST);
+            for (int i = 0; i < filtersArray.size(); i++) {
+              String filterValueString = filtersArray.get(i).toString();
+              UiFilterValueEntity filterValue =
+                  mapper.readValue(filterValueString, UiFilterValueEntity.class);
+              responseSuggestion.getFilterValues().add(filterValue);
             }
-            returnList.add(responseSuggestion);
           }
+          suggestionEntityList.add(responseSuggestion);
         }
       }
-    } catch (Exception exc) {
-      LOG.error(AaiUiMsgs.ERROR_GENERIC, "Search failed due to error = " + exc.getMessage());
+    } catch (IOException exc) {
+      LOG.warn(AaiUiMsgs.SEARCH_RESPONSE_BUILDING_EXCEPTION, exc.getLocalizedMessage());
     }
+    return suggestionEntityList;
 
-    return returnList;
   }
-  
+
+  private String getValueFromNode(JsonNode node, String fieldName) {
+
+    if (node == null || fieldName == null) {
+      return null;
+    }
+
+    JsonNode valueNode = node.get(fieldName);
+
+    if (valueNode != null) {
+      return valueNode.asText();
+    }
+
+    return null;
+
+  }
+
 }
index a5b14bd..a71b36b 100644 (file)
@@ -30,13 +30,11 @@ import javax.json.JsonArrayBuilder;
 import javax.json.JsonObject;
 import javax.json.JsonObjectBuilder;
 
-
 /**
  * Build a JSON payload to send to elastic search to get vnf search data.
  */
 
 public class VnfSearchQueryBuilder {
-       
 
   /**
    * Creates the suggestions query.
@@ -136,8 +134,6 @@ public class VnfSearchQueryBuilder {
         Json.createObjectBuilder().add("must", mustBlobBuilder)));
   }
 
-
-
   public static JsonObject createSummaryByEntityTypeQuery(Map<String, String> attributes,
       String groupByKey) {
     JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
index f1ae6b1..1c64622 100644 (file)
@@ -44,6 +44,7 @@ import org.slf4j.MDC;
 public class SearchServiceAdapter {
 
   private static final String VALUE_QUERY = "query";
+  private static final String SUGGEST_QUERY = "suggest";
   
   private RestClient client;
   private RestEndpointConfig endpointConfig;
@@ -126,6 +127,17 @@ public class SearchServiceAdapter {
   public String buildSearchServiceQueryUrl(String indexName) {
     return buildSearchServiceUrlForApi(indexName, VALUE_QUERY);
   }
+  
+  /**
+   * Get Full URL for search
+   *
+   * @param api the api
+   * @param indexName
+   * @return the full url
+   */
+  public String buildSuggestServiceQueryUrl(String indexName) {
+    return buildSearchServiceUrlForApi(indexName, SUGGEST_QUERY);
+  }
 
   public String buildSearchServiceUrlForApi(String indexName, String api) {
     return String.format("https://%s:%s/services/search-data-service/%s/search/indexes/%s/%s",
diff --git a/src/test/java/org/onap/aai/sparky/aggregatevnf/search/AggregateVnfSearchProviderTest.java b/src/test/java/org/onap/aai/sparky/aggregatevnf/search/AggregateVnfSearchProviderTest.java
new file mode 100644 (file)
index 0000000..5a24edf
--- /dev/null
@@ -0,0 +1,62 @@
+package org.onap.aai.sparky.aggregatevnf.search;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+
+import javax.ws.rs.core.MediaType;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.onap.aai.restclient.client.OperationResult;
+import org.onap.aai.restclient.client.RestClient;
+import org.onap.aai.restclient.enums.RestAuthenticationMode;
+import org.onap.aai.sparky.dal.rest.config.RestEndpointConfig;
+import org.onap.aai.sparky.search.SearchServiceAdapter;
+import org.onap.aai.sparky.search.entity.QuerySearchEntity;
+
+public class AggregateVnfSearchProviderTest {
+
+  private AggregateVnfSearchProvider aggregateVnfSearchProvider;
+  private RestEndpointConfig restEndpointConfig;
+  private SearchServiceAdapter searchserviceAdapter;
+  private QuerySearchEntity querySearchEntity;
+  private String successResponsePayload;
+  private OperationResult successResult = null;
+  private String goodDrTargetUrl = "https://0.0.0.0:9502/ui-request/servicegraph";
+
+  @Before
+  public void init() throws Exception {
+
+    restEndpointConfig = new RestEndpointConfig();
+    successResponsePayload = "good-payload";
+    successResult = new OperationResult(200, successResponsePayload);
+    restEndpointConfig.setRestAuthenticationMode(RestAuthenticationMode.SSL_BASIC);
+    searchserviceAdapter = Mockito.mock(SearchServiceAdapter.class);
+    aggregateVnfSearchProvider =
+        new AggregateVnfSearchProvider(searchserviceAdapter, "auto-suggest", "schema");
+    querySearchEntity = new QuerySearchEntity();
+
+  }
+
+  @Test
+  public void updateValues() {
+
+    assertNotNull(aggregateVnfSearchProvider.search(querySearchEntity));
+    aggregateVnfSearchProvider.setAutoSuggestIndexName("auto-suggest-index-1");
+
+  }
+
+  @Test
+  public void testProxyMessage_Success() {
+    Mockito.when(searchserviceAdapter.doPost(Mockito.eq(goodDrTargetUrl), Mockito.anyString(),
+        Mockito.eq(MediaType.APPLICATION_JSON_TYPE.toString()))).thenReturn(successResult);
+  }
+
+}
index 7963528..90acfa4 100644 (file)
@@ -40,6 +40,7 @@ public class SearchServiceAdapterTest {
                assertNotNull(searchServiceAdapter.getTxnHeader());
                assertNotNull(searchServiceAdapter.buildSearchServiceQueryUrl("searchentity-localhost"));
                assertNotNull(searchServiceAdapter.buildSearchServiceUrlForApi("searchentity-localhost","2.0"));
+               assertNotNull(searchServiceAdapter.buildSuggestServiceQueryUrl("searchentity-localhost"));
                
                
        }