aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/onap/aai/datarouter/entity/SpikeAggregationEntity.java113
-rw-r--r--src/main/java/org/onap/aai/datarouter/policy/AbstractSpikeEntityEventProcessor.java685
-rw-r--r--src/main/java/org/onap/aai/datarouter/policy/EntityEventPolicy.java2
-rw-r--r--src/main/java/org/onap/aai/datarouter/policy/SpikeAggregateGenericVnfProcessor.java117
-rw-r--r--src/main/java/org/onap/aai/datarouter/policy/SpikeAutosuggestIndexProcessor.java254
-rw-r--r--src/main/java/org/onap/aai/datarouter/policy/SpikeEntitySearchProcessor.java160
-rw-r--r--src/main/java/org/onap/aai/datarouter/policy/SpikeEventPolicyConfig.java90
-rw-r--r--src/main/java/org/onap/aai/datarouter/util/SearchServiceAgent.java32
-rw-r--r--src/main/resources/aggregatevnf_schema.json17
-rw-r--r--src/main/resources/autosuggest_schema.json31
10 files changed, 1500 insertions, 1 deletions
diff --git a/src/main/java/org/onap/aai/datarouter/entity/SpikeAggregationEntity.java b/src/main/java/org/onap/aai/datarouter/entity/SpikeAggregationEntity.java
new file mode 100644
index 0000000..cb620d8
--- /dev/null
+++ b/src/main/java/org/onap/aai/datarouter/entity/SpikeAggregationEntity.java
@@ -0,0 +1,113 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * 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 is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.datarouter.entity;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.onap.aai.datarouter.util.NodeUtils;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * The Class SpikeAggregationEntity. Mimics functionality of SPIKEUI's AggregationEntity
+ */
+public class SpikeAggregationEntity implements DocumentStoreDataEntity, Serializable {
+ private String id;
+ private String link;
+ private String lastmodTimestamp;
+
+ public String getLink() {
+ return link;
+ }
+
+ public void setLink(String link) {
+ this.link = link;
+ }
+
+ @Override
+ public String getId() {
+ // make sure that deliveFields() is called before getting the id
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+
+ public String getLastmodTimestamp() {
+ return lastmodTimestamp;
+ }
+
+ public void setLastmodTimestamp(String lastmodTimestamp) {
+ this.lastmodTimestamp = lastmodTimestamp;
+ }
+
+
+ Map<String, String> attributes = new HashMap<>();
+ ObjectMapper mapper = new ObjectMapper();
+
+ /**
+ * Instantiates a new aggregation entity.
+ */
+ public SpikeAggregationEntity() {}
+
+ public void deriveFields(JsonNode uebPayload) {
+
+ this.setId(NodeUtils.generateUniqueShaDigest(link));
+ this.setLastmodTimestamp(Long.toString(System.currentTimeMillis()));
+ JsonNode entityNode = uebPayload.get("vertex").get("properties");
+ Iterator<Entry<String, JsonNode>> nodes = entityNode.fields();
+ while (nodes.hasNext()) {
+ Map.Entry<String, JsonNode> entry = (Map.Entry<String, JsonNode>) nodes.next();
+ attributes.put(entry.getKey(), entry.getValue().asText());
+ }
+ }
+
+
+
+ @Override
+ public String getAsJson() {
+ ObjectNode rootNode = mapper.createObjectNode();
+ rootNode.put("link", this.getLink());
+ rootNode.put("lastmodTimestamp", lastmodTimestamp);
+ for (Map.Entry<String, String> entry : this.attributes.entrySet()) {
+ String key = entry.getKey();
+ String value = entry.getValue();
+ rootNode.put(key, value);
+ }
+ return rootNode.toString();
+ }
+
+ @Override
+ public String toString() {
+ return "AggregationEntity [id=" + id + ", link=" + link + ", attributes=" + attributes
+ + ", mapper=" + mapper + "]";
+ }
+}
diff --git a/src/main/java/org/onap/aai/datarouter/policy/AbstractSpikeEntityEventProcessor.java b/src/main/java/org/onap/aai/datarouter/policy/AbstractSpikeEntityEventProcessor.java
new file mode 100644
index 0000000..9627365
--- /dev/null
+++ b/src/main/java/org/onap/aai/datarouter/policy/AbstractSpikeEntityEventProcessor.java
@@ -0,0 +1,685 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017-2018 Amdocs
+ * ================================================================================
+ * 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=========================================================
+ */
+package org.onap.aai.datarouter.policy;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.internal.helper.DatabaseField;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.json.JSONException;
+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.datarouter.entity.DocumentStoreDataEntity;
+import org.onap.aai.datarouter.entity.OxmEntityDescriptor;
+import org.onap.aai.datarouter.entity.SpikeEventEntity;
+import org.onap.aai.datarouter.entity.SpikeEventVertex;
+import org.onap.aai.datarouter.logging.EntityEventPolicyMsgs;
+import org.onap.aai.datarouter.util.EntityOxmReferenceHelper;
+import org.onap.aai.datarouter.util.ExternalOxmModelProcessor;
+import org.onap.aai.datarouter.util.OxmModelLoader;
+import org.onap.aai.datarouter.util.RouterServiceUtil;
+import org.onap.aai.datarouter.util.SearchServiceAgent;
+import org.onap.aai.restclient.client.Headers;
+import org.onap.aai.restclient.client.OperationResult;
+import org.onap.aai.restclient.rest.HttpUtil;
+import org.slf4j.MDC;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+
+public abstract class AbstractSpikeEntityEventProcessor implements Processor {
+
+ protected static final String additionalInfo = "Response of SpikeEntityEventPolicy";
+ private Collection<ExternalOxmModelProcessor> externalOxmModelProcessors;
+
+
+ protected final String ACTION_CREATE = "create";
+ private final String EVENT_VERTEX = "vertex";
+ public final static String ACTION_DELETE = "delete";
+ protected final String ACTION_UPDATE = "update";
+ protected final String PROCESS_SPIKE_EVENT = "Process Spike Event";
+ private final String OPERATION_KEY = "operation";
+
+ protected enum ResponseType {
+ SUCCESS, PARTIAL_SUCCESS, FAILURE;
+ }
+
+ private final List<String> SUPPORTED_ACTIONS =
+ Arrays.asList(ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE);
+
+ Map<String, DynamicJAXBContext> oxmVersionContextMap = new HashMap<>();
+ private String oxmVersion = null;
+
+ /** Agent for communicating with the Search Service. */
+ protected SearchServiceAgent searchAgent = null;
+ protected String searchIndexName;
+ protected String searchIndexSchema;
+ protected String createIndexUrl;
+
+ protected Logger logger;
+ protected Logger metricsLogger;
+ protected ObjectMapper mapper;
+
+
+ public AbstractSpikeEntityEventProcessor(SpikeEventPolicyConfig config)
+ throws FileNotFoundException {
+ mapper = new ObjectMapper();
+ LoggerFactory loggerFactoryInstance = LoggerFactory.getInstance();
+ logger = loggerFactoryInstance.getLogger(AbstractSpikeEntityEventProcessor.class.getName());
+ metricsLogger =
+ loggerFactoryInstance.getMetricsLogger(AbstractSpikeEntityEventProcessor.class.getName());
+
+ // Instantiate the agent that we will use for interacting with the Search Service.
+ searchAgent = new SearchServiceAgent(config.getSearchCertName(), config.getSearchKeystore(),
+ config.getSearchKeystorePwd(), AbstractSpikeEntityEventProcessor
+ .concatSubUri(config.getSearchBaseUrl(), config.getSearchEndpoint()),
+ config.getSearchEndpointDocuments(), logger);
+
+ this.externalOxmModelProcessors = new ArrayList<>();
+ this.externalOxmModelProcessors.add(EntityOxmReferenceHelper.getInstance());
+ OxmModelLoader.registerExternalOxmModelProcessors(externalOxmModelProcessors);
+ OxmModelLoader.loadModels();
+ oxmVersionContextMap = OxmModelLoader.getVersionContextMap();
+ parseLatestOxmVersion();
+ }
+
+ public String getCreateIndexUrl() {
+ return createIndexUrl;
+ }
+
+
+ public void setCreateIndexUrl(String createIndexUrl) {
+ this.createIndexUrl = createIndexUrl;
+ }
+
+ public String getSearchIndexName() {
+ return searchIndexName;
+ }
+
+
+ public void setSearchIndexName(String searchIndexName) {
+ this.searchIndexName = searchIndexName;
+ }
+
+ public String getSearchIndexSchema() {
+ return searchIndexSchema;
+ }
+
+
+ public void setSearchIndexSchema(String searchIndexSchema) {
+ this.searchIndexSchema = searchIndexSchema;
+ }
+
+ protected void startup() {
+
+ }
+
+ /*
+ * Load the UEB JSON payload, any errors would result to a failure case response.
+ */
+ protected JSONObject getUebContentAsJson(String payload, String contentKey) {
+
+ JSONObject uebJsonObj;
+ JSONObject uebObjContent;
+
+ try {
+ uebJsonObj = new JSONObject(payload);
+ } catch (JSONException e) {
+ logger.debug(EntityEventPolicyMsgs.UEB_INVALID_PAYLOAD_JSON_FORMAT, payload);
+ logger.error(EntityEventPolicyMsgs.UEB_INVALID_PAYLOAD_JSON_FORMAT, payload);
+ return null;
+ }
+
+ if (uebJsonObj.has(contentKey)) {
+ uebObjContent = uebJsonObj.getJSONObject(contentKey);
+ } else {
+ logger.debug(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, contentKey);
+ logger.error(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, contentKey);
+ return null;
+ }
+
+ return uebObjContent;
+ }
+ public abstract void process(Exchange exchange) throws Exception;
+
+
+ private void parseLatestOxmVersion() {
+ int latestVersion = -1;
+ if (oxmVersionContextMap != null) {
+ Iterator it = oxmVersionContextMap.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry pair = (Map.Entry) it.next();
+
+ String version = pair.getKey().toString();
+ int versionNum = Integer.parseInt(version.substring(1, version.length()));
+
+ if (versionNum > latestVersion) {
+ latestVersion = versionNum;
+ oxmVersion = pair.getKey().toString();
+ }
+
+ logger.info(EntityEventPolicyMsgs.PROCESS_OXM_MODEL_FOUND, pair.getKey().toString());
+ }
+ } else {
+ logger.error(EntityEventPolicyMsgs.PROCESS_OXM_MODEL_MISSING, "");
+ }
+ }
+
+
+
+ /**
+ * This will be used in: updateSearchEntityWithCrossEntityReference not this scope Convert object
+ * to json.
+ *
+ * @param object the object
+ * @param pretty the pretty
+ * @return the string
+ * @throws JsonProcessingException the json processing exception
+ *
+ * protected static String convertObjectToJson(Object object, boolean pretty) throws
+ * JsonProcessingException { ObjectWriter ow;
+ *
+ * if (pretty) { ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
+ *
+ * } else { ow = new ObjectMapper().writer(); }
+ *
+ * return ow.writeValueAsString(object); }
+ */
+
+ protected void returnWithError(Exchange exchange, String payload, String errorMsg) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_EVENT_NONVERBOSE, errorMsg);
+ logger.debug(EntityEventPolicyMsgs.DISCARD_EVENT_VERBOSE, errorMsg, payload);
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ }
+
+ private boolean isJSONValid(String test) {
+ try {
+ new JSONObject(test);
+ } catch (JSONException ex) {
+ return false;
+ }
+ return true;
+ }
+
+
+
+ protected String getSpikeEventAction(Exchange exchange, String uebPayload) {
+ JSONObject mainJson = new JSONObject(uebPayload);
+ String action = mainJson.getString(OPERATION_KEY);
+ if (action == null || !SUPPORTED_ACTIONS.contains(action.toLowerCase())) {
+ logger.debug(EntityEventPolicyMsgs.DISCARD_EVENT_VERBOSE,
+ "Unrecognized action '" + action + "'", uebPayload);
+ logger.error(EntityEventPolicyMsgs.DISCARD_EVENT_NONVERBOSE,
+ "Unrecognized action '" + action + "'");
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return null;
+ }
+ return action;
+ }
+
+ protected String getExchangeBody(Exchange exchange) {
+ String uebPayload = exchange.getIn().getBody().toString();
+ if (uebPayload == null || !isJSONValid(uebPayload)) {
+ uebPayload = exchange.getIn().getBody(String.class);
+ if (uebPayload == null || !isJSONValid(uebPayload)) {
+ returnWithError(exchange, uebPayload, "Invalid Payload");
+ return null;
+ }
+ }
+ return uebPayload;
+ }
+
+ protected SpikeEventVertex populateEventVertex(Exchange exchange, String uebPayload)
+ throws Exception {
+
+ // Load the UEB payload data, any errors will result in a failure and discard
+
+ JSONObject spikeObjVertex = getUebContentAsJson(uebPayload, EVENT_VERTEX);
+ if (spikeObjVertex == null) {
+ returnWithError(exchange, uebPayload, "Payload is missing " + EVENT_VERTEX);
+ return null;
+ }
+
+ SpikeEventVertex eventVertex = initializeSpikeEventVertex(spikeObjVertex.toString());
+ return eventVertex;
+ }
+
+ protected DynamicJAXBContext readOxm(Exchange exchange, String uebPayload) {
+ DynamicJAXBContext oxmJaxbContext = loadOxmContext(oxmVersion.toLowerCase());
+ if (oxmJaxbContext == null) {
+ logger.error(EntityEventPolicyMsgs.OXM_VERSION_NOT_SUPPORTED, oxmVersion);
+ logger.debug(EntityEventPolicyMsgs.DISCARD_EVENT_VERBOSE, "OXM version mismatch", uebPayload);
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return null;
+ }
+ return oxmJaxbContext;
+ }
+
+
+ protected String getEntityType(Exchange exchange, SpikeEventVertex eventVertex,
+ String uebPayload) {
+
+ String entityType = eventVertex.getType();
+ if (entityType == null || entityType.isEmpty()) {
+ logger.debug(EntityEventPolicyMsgs.DISCARD_EVENT_VERBOSE,
+ "Payload header missing entity type", uebPayload);
+ logger.error(EntityEventPolicyMsgs.DISCARD_EVENT_NONVERBOSE,
+ "Payload header missing entity type");
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return null;
+ }
+ return entityType;
+ }
+
+
+
+ protected String getEntityLink(Exchange exchange, SpikeEventVertex eventVertex,
+ String uebPayload) {
+ String entityKey = eventVertex.getKey();
+ if (entityKey == null || entityKey.isEmpty()) {
+ logger.debug(EntityEventPolicyMsgs.DISCARD_EVENT_VERBOSE, "Payload vertex missing entity key",
+ uebPayload);
+ logger.error(EntityEventPolicyMsgs.DISCARD_EVENT_NONVERBOSE,
+ "Payload vertex missing entity key");
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return null;
+ }
+ //EntityLink never can be null if entityKey is not null. no need to check
+ return eventVertex.getEntityLink();
+
+ }
+
+
+
+ /*
+ * Use the OXM Model to determine the primary key field name based on the entity-type
+ */
+ protected SpikeEventEntity populateSpikeEventEntity(Exchange exchange,
+ SpikeEventEntity spikeEventEntity, DynamicJAXBContext oxmJaxbContext, String entityType,
+ String action, String uebPayload, String oxmEntityType, List<String> searchableAttr) {
+
+ String entityPrimaryKeyFieldName =
+ getEntityPrimaryKeyFieldName(oxmJaxbContext, uebPayload, oxmEntityType, entityType);
+ if (entityPrimaryKeyFieldName == null) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_EVENT_NONVERBOSE,
+ "Payload missing primary key attribute");
+ logger.debug(EntityEventPolicyMsgs.DISCARD_EVENT_VERBOSE,
+ "Payload missing primary key attribute", uebPayload);
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return null;
+ }
+ String entityPrimaryKeyFieldValue = lookupValueUsingKey(uebPayload, entityPrimaryKeyFieldName);
+ if (entityPrimaryKeyFieldValue.isEmpty()) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_EVENT_NONVERBOSE,
+ "Payload missing primary value attribute");
+ logger.debug(EntityEventPolicyMsgs.DISCARD_EVENT_VERBOSE,
+ "Payload missing primary value attribute", uebPayload);
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return null;
+ }
+
+
+ if (!getSearchTags(spikeEventEntity, searchableAttr, uebPayload, action)) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_EVENT_NONVERBOSE,
+ "Payload missing searchable attribute for entity type '" + entityType + "'");
+ logger.debug(EntityEventPolicyMsgs.DISCARD_EVENT_VERBOSE,
+ "Payload missing searchable attribute for entity type '" + entityType + "'", uebPayload);
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return null;
+ }
+ spikeEventEntity.setEntityPrimaryKeyName(entityPrimaryKeyFieldName);
+ spikeEventEntity.setEntityPrimaryKeyValue(entityPrimaryKeyFieldName);
+
+ try {
+ spikeEventEntity.deriveFields();
+
+ } catch (NoSuchAlgorithmException e) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_EVENT_VERBOSE, "Cannot create unique SHA digest");
+ logger.debug(EntityEventPolicyMsgs.DISCARD_EVENT_VERBOSE, "Cannot create unique SHA digest",
+ uebPayload);
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return null;
+ }
+ return spikeEventEntity;
+ }
+
+ protected void setResponse(Exchange exchange, ResponseType responseType, String additionalInfo) {
+
+ exchange.getOut().setHeader("ResponseType", responseType.toString());
+ exchange.getOut().setBody(additionalInfo);
+ }
+
+
+ protected String getOxmEntityType(String entityType) {
+
+ String[] entityTypeArr = entityType.split("-");
+ String oxmEntityType = "";
+ for (String entityWord : entityTypeArr) {
+ oxmEntityType += entityWord.substring(0, 1).toUpperCase() + entityWord.substring(1);
+ }
+ return oxmEntityType;
+ }
+
+ protected List<String> getSearchableAttibutes(DynamicJAXBContext oxmJaxbContext, String oxmEntityType,
+ String entityType, String uebPayload,Exchange exchange) {
+ List<String> searchableAttr =
+ getOxmAttributes(oxmJaxbContext, oxmEntityType, entityType, "searchable");
+ if (searchableAttr == null) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_EVENT_NONVERBOSE,
+ "Searchable attribute not found for payload entity type '" + entityType + "'");
+ logger.debug(EntityEventPolicyMsgs.DISCARD_EVENT_VERBOSE,
+ "Searchable attribute not found for payload entity type '" + entityType + "'",
+ uebPayload);
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return null;
+ }
+ return searchableAttr;
+ }
+
+
+ private SpikeEventVertex initializeSpikeEventVertex(String payload) {
+
+ SpikeEventVertex eventVertex = null;
+ ObjectMapper mapper = new ObjectMapper();
+
+ // Make sure that were were actually passed in a valid string.
+ if (payload == null || payload.isEmpty()) {
+ logger.debug(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, EVENT_VERTEX);
+ logger.error(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, EVENT_VERTEX);
+
+ return eventVertex;
+ }
+
+ // Marshal the supplied string into a UebEventHeader object.
+ try {
+ eventVertex = mapper.readValue(payload, SpikeEventVertex.class);
+ } catch (JsonProcessingException e) {
+ logger.error(EntityEventPolicyMsgs.UEB_FAILED_UEBEVENTHEADER_CONVERSION, e.toString());
+ } catch (Exception e) {
+ logger.error(EntityEventPolicyMsgs.UEB_FAILED_UEBEVENTHEADER_CONVERSION, e.toString());
+ }
+
+ if (eventVertex != null) {
+ logger.debug(EntityEventPolicyMsgs.UEB_EVENT_HEADER_PARSED, eventVertex.toString());
+ }
+
+ return eventVertex;
+ }
+
+
+ private String getEntityPrimaryKeyFieldName(DynamicJAXBContext oxmJaxbContext, String payload,
+ String oxmEntityType, String entityType) {
+
+ DynamicType entity = oxmJaxbContext.getDynamicType(oxmEntityType);
+ if (entity == null) {
+ return null;
+ }
+
+ List<DatabaseField> list = entity.getDescriptor().getPrimaryKeyFields();
+ if (list != null && !list.isEmpty()) {
+ String keyName = list.get(0).getName();
+ return keyName.substring(0, keyName.indexOf('/'));
+ }
+
+ return "";
+ }
+
+ private String lookupValueUsingKey(String payload, String key) throws JSONException {
+ JsonNode jsonNode = convertToJsonNode(payload);
+ return RouterServiceUtil.recursivelyLookupJsonPayload(jsonNode, key);
+ }
+
+
+ private JsonNode convertToJsonNode(String payload) {
+
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode jsonNode = null;
+ try {
+ jsonNode = mapper.readTree(mapper.getJsonFactory().createJsonParser(payload));
+ } catch (IOException e) {
+ logger.debug(EntityEventPolicyMsgs.FAILED_TO_PARSE_UEB_PAYLOAD, EVENT_VERTEX + " missing",
+ payload);
+ logger.error(EntityEventPolicyMsgs.FAILED_TO_PARSE_UEB_PAYLOAD, EVENT_VERTEX + " missing",
+ "");
+ }
+
+ return jsonNode;
+ }
+
+
+ private boolean getSearchTags(SpikeEventEntity spikeEventEntity, List<String> searchableAttr,
+ String payload, String action) {
+
+ boolean hasSearchableAttr = false;
+ for (String searchTagField : searchableAttr) {
+ String searchTagValue;
+ if (searchTagField.equalsIgnoreCase(spikeEventEntity.getEntityPrimaryKeyName())) {
+ searchTagValue = spikeEventEntity.getEntityPrimaryKeyValue();
+ } else {
+ searchTagValue = this.lookupValueUsingKey(payload, searchTagField);
+ }
+
+ if (searchTagValue != null && !searchTagValue.isEmpty()) {
+ hasSearchableAttr = true;
+ spikeEventEntity.addSearchTagWithKey(searchTagValue, searchTagField);
+ }
+ }
+ return hasSearchableAttr;
+ }
+
+ /*
+ * Check if OXM version is available. If available, load it.
+ */
+ private DynamicJAXBContext loadOxmContext(String version) {
+ if (version == null) {
+ logger.error(EntityEventPolicyMsgs.FAILED_TO_FIND_OXM_VERSION, version);
+ return null;
+ }
+
+ return oxmVersionContextMap.get(version);
+ }
+
+ private List<String> getOxmAttributes(DynamicJAXBContext oxmJaxbContext, String oxmEntityType,
+ String entityType, String fieldName) {
+
+ DynamicType entity = (DynamicType) oxmJaxbContext.getDynamicType(oxmEntityType);
+ if (entity == null) {
+ return null;
+ }
+
+ /*
+ * Check for searchable XML tag
+ */
+ List<String> fieldValues = null;
+ Map<String, String> properties = entity.getDescriptor().getProperties();
+ for (Map.Entry<String, String> entry : properties.entrySet()) {
+ if (entry.getKey().equalsIgnoreCase(fieldName)) {
+ fieldValues = Arrays.asList(entry.getValue().split(","));
+ break;
+ }
+ }
+
+ return fieldValues;
+ }
+
+ protected SpikeEventEntity getPopulatedEntity(JsonNode entityNode,
+ OxmEntityDescriptor resultDescriptor) {
+ SpikeEventEntity d = new SpikeEventEntity();
+
+ d.setEntityType(resultDescriptor.getEntityName());
+
+ List<String> primaryKeyValues = new ArrayList<>();
+ List<String> primaryKeyNames = new ArrayList<>();
+ String pkeyValue;
+
+ for (String keyName : resultDescriptor.getPrimaryKeyAttributeName()) {
+ pkeyValue = RouterServiceUtil.getNodeFieldAsText(entityNode, keyName);
+ if (pkeyValue != null) {
+ primaryKeyValues.add(pkeyValue);
+ primaryKeyNames.add(keyName);
+ } else {
+ // logger.warn("getPopulatedDocument(), pKeyValue is null for entityType = " +
+ // resultDescriptor.getEntityName());
+ logger.error(EntityEventPolicyMsgs.PRIMARY_KEY_NULL_FOR_ENTITY_TYPE,
+ resultDescriptor.getEntityName());
+ }
+ }
+
+ final String primaryCompositeKeyValue = RouterServiceUtil.concatArray(primaryKeyValues, "/");
+ d.setEntityPrimaryKeyValue(primaryCompositeKeyValue);
+ final String primaryCompositeKeyName = RouterServiceUtil.concatArray(primaryKeyNames, "/");
+ d.setEntityPrimaryKeyName(primaryCompositeKeyName);
+
+ final List<String> searchTagFields = resultDescriptor.getSearchableAttributes();
+
+ /*
+ * Based on configuration, use the configured field names for this entity-Type to build a
+ * multi-value collection of search tags for elastic search entity search criteria.
+ */
+
+
+ for (String searchTagField : searchTagFields) {
+ String searchTagValue = RouterServiceUtil.getNodeFieldAsText(entityNode, searchTagField);
+ if (searchTagValue != null && !searchTagValue.isEmpty()) {
+ d.addSearchTagWithKey(searchTagValue, searchTagField);
+ }
+ }
+
+ return d;
+ }
+
+
+
+ // put this here until we find a better spot
+ /**
+ * Helper utility to concatenate substrings of a URI together to form a proper URI.
+ *
+ * @param suburis the list of substrings to concatenate together
+ * @return the concatenated list of substrings
+ */
+ private static String concatSubUri(String... suburis) {
+ String finalUri = "";
+
+ for (String suburi : suburis) {
+
+ if (suburi != null) {
+ // Remove any leading / since we only want to append /
+ suburi = suburi.replaceFirst("^/*", "");
+
+ // Add a trailing / if one isn't already there
+ finalUri += suburi.endsWith("/") ? suburi : suburi + "/";
+ }
+ }
+
+ return finalUri;
+ }
+
+
+
+ /**
+ * Perform create, read, update or delete (CRUD) operation on search engine's suggestive search
+ * index
+ *
+ * @param eventEntity Entity/data to use in operation
+ * @param action The operation to perform
+ */
+ protected void handleSearchServiceOperation(DocumentStoreDataEntity eventEntity, String action,
+ String index) {
+ try {
+
+ Map<String, List<String>> headers = new HashMap<>();
+ headers.put(Headers.FROM_APP_ID, Arrays.asList("DataLayer"));
+ headers.put(Headers.TRANSACTION_ID, Arrays.asList(MDC.get(MdcContext.MDC_REQUEST_ID)));
+
+ String entityId = eventEntity.getId();
+
+ if ((action.equalsIgnoreCase(ACTION_CREATE) && entityId != null)
+ || action.equalsIgnoreCase(ACTION_UPDATE)) {
+
+ // Run the GET to retrieve the ETAG from the search service
+ OperationResult storedEntity = searchAgent.getDocument(index, entityId);
+
+ if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) {
+ List<String> etag = storedEntity.getHeaders().get(Headers.ETAG);
+
+ if (etag != null && !etag.isEmpty()) {
+ headers.put(Headers.IF_MATCH, etag);
+ } else {
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, index, entityId);
+ }
+ }
+
+ // Write the entity to the search service.
+ // PUT
+ searchAgent.putDocument(index, entityId, eventEntity.getAsJson(), headers);
+ } else if (action.equalsIgnoreCase(ACTION_CREATE)) {
+ // Write the entry to the search service.
+ searchAgent.postDocument(index, eventEntity.getAsJson(), headers);
+
+ } else if (action.equalsIgnoreCase(ACTION_DELETE)) {
+ // Run the GET to retrieve the ETAG from the search service
+ OperationResult storedEntity = searchAgent.getDocument(index, entityId);
+
+ if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) {
+ List<String> etag = storedEntity.getHeaders().get(Headers.ETAG);
+
+ if (etag != null && !etag.isEmpty()) {
+ headers.put(Headers.IF_MATCH, etag);
+ } else {
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, index, entityId);
+ }
+
+ searchAgent.deleteDocument(index, eventEntity.getId(), headers);
+ } else {
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, index, entityId);
+ }
+ } else {
+ logger.error(EntityEventPolicyMsgs.ENTITY_OPERATION_NOT_SUPPORTED, action);
+ }
+ } catch (IOException e) {
+ logger.error(EntityEventPolicyMsgs.FAILED_TO_UPDATE_ENTITY_IN_DOCSTORE, eventEntity.getId(),
+ action);
+ }
+ }
+}
diff --git a/src/main/java/org/onap/aai/datarouter/policy/EntityEventPolicy.java b/src/main/java/org/onap/aai/datarouter/policy/EntityEventPolicy.java
index db68c21..1d447c9 100644
--- a/src/main/java/org/onap/aai/datarouter/policy/EntityEventPolicy.java
+++ b/src/main/java/org/onap/aai/datarouter/policy/EntityEventPolicy.java
@@ -901,7 +901,7 @@ public class EntityEventPolicy implements Processor {
headers.put(Headers.IF_MATCH, etag);
} else {
logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE,
- entitySearchIndex, entityId);
+ entitySearchIndex, entityId);
}
ArrayList<JsonNode> sourceObject = new ArrayList<>();
diff --git a/src/main/java/org/onap/aai/datarouter/policy/SpikeAggregateGenericVnfProcessor.java b/src/main/java/org/onap/aai/datarouter/policy/SpikeAggregateGenericVnfProcessor.java
new file mode 100644
index 0000000..76fce7b
--- /dev/null
+++ b/src/main/java/org/onap/aai/datarouter/policy/SpikeAggregateGenericVnfProcessor.java
@@ -0,0 +1,117 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * 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 is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.datarouter.policy;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.onap.aai.datarouter.entity.SpikeAggregationEntity;
+import org.onap.aai.datarouter.entity.SpikeEventVertex;
+import org.onap.aai.datarouter.logging.EntityEventPolicyMsgs;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+
+public class SpikeAggregateGenericVnfProcessor extends AbstractSpikeEntityEventProcessor {
+
+ public static final String additionalInfo = "Response of SpikeEntityEventPolicy";
+
+ /** Agent for communicating with the Search Service. */
+
+ public SpikeAggregateGenericVnfProcessor(SpikeEventPolicyConfig config)
+ throws FileNotFoundException {
+ super(config);
+ }
+
+ @Override
+ protected void startup() {
+ // Create the indexes in the search service if they do not already exist.
+ searchAgent.createSearchIndex(searchIndexName, searchIndexSchema, createIndexUrl);
+ logger.info(EntityEventPolicyMsgs.ENTITY_EVENT_POLICY_REGISTERED);
+ }
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+
+ long startTime = System.currentTimeMillis();
+ String uebPayload = getExchangeBody(exchange);
+ if (uebPayload == null) {
+ return;
+ }
+ JsonNode uebAsJson = null;
+ try {
+ uebAsJson = mapper.readTree(uebPayload);
+ } catch (IOException e) {
+ returnWithError(exchange, uebPayload, "Invalid Payload");
+ return;
+ }
+
+ String action = getSpikeEventAction(exchange, uebPayload);
+ if (action == null) {
+ return;
+ }
+ SpikeEventVertex eventVertex = populateEventVertex(exchange, uebPayload);
+ if (eventVertex == null) {
+ return;
+ }
+ String entityType = getEntityType(exchange, eventVertex, uebPayload);
+ if (entityType == null) {
+ return;
+ }
+ String entityLink = getEntityLink(exchange, eventVertex, uebPayload);
+ if (entityLink == null) {
+ return;
+ }
+ DynamicJAXBContext oxmJaxbContext = readOxm(exchange, uebPayload);
+ if (oxmJaxbContext == null) {
+ return;
+ }
+ String oxmEntityType = getOxmEntityType(entityType);
+ List<String> searchableAttr = getSearchableAttibutes(oxmJaxbContext, oxmEntityType, entityType, uebPayload,
+ exchange);
+ if (searchableAttr == null) {
+ return;
+ }
+
+
+ // log the fact that all data are in good shape
+ logger.info(EntityEventPolicyMsgs.PROCESS_ENTITY_EVENT_POLICY_NONVERBOSE, action, entityType);
+ logger.debug(EntityEventPolicyMsgs.PROCESS_ENTITY_EVENT_POLICY_VERBOSE, action, entityType,
+ uebPayload);
+
+ SpikeAggregationEntity spikeAgregationEntity = new SpikeAggregationEntity();
+ spikeAgregationEntity.setLink(entityLink);
+ spikeAgregationEntity.deriveFields(uebAsJson);
+ handleSearchServiceOperation(spikeAgregationEntity, action, searchIndexName);
+
+ long stopTime = System.currentTimeMillis();
+ metricsLogger.info(EntityEventPolicyMsgs.OPERATION_RESULT_NO_ERRORS, PROCESS_SPIKE_EVENT,
+ String.valueOf(stopTime - startTime));
+ setResponse(exchange, ResponseType.SUCCESS, additionalInfo);
+ return;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/datarouter/policy/SpikeAutosuggestIndexProcessor.java b/src/main/java/org/onap/aai/datarouter/policy/SpikeAutosuggestIndexProcessor.java
new file mode 100644
index 0000000..7c10fff
--- /dev/null
+++ b/src/main/java/org/onap/aai/datarouter/policy/SpikeAutosuggestIndexProcessor.java
@@ -0,0 +1,254 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * 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 is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.datarouter.policy;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.aai.datarouter.entity.OxmEntityDescriptor;
+import org.onap.aai.datarouter.entity.SpikeEventVertex;
+import org.onap.aai.datarouter.entity.SuggestionSearchEntity;
+import org.onap.aai.datarouter.logging.EntityEventPolicyMsgs;
+import org.onap.aai.datarouter.util.EntityOxmReferenceHelper;
+import org.onap.aai.datarouter.util.SearchSuggestionPermutation;
+import org.onap.aai.datarouter.util.Version;
+import org.onap.aai.datarouter.util.VersionedOxmEntities;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+
+public class SpikeAutosuggestIndexProcessor extends AbstractSpikeEntityEventProcessor {
+
+ public static final String additionalInfo = "Response of SpikeEntityEventPolicy";
+
+ private final String EVENT_VERTEX = "vertex";
+
+ private String oxmVersion = null;
+
+ /** Agent for communicating with the Search Service. */
+
+ public SpikeAutosuggestIndexProcessor(SpikeEventPolicyConfig config)
+ throws FileNotFoundException {
+ super(config);
+ parseLatestOxmVersion();
+ }
+
+ @Override
+ protected void startup() {
+ // Create the indexes in the search service if they do not already exist.
+ searchAgent.createSearchIndex(searchIndexName, searchIndexSchema, createIndexUrl);
+ logger.info(EntityEventPolicyMsgs.ENTITY_EVENT_POLICY_REGISTERED);
+ }
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+
+ long startTime = System.currentTimeMillis();
+ String uebPayload = getExchangeBody(exchange);
+ if (uebPayload == null) {
+ return;
+ }
+ JsonNode uebAsJson = null;
+ try {
+ uebAsJson = mapper.readTree(uebPayload);
+ } catch (IOException e) {
+ returnWithError(exchange, uebPayload, "Invalid Payload");
+ return;
+ }
+
+ String action = getSpikeEventAction(exchange, uebPayload);
+ if (action == null) {
+ return;
+ }
+ JSONObject uebObjEntity = getUebContentAsJson(uebPayload, EVENT_VERTEX);
+ if (uebObjEntity == null) {
+ returnWithError(exchange, uebPayload, "Payload is missing " + EVENT_VERTEX);
+ return;
+ }
+
+ SpikeEventVertex eventVertex = populateEventVertex(exchange, uebPayload);
+ if (eventVertex == null) {
+ return;
+ }
+ String entityType = getEntityType(exchange, eventVertex, uebPayload);
+ if (entityType == null) {
+ return;
+ }
+ String entityLink = getEntityLink(exchange, eventVertex, uebPayload);
+ if (entityLink == null) {
+ return;
+ }
+ DynamicJAXBContext oxmJaxbContext = readOxm(exchange, uebPayload);
+ if (oxmJaxbContext == null) {
+ return;
+ }
+ String oxmEntityType = getOxmEntityType(entityType);
+ List<String> searchableAttr = getSearchableAttibutes(oxmJaxbContext, oxmEntityType, entityType, uebPayload,
+ exchange);
+ if (searchableAttr == null) {
+ return;
+ }
+
+ // log the fact that all data are in good shape
+ logger.info(EntityEventPolicyMsgs.PROCESS_ENTITY_EVENT_POLICY_NONVERBOSE, action, entityType);
+ logger.debug(EntityEventPolicyMsgs.PROCESS_ENTITY_EVENT_POLICY_VERBOSE, action, entityType,
+ uebPayload);
+
+
+ /*
+ * Use the versioned OXM Entity class to get access to cross-entity reference helper collections
+ */
+ VersionedOxmEntities oxmEntities =
+ EntityOxmReferenceHelper.getInstance().getVersionedOxmEntities(Version.valueOf(oxmVersion));
+
+ /*
+ * Process for autosuggestable entities
+ */
+ if (oxmEntities != null) {
+ Map<String, OxmEntityDescriptor> rootDescriptor =
+ oxmEntities.getSuggestableEntityDescriptors();
+ if (!rootDescriptor.isEmpty()) {
+ List<String> suggestibleAttrInPayload = new ArrayList<>();
+ List<String> suggestibleAttrInOxm = extractSuggestableAttr(oxmEntities, entityType);
+ if (suggestibleAttrInOxm != null) {
+ for (String attr: suggestibleAttrInOxm){
+ if ( uebAsJson.get("vertex").get("properties").has(attr) ){
+ suggestibleAttrInPayload.add(attr);
+ }
+ }
+ }
+
+ if (suggestibleAttrInPayload.isEmpty()) {
+ return;
+ }
+ List<String> suggestionAliases = extractAliasForSuggestableEntity(oxmEntities, entityType);
+
+ /*
+ * It was decided to silently ignore DELETE requests for resources we don't allow to be
+ * deleted. e.g. auto-suggestion deletion is not allowed while aggregation deletion is.
+ */
+ if (!ACTION_DELETE.equalsIgnoreCase(action)) {
+ List<ArrayList<String>> listOfValidPowerSetElements =
+ SearchSuggestionPermutation.getNonEmptyUniqueLists(suggestibleAttrInPayload);
+
+ // Now we have a list containing the power-set (minus empty element) for the status that are
+ // available in the payload. Try inserting a document for every combination.
+ for (ArrayList<String> list : listOfValidPowerSetElements) {
+ SuggestionSearchEntity suggestionSearchEntity = new SuggestionSearchEntity();
+ suggestionSearchEntity.setEntityType(entityType);
+ suggestionSearchEntity.setSuggestableAttr(list);
+ suggestionSearchEntity.setEntityTypeAliases(suggestionAliases);
+ suggestionSearchEntity.setFilterBasedPayloadFromResponse(uebAsJson.get("vertex").get("properties"),
+ suggestibleAttrInOxm, list);
+ suggestionSearchEntity.setSuggestionInputPermutations(
+ suggestionSearchEntity.generateSuggestionInputPermutations());
+
+ if (suggestionSearchEntity.isSuggestableDoc()) {
+ try {
+ suggestionSearchEntity.generateSearchSuggestionDisplayStringAndId();
+ } catch (NoSuchAlgorithmException e) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_UPDATING_SEARCH_SUGGESTION_DATA,
+ "Cannot create unique SHA digest for search suggestion data. Exception: "
+ + e.getLocalizedMessage());
+ }
+
+ handleSearchServiceOperation(suggestionSearchEntity, action, searchIndexName);
+ }
+ }
+ }
+ }
+ }
+ long stopTime = System.currentTimeMillis();
+ metricsLogger.info(EntityEventPolicyMsgs.OPERATION_RESULT_NO_ERRORS, PROCESS_SPIKE_EVENT,
+ String.valueOf(stopTime - startTime));
+ setResponse(exchange, ResponseType.SUCCESS, additionalInfo);
+ return;
+ }
+
+ public List<String> extractSuggestableAttr(VersionedOxmEntities oxmEntities, String entityType) {
+ // Extract suggestable attributeshandleTopographicalData
+ Map<String, OxmEntityDescriptor> rootDescriptor = oxmEntities.getSuggestableEntityDescriptors();
+
+ if (rootDescriptor == null) {
+ return Collections.emptyList();
+ }
+
+ OxmEntityDescriptor desc = rootDescriptor.get(entityType);
+
+ if (desc == null) {
+ return Collections.emptyList();
+ }
+
+ return desc.getSuggestableAttributes();
+ }
+
+
+ public List<String> extractAliasForSuggestableEntity(VersionedOxmEntities oxmEntities,
+ String entityType) {
+
+ // Extract alias
+ Map<String, OxmEntityDescriptor> rootDescriptor = oxmEntities.getEntityAliasDescriptors();
+
+ if (rootDescriptor == null) {
+ return Collections.emptyList();
+ }
+
+ OxmEntityDescriptor desc = rootDescriptor.get(entityType);
+ return desc.getAlias();
+ }
+
+ private void parseLatestOxmVersion() {
+ int latestVersion = -1;
+ if (oxmVersionContextMap != null) {
+ Iterator it = oxmVersionContextMap.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry pair = (Map.Entry) it.next();
+
+ String version = pair.getKey().toString();
+ int versionNum = Integer.parseInt(version.substring(1, version.length()));
+
+ if (versionNum > latestVersion) {
+ latestVersion = versionNum;
+ oxmVersion = pair.getKey().toString();
+ }
+
+ logger.info(EntityEventPolicyMsgs.PROCESS_OXM_MODEL_FOUND, pair.getKey().toString());
+ }
+ } else {
+ logger.error(EntityEventPolicyMsgs.PROCESS_OXM_MODEL_MISSING, "");
+ }
+ }
+
+
+
+}
diff --git a/src/main/java/org/onap/aai/datarouter/policy/SpikeEntitySearchProcessor.java b/src/main/java/org/onap/aai/datarouter/policy/SpikeEntitySearchProcessor.java
new file mode 100644
index 0000000..7f7bdd9
--- /dev/null
+++ b/src/main/java/org/onap/aai/datarouter/policy/SpikeEntitySearchProcessor.java
@@ -0,0 +1,160 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ================================================================================
+ * 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 is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.aai.datarouter.policy;
+
+import java.io.FileNotFoundException;
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.onap.aai.datarouter.entity.SpikeEventEntity;
+import org.onap.aai.datarouter.entity.SpikeEventVertex;
+import org.onap.aai.datarouter.logging.EntityEventPolicyMsgs;
+
+
+public class SpikeEntitySearchProcessor extends AbstractSpikeEntityEventProcessor {
+
+ public static final String additionalInfo = "Response of SpikeEntityEventPolicy";
+ private static final String searchIndexSchema = "";
+
+
+
+ /** Agent for communicating with the Search Service. */
+
+ public SpikeEntitySearchProcessor(SpikeEventPolicyConfig config)
+ throws FileNotFoundException {
+ super(config);
+
+ }
+
+ @Override
+ protected void startup() {
+ // Create the indexes in the search service if they do not already exist.
+ searchAgent.createSearchIndex(searchIndexName, searchIndexSchema);
+ logger.info(EntityEventPolicyMsgs.ENTITY_EVENT_POLICY_REGISTERED);
+ }
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+
+ long startTime = System.currentTimeMillis();
+ String uebPayload = getExchangeBody(exchange);
+ if (uebPayload == null) {
+ return;
+ }
+
+ String action = getSpikeEventAction(exchange, uebPayload);
+ if (action == null) {
+ return;
+ }
+ SpikeEventVertex eventVertex = populateEventVertex(exchange, uebPayload);
+ if (eventVertex == null) {
+ return;
+ }
+ String entityType = getEntityType(exchange, eventVertex, uebPayload);
+ if (entityType == null) {
+ return;
+ }
+ String entityLink = getEntityLink(exchange, eventVertex, uebPayload);
+ if (entityLink == null) {
+ return;
+ }
+ DynamicJAXBContext oxmJaxbContext = readOxm(exchange, uebPayload);
+ if (oxmJaxbContext == null) {
+ return;
+ }
+ String oxmEntityType = getOxmEntityType(entityType);
+ List<String> searchableAttr = getSearchableAttibutes(oxmJaxbContext, oxmEntityType, entityType, uebPayload,
+ exchange);
+ if (searchableAttr == null) {
+ return;
+ }
+
+ // log the fact that all data are in good shape
+ logger.info(EntityEventPolicyMsgs.PROCESS_ENTITY_EVENT_POLICY_NONVERBOSE, action, entityType);
+ logger.debug(EntityEventPolicyMsgs.PROCESS_ENTITY_EVENT_POLICY_VERBOSE, action, entityType,
+ uebPayload);
+
+ SpikeEventEntity spikeEventEntity = new SpikeEventEntity();
+ spikeEventEntity.setEntityType(entityType);
+ spikeEventEntity.setLink(entityLink);
+ spikeEventEntity = populateSpikeEventEntity(exchange, spikeEventEntity, oxmJaxbContext,
+ entityType, action, uebPayload, oxmEntityType,searchableAttr);
+ if (spikeEventEntity == null) {
+ return;
+ }
+
+ handleSearchServiceOperation(spikeEventEntity, action, searchIndexName);
+ long stopTime = System.currentTimeMillis();
+ metricsLogger.info(EntityEventPolicyMsgs.OPERATION_RESULT_NO_ERRORS, PROCESS_SPIKE_EVENT,
+ String.valueOf(stopTime - startTime));
+ setResponse(exchange, ResponseType.SUCCESS, additionalInfo);
+ return;
+ }
+
+ /*
+ * This is not for this Scope. We get back to it later. (updateCerInEntity) private void
+ * updateSearchEntityWithCrossEntityReference(SpikeEventEntity spikeEventEntity) { try {
+ * Map<String, List<String>> headers = new HashMap<>(); headers.put(Headers.FROM_APP_ID,
+ * Arrays.asList("Data Router")); headers.put(Headers.TRANSACTION_ID,
+ * Arrays.asList(MDC.get(MdcContext.MDC_REQUEST_ID)));
+ *
+ * String entityId = spikeEventEntity.getId(); String jsonPayload;
+ *
+ * // Run the GET to retrieve the ETAG from the search service OperationResult storedEntity =
+ * searchAgent.getDocument(entitySearchIndex, entityId);
+ *
+ * if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) { /* NOTES:
+ * aaiEventEntity (ie the nested entity) may contain a subset of properties of the pre-existing
+ * object, so all we want to do is update the CER on the pre-existing object (if needed).
+ *
+ *
+ * List<String> etag = storedEntity.getHeaders().get(Headers.ETAG);
+ *
+ * if (etag != null && !etag.isEmpty()) { headers.put(Headers.IF_MATCH, etag); } else {
+ * logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, entitySearchIndex, entityId); }
+ *
+ * ArrayList<JsonNode> sourceObject = new ArrayList<>();
+ * NodeUtils.extractObjectsByKey(NodeUtils.convertJsonStrToJsonNode(storedEntity.getResult()),
+ * "content", sourceObject);
+ *
+ * if (!sourceObject.isEmpty()) { JsonNode node = sourceObject.get(0); final String sourceCer =
+ * NodeUtils.extractFieldValueFromObject(node, "crossEntityReferenceValues"); String newCer =
+ * spikeEventEntity.getCrossReferenceEntityValues(); boolean hasNewCer = true; if (sourceCer !=
+ * null && sourceCer.length() > 0) { // already has CER if (!sourceCer.contains(newCer)) {// don't
+ * re-add newCer = sourceCer + ";" + newCer; } else { hasNewCer = false; } }
+ *
+ * if (hasNewCer) { // Do the PUT with new CER ((ObjectNode)
+ * node).put("crossEntityReferenceValues", newCer); jsonPayload =
+ * NodeUtils.convertObjectToJson(node, false); searchAgent.putDocument(entitySearchIndex,
+ * entityId, jsonPayload, headers); } } } else {
+ *
+ * if (storedEntity.getResultCode() == 404) { // entity not found, so attempt to do a PUT
+ * searchAgent.putDocument(entitySearchIndex, entityId, spikeEventEntity.getAsJson(), headers); }
+ * else { logger.error(EntityEventPolicyMsgs.FAILED_TO_UPDATE_ENTITY_IN_DOCSTORE,
+ * spikeEventEntity.getId(), "SYNC_ENTITY"); } } } catch (IOException e) {
+ * logger.error(EntityEventPolicyMsgs.FAILED_TO_UPDATE_ENTITY_IN_DOCSTORE,
+ * spikeEventEntity.getId(), "SYNC_ENTITY"); } }
+ */
+
+}
diff --git a/src/main/java/org/onap/aai/datarouter/policy/SpikeEventPolicyConfig.java b/src/main/java/org/onap/aai/datarouter/policy/SpikeEventPolicyConfig.java
new file mode 100644
index 0000000..55db200
--- /dev/null
+++ b/src/main/java/org/onap/aai/datarouter/policy/SpikeEventPolicyConfig.java
@@ -0,0 +1,90 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017-2018 Amdocs
+ * ================================================================================
+ * 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=========================================================
+ */
+package org.onap.aai.datarouter.policy;
+
+public class SpikeEventPolicyConfig {
+
+ private String sourceDomain;
+ private String searchBaseUrl;
+ private String searchEndpoint;
+ private String searchEndpointDocuments;
+ private String searchCertName;
+ private String searchKeystorePwd;
+ private String searchKeystore;
+
+
+ public String getSourceDomain() {
+ return sourceDomain;
+ }
+
+ public void setSourceDomain(String sourceDomain) {
+ this.sourceDomain = sourceDomain;
+ }
+
+ public String getSearchBaseUrl() {
+ return searchBaseUrl;
+ }
+
+ public void setSearchBaseUrl(String searchBaseUrl) {
+ this.searchBaseUrl = searchBaseUrl;
+ }
+
+ public String getSearchEndpoint() {
+ return searchEndpoint;
+ }
+
+ public void setSearchEndpoint(String searchEndpoint) {
+ this.searchEndpoint = searchEndpoint;
+ }
+
+ public String getSearchEndpointDocuments() {
+ return searchEndpointDocuments;
+ }
+
+ public void setSearchEndpointDocuments(String searchEndpointDocuments) {
+ this.searchEndpointDocuments = searchEndpointDocuments;
+ }
+
+
+ public String getSearchCertName() {
+ return searchCertName;
+ }
+
+ public void setSearchCertName(String searchCertName) {
+ this.searchCertName = searchCertName;
+ }
+
+ public String getSearchKeystore() {
+ return searchKeystore;
+ }
+
+ public void setSearchKeystore(String searchKeystore) {
+ this.searchKeystore = searchKeystore;
+ }
+
+ public String getSearchKeystorePwd() {
+ return searchKeystorePwd;
+ }
+
+ public void setSearchKeystorePwd(String searchKeystorePwd) {
+ this.searchKeystorePwd = searchKeystorePwd;
+ }
+}
diff --git a/src/main/java/org/onap/aai/datarouter/util/SearchServiceAgent.java b/src/main/java/org/onap/aai/datarouter/util/SearchServiceAgent.java
index fe1df3b..42861b4 100644
--- a/src/main/java/org/onap/aai/datarouter/util/SearchServiceAgent.java
+++ b/src/main/java/org/onap/aai/datarouter/util/SearchServiceAgent.java
@@ -127,6 +127,14 @@ public class SearchServiceAgent {
createIndex(index, schemaLocation);
}
+ public void createSearchIndex(String index, String schemaLocation, String endUrl) {
+
+ // Create a mapping of the index name to schema location
+ indexSchemaMapping.put(index, schemaLocation);
+
+ // Now, create the index.
+ createIndex(index, schemaLocation, endUrl);
+ }
/**
* This method performs the actual work of creating a search index.
@@ -160,6 +168,30 @@ public class SearchServiceAgent {
}
}
+ private void createIndex(String index, String schemaLocation, String endUrl) {
+
+ logger.debug("Creating search index, index name: = " + index + ", schemaLocation = " + schemaLocation);
+
+ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+ headers.put("Accept", Arrays.asList("application/json"));
+ headers.put(Headers.FROM_APP_ID, Arrays.asList("DL"));
+ headers.put(Headers.TRANSACTION_ID, Arrays.asList(UUID.randomUUID().toString()));
+
+ String url = concatSubUri(searchUrl, endUrl, index);
+ try {
+
+ OperationResult result = searchClient.put(url, loadFileData(schemaLocation), headers,
+ MediaType.APPLICATION_JSON_TYPE, null);
+ if (!HttpUtil.isHttpResponseClassSuccess(result.getResultCode())) {
+ logger.error(DataRouterMsgs.FAIL_TO_CREATE_SEARCH_INDEX, index, result.getFailureCause());
+ } else {
+ logger.info(DataRouterMsgs.SEARCH_INDEX_CREATE_SUCCESS, index);
+ }
+
+ } catch (Exception e) {
+ logger.error(DataRouterMsgs.FAIL_TO_CREATE_SEARCH_INDEX, index, e.getLocalizedMessage());
+ }
+ }
/**
* Retrieves a document from the search service.
diff --git a/src/main/resources/aggregatevnf_schema.json b/src/main/resources/aggregatevnf_schema.json
new file mode 100644
index 0000000..03d5627
--- /dev/null
+++ b/src/main/resources/aggregatevnf_schema.json
@@ -0,0 +1,17 @@
+{
+ "mappings": {
+ "default": {
+ "dynamic_templates": [{
+ "strings": {
+ "match_mapping_type": "string",
+ "match": "*",
+ "mapping": {
+ "type": "string",
+ "index": "not_analyzed"
+ }
+ }
+ }
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/resources/autosuggest_schema.json b/src/main/resources/autosuggest_schema.json
new file mode 100644
index 0000000..99ac031
--- /dev/null
+++ b/src/main/resources/autosuggest_schema.json
@@ -0,0 +1,31 @@
+{
+ "settings": {
+ "analysis": {
+ "filter": {
+ "eng_stop": {
+ "type": "stop",
+ "stopwords": "_english_"
+ }
+ },
+ "analyzer": {
+ "custom_analyzer": {
+ "type": "custom",
+ "tokenizer": "standard",
+ "filter": ["lowercase", "asciifolding", "eng_stop"]
+ }
+ }
+ }
+ },
+ "mappings": {
+ "default": {
+ "properties": {
+ "entity_suggest": {
+ "type": "completion",
+ "payloads": true,
+ "analyzer": "custom_analyzer",
+ "preserve_position_increments": false
+ }
+ }
+ }
+ }
+} \ No newline at end of file