summaryrefslogtreecommitdiffstats
path: root/sparkybe-onap-service/src/main/java/org/onap/aai/sparky/search/EntityCountHistoryProcessor.java
diff options
context:
space:
mode:
Diffstat (limited to 'sparkybe-onap-service/src/main/java/org/onap/aai/sparky/search/EntityCountHistoryProcessor.java')
-rw-r--r--sparkybe-onap-service/src/main/java/org/onap/aai/sparky/search/EntityCountHistoryProcessor.java407
1 files changed, 407 insertions, 0 deletions
diff --git a/sparkybe-onap-service/src/main/java/org/onap/aai/sparky/search/EntityCountHistoryProcessor.java b/sparkybe-onap-service/src/main/java/org/onap/aai/sparky/search/EntityCountHistoryProcessor.java
new file mode 100644
index 0000000..4c393e1
--- /dev/null
+++ b/sparkybe-onap-service/src/main/java/org/onap/aai/sparky/search/EntityCountHistoryProcessor.java
@@ -0,0 +1,407 @@
+/**
+ * ============LICENSE_START===================================================
+ * SPARKY (AAI UI service)
+ * ============================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=====================================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.aai.sparky.search;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.component.restlet.RestletConstants;
+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.cl.mdc.MdcContext;
+import org.onap.aai.restclient.client.OperationResult;
+import org.onap.aai.sparky.dal.ElasticSearchAdapter;
+import org.onap.aai.sparky.inventory.EntityHistoryQueryBuilder;
+import org.onap.aai.sparky.logging.AaiUiMsgs;
+import org.onap.aai.sparky.util.NodeUtils;
+import org.onap.aai.sparky.util.RestletUtils;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.data.ClientInfo;
+import org.restlet.data.MediaType;
+import org.restlet.data.Status;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+/**
+ * Receives and processes Entity Count History requests
+ */
+public class EntityCountHistoryProcessor implements Processor {
+
+ private static final Logger LOG =
+ LoggerFactory.getInstance().getLogger(EntityCountHistoryProcessor.class);
+
+ private static final long serialVersionUID = 1L;
+
+ private ElasticSearchAdapter elasticSearchAdapter = null;
+ private ObjectMapper mapper;
+
+ private static final String SEARCH_PRETTY_STRING = "_search?pretty";
+ private static final String TYPE = "type";
+ private static final String TABLE = "table";
+ private static final String GRAPH = "graph";
+
+ private List<String> entityTypesToSummarize;
+ private List<String> vnfEntityTypes;
+
+ private String entityCountHistoryIndexName;
+
+ private boolean summarizeVnfs = false;
+
+ private RestletUtils restletUtils = new RestletUtils();
+
+ /**
+ * Instantiates a new Entity Count History
+ */
+
+ public EntityCountHistoryProcessor(ElasticSearchAdapter elasticSearchAdapter,
+ String entityTypesToSummarizeDelimitedList, String vnfEntityTypesDelimitedList, String entityCountHistoryIndexName) {
+
+ this.elasticSearchAdapter = elasticSearchAdapter;
+ this.entityCountHistoryIndexName = entityCountHistoryIndexName;
+
+ entityTypesToSummarize =
+ Arrays.asList(entityTypesToSummarizeDelimitedList.toLowerCase().split("[\\s,]+"));
+
+ vnfEntityTypes =
+ Arrays.asList(vnfEntityTypesDelimitedList.toLowerCase().split("[\\s,]+"));
+
+ summarizeVnfs = vnfEntityTypesDelimitedList.toLowerCase().contains("vnf");
+
+ this.mapper = new ObjectMapper();
+ this.mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
+ }
+
+ /**
+ * Processes a entity count history search request
+ *
+ * @param exchange The Exchange object generated by Apache Camel for the incoming request
+ */
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+
+ Request request = exchange.getIn().getHeader(RestletConstants.RESTLET_REQUEST, Request.class);
+ Response restletResponse =
+ exchange.getIn().getHeader(RestletConstants.RESTLET_RESPONSE, Response.class);
+
+ Object xTransactionId = exchange.getIn().getHeader("X-TransactionId");
+ if (xTransactionId == null) {
+ xTransactionId = NodeUtils.getRandomTxnId();
+ }
+
+ Object partnerName = exchange.getIn().getHeader("X-FromAppId");
+ if (partnerName == null) {
+ partnerName = "Browser";
+ }
+
+ /*
+ * Disables automatic Apache Camel Restlet component logging which prints out an undesirable log
+ * entry which includes client (e.g. browser) information
+ */
+ request.setLoggable(false);
+
+ ClientInfo clientInfo = request.getClientInfo();
+ MdcContext.initialize((String) xTransactionId, "AAI-UI", "", (String) partnerName,
+ clientInfo.getAddress() + ":" + clientInfo.getPort());
+
+ String typeParameter = getTypeParameter(exchange);
+
+ if (null != typeParameter && !typeParameter.isEmpty()) {
+ OperationResult operationResult = null;
+
+ try {
+ operationResult = getResults(restletResponse, typeParameter);
+ restletResponse.setEntity(operationResult.getResult(), MediaType.APPLICATION_JSON);
+ } catch (Exception exc) {
+ LOG.error(AaiUiMsgs.CONFIGURATION_ERROR, exc.getLocalizedMessage());
+ }
+ } else {
+ LOG.error(AaiUiMsgs.RESOURCE_NOT_FOUND, request.getOriginalRef().toString());
+ String errorMessage =
+ restletUtils.generateJsonErrorResponse("Unsupported request. Resource not found.");
+ restletResponse.setEntity(errorMessage, MediaType.APPLICATION_JSON);
+ restletResponse.setStatus(Status.CLIENT_ERROR_NOT_FOUND);
+ }
+
+ exchange.getOut().setBody(restletResponse);
+ }
+
+
+ /**
+ * Format line graph output
+ *
+ * @param results The results
+ * @return The JSON object
+ * @throws JsonProcessingException The JSON processing exception
+ */
+ public JSONObject formatLineGraphOutput(String results) throws JsonProcessingException {
+ Map<Long, Long> countByDateMap = new HashMap<Long, Long>();
+
+ JsonNode resultNode = null;
+
+ JSONObject finalResult = new JSONObject();
+ JSONArray finalResultArr = new JSONArray();
+
+ try {
+ resultNode = mapper.readTree(results);
+
+ final JsonNode bucketsNode = getBucketsNode(resultNode);
+
+ if (bucketsNode.isArray()) {
+
+ for (final JsonNode entityNode : bucketsNode) {
+ final JsonNode dateBucketNode = entityNode.get("group_by_date").get("buckets");
+ if (dateBucketNode.isArray()) {
+ for (final JsonNode dateBucket : dateBucketNode) {
+ Long date = dateBucket.get("key").asLong();
+ final JsonNode countBucketNode =
+ dateBucket.get("sort_by_date").get("hits").get("hits");
+
+ if (countBucketNode.isArray()) {
+ final JsonNode latestEntityNode = countBucketNode.get(0);
+
+ long currentCount = latestEntityNode.get("_source").get("count").asLong();
+ if (countByDateMap.containsKey(date)) {
+ // add to the value if map already contains this date
+ currentCount += countByDateMap.get(date);
+ }
+
+ countByDateMap.put(date, currentCount);
+ }
+ }
+
+ }
+ }
+ }
+
+ /*
+ * Sort the map by epoch timestamp
+ */
+ Map<Long, Long> sortedMap = new TreeMap<Long, Long>(countByDateMap);
+ for (Entry<Long, Long> entry : sortedMap.entrySet()) {
+ JSONObject dateEntry = new JSONObject();
+ dateEntry.put("date", entry.getKey());
+ dateEntry.put("count", entry.getValue());
+ finalResultArr.put(dateEntry);
+ }
+
+ } catch (Exception exc) {
+ LOG.warn(AaiUiMsgs.ERROR_BUILDING_SEARCH_RESPONSE, exc.getLocalizedMessage());
+ }
+
+ return finalResult.put("result", finalResultArr);
+ }
+
+ /**
+ * Format table output
+ *
+ * @param results The results
+ * @return The JSON object
+ * @throws JsonProcessingException The JSON processing exception
+ */
+ public JSONObject formatTableOutput(String results) throws JsonProcessingException {
+ JsonNode resultNode = null;
+
+ JSONObject finalResult = new JSONObject();
+ JSONArray entitiesArr = new JSONArray();
+
+ Map<String, Long> entityCountInTable = initializeEntityMap();
+
+ long vnfCount = 0;
+
+ try {
+ resultNode = mapper.readTree(results);
+
+ final JsonNode bucketsNode = getBucketsNode(resultNode);
+ if (bucketsNode.isArray()) {
+
+ for (final JsonNode entityNode : bucketsNode) {
+ String entityType = entityNode.get("key").asText();
+ boolean isAVnf = vnfEntityTypes.contains(entityType);
+ long countValue = 0;
+
+ if (isAVnf || entityCountInTable.get(entityType) != null) {
+ final JsonNode hitsBucketNode = entityNode.get("sort_by_date").get("hits").get("hits");
+ if (hitsBucketNode.isArray()) {
+ // the first bucket will be the latest
+ final JsonNode hitNode = hitsBucketNode.get(0);
+
+ countValue = hitNode.get("_source").get("count").asLong();
+
+ /*
+ * Special case: Add all the VNF types together to get aggregate count
+ */
+ if (summarizeVnfs && isAVnf) {
+ vnfCount += countValue;
+ countValue = vnfCount;
+ entityType = "vnf";
+ }
+
+ entityCountInTable.replace(entityType, countValue);
+ }
+ }
+
+ }
+ }
+ for (Entry<String, Long> entry : entityCountInTable.entrySet()) {
+ JSONObject entityType = new JSONObject();
+ entityType.put("key", entry.getKey());
+ entityType.put("doc_count", entry.getValue());
+ entitiesArr.put(entityType);
+ }
+
+ finalResult.put("result", entitiesArr);
+
+ } catch (Exception exc) {
+ LOG.warn(AaiUiMsgs.ERROR_BUILDING_RESPONSE_FOR_TABLE_QUERY, exc.getLocalizedMessage());
+ }
+
+ return finalResult;
+ }
+
+ /**
+ * Gets the results
+ *
+ * @param response The response
+ * @param type The type
+ * @return The results
+ */
+ public OperationResult getResults(Response response, String type) {
+ OperationResult operationResult = new OperationResult();
+
+ String reqPayload = EntityHistoryQueryBuilder.getQuery(type).toString();
+
+ try {
+ final String fullUrlStr = elasticSearchAdapter
+ .buildElasticSearchUrlForApi(entityCountHistoryIndexName, SEARCH_PRETTY_STRING);
+
+ OperationResult opResult = elasticSearchAdapter.doPost(fullUrlStr, reqPayload,
+ javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE);
+
+ JSONObject finalOutput = null;
+ if (type.equalsIgnoreCase(TABLE)) {
+ finalOutput = formatTableOutput(opResult.getResult());
+ } else if (type.equalsIgnoreCase(GRAPH)) {
+ finalOutput = formatLineGraphOutput(opResult.getResult());
+ }
+
+ if (finalOutput != null) {
+ response.setEntity(finalOutput.toString(), MediaType.APPLICATION_JSON);
+ operationResult.setResult(finalOutput.toString());
+ }
+ } catch (JsonProcessingException exc) {
+ restletUtils.handleRestletErrors(LOG, "Unable to map JSONpayload", exc, response);
+ }
+
+ return operationResult;
+ }
+
+ /**
+ * Gets the buckets node
+ *
+ * @param node The node
+ * @return The buckets node
+ * @throws Exception The exception
+ */
+ public JsonNode getBucketsNode(JsonNode node) throws Exception {
+ if (node.get("aggregations").get("group_by_entityType").get("buckets") != null) {
+ return node.get("aggregations").get("group_by_entityType").get("buckets");
+ } else {
+ throw new Exception("Failed to map JSON response");
+ }
+ }
+
+ /**
+ * Initialize entity map
+ *
+ * @return the map
+ */
+ private Map<String, Long> initializeEntityMap() {
+ Map<String, Long> entityMap = new HashMap<String, Long>();
+ for (String entity : entityTypesToSummarize) {
+ entityMap.put(entity, (long) 0);
+ }
+
+ return entityMap;
+ }
+
+ /**
+ * Extracts the "type" query parameter from the request URI
+ *
+ * @param exchange
+ * @return String containing the value of the "type" query parameter of the request. Returns null
+ * if no "type" parameter found
+ */
+ public String getTypeParameter(Exchange exchange) {
+ String typeParameter = null;
+
+ String requestUriParameterString = exchange.getIn().getHeader("CamelHttpQuery", String.class);
+
+ if (null != requestUriParameterString) {
+ String[] requestParameterParts = requestUriParameterString.split("&");
+
+ String[] parameter = requestParameterParts[0].split("=");
+ String currentParameterKey = parameter[0];
+
+ if (null != currentParameterKey && !currentParameterKey.isEmpty()) {
+ // Check if we're looking at the "type" parameter key
+ if (currentParameterKey.equals(TYPE)) {
+ boolean uriIncludesTypeParameterValue =
+ (parameter.length >= 2) && !parameter[1].isEmpty();
+
+ if (uriIncludesTypeParameterValue) {
+ String typeParameterValue = parameter[1];
+
+ // Is the parameter value one that we return data for?
+ if (typeParameterValue.equalsIgnoreCase(TABLE)
+ || typeParameterValue.equalsIgnoreCase(GRAPH)) {
+ typeParameter = typeParameterValue;
+ }
+ }
+ }
+ }
+ }
+
+ return typeParameter;
+ }
+
+
+ public void setRestletUtils(RestletUtils restletUtils) {
+ this.restletUtils = restletUtils;
+ }
+
+}