aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openecomp/datarouter/policy/EntityEventPolicy.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/openecomp/datarouter/policy/EntityEventPolicy.java')
-rw-r--r--src/main/java/org/openecomp/datarouter/policy/EntityEventPolicy.java1162
1 files changed, 1162 insertions, 0 deletions
diff --git a/src/main/java/org/openecomp/datarouter/policy/EntityEventPolicy.java b/src/main/java/org/openecomp/datarouter/policy/EntityEventPolicy.java
new file mode 100644
index 0000000..170c646
--- /dev/null
+++ b/src/main/java/org/openecomp/datarouter/policy/EntityEventPolicy.java
@@ -0,0 +1,1162 @@
+/**
+ * ============LICENSE_START=======================================================
+ * DataRouter
+ * ================================================================================
+ * 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.openecomp.datarouter.policy;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+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 java.util.UUID;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.eclipse.jetty.util.security.Password;
+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.openecomp.cl.api.Logger;
+import org.openecomp.cl.eelf.LoggerFactory;
+import org.openecomp.cl.mdc.MdcContext;
+import org.openecomp.datarouter.entity.AaiEventEntity;
+import org.openecomp.datarouter.entity.AggregationEntity;
+import org.openecomp.datarouter.entity.DocumentStoreDataEntity;
+import org.openecomp.datarouter.entity.OxmEntityDescriptor;
+import org.openecomp.datarouter.entity.SuggestionSearchEntity;
+import org.openecomp.datarouter.entity.TopographicalEntity;
+import org.openecomp.datarouter.entity.UebEventHeader;
+import org.openecomp.datarouter.logging.DataRouterMsgs;
+import org.openecomp.datarouter.logging.EntityEventPolicyMsgs;
+import org.openecomp.datarouter.util.CrossEntityReference;
+import org.openecomp.datarouter.util.DataRouterConstants;
+import org.openecomp.datarouter.util.EntityOxmReferenceHelper;
+import org.openecomp.datarouter.util.ExternalOxmModelProcessor;
+import org.openecomp.datarouter.util.OxmModelLoader;
+import org.openecomp.datarouter.util.RouterServiceUtil;
+import org.openecomp.datarouter.util.SearchSuggestionPermutation;
+import org.openecomp.datarouter.util.Version;
+import org.openecomp.datarouter.util.VersionedOxmEntities;
+import org.openecomp.restclient.client.Headers;
+import org.openecomp.restclient.client.OperationResult;
+import org.openecomp.restclient.client.RestClient;
+import org.openecomp.restclient.rest.HttpUtil;
+import org.slf4j.MDC;
+
+public class EntityEventPolicy implements Processor {
+
+ public static final String additionalInfo = "Response of AAIEntityEventPolicy";
+ private static final String entitySearchSchema = "entitysearch_schema.json";
+ private static final String topographicalSearchSchema = "topographysearch_schema.json";
+ private Collection<ExternalOxmModelProcessor> externalOxmModelProcessors;
+ RestClient searchClient = null;
+
+ private final String EVENT_HEADER = "event-header";
+ private final String ENTITY_HEADER = "entity";
+ private final String ACTION_CREATE = "create";
+ private final String ACTION_DELETE = "delete";
+ private final String ACTION_UPDATE = "update";
+ private final String PROCESS_AAI_EVENT = "Process AAI Event";
+ private final String TOPO_LAT = "latitude";
+ private final String TOPO_LONG = "longitude";
+
+ private final List<String> SUPPORTED_ACTIONS =
+ Arrays.asList(ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE);
+
+ Map<String, DynamicJAXBContext> oxmVersionContextMap = new HashMap<>();
+ private String oxmVersion = null;
+
+ private String entityIndexTarget = null;
+ private String entitySearchTarget = null;
+ private String topographicalIndexTarget = null;
+ private String topographicalSearchTarget = null;
+ private String autoSuggestSearchTarget = null;
+ private String aggregationSearchVnfTarget = null;
+
+ private String srcDomain;
+
+ private Logger logger;
+ private Logger metricsLogger;
+ private Logger auditLogger;
+
+ public enum ResponseType {
+ SUCCESS, PARTIAL_SUCCESS, FAILURE;
+ };
+
+ public EntityEventPolicy(EntityEventPolicyConfig config) {
+ LoggerFactory loggerFactoryInstance = LoggerFactory.getInstance();
+ logger = loggerFactoryInstance.getLogger(EntityEventPolicy.class.getName());
+ metricsLogger = loggerFactoryInstance.getMetricsLogger(EntityEventPolicy.class.getName());
+ auditLogger = loggerFactoryInstance.getAuditLogger(EntityEventPolicy.class.getName());
+
+ srcDomain = config.getSourceDomain();
+
+ entityIndexTarget =
+ EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(), config.getSearchEndpoint(),
+ config.getSearchEntitySearchIndex());
+
+ entitySearchTarget =
+ EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(), config.getSearchEndpoint(),
+ config.getSearchEntitySearchIndex(), config.getSearchEndpointDocuments());
+
+ topographicalIndexTarget =
+ EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(), config.getSearchEndpoint(),
+ config.getSearchTopographySearchIndex());
+
+ topographicalSearchTarget = EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(),
+ config.getSearchEndpoint(), config.getSearchTopographySearchIndex());
+
+ // Create REST client for search service
+ searchClient = new RestClient().validateServerHostname(false).validateServerCertChain(true)
+ .clientCertFile(DataRouterConstants.DR_HOME_AUTH + config.getSearchCertName())
+ .clientCertPassword(Password.deobfuscate(config.getSearchKeystorePwd()))
+ .trustStore(DataRouterConstants.DR_HOME_AUTH + config.getSearchKeystore());
+
+ autoSuggestSearchTarget =
+ EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(), config.getSearchEndpoint(),
+ config.getSearchEntityAutoSuggestIndex(), config.getSearchEndpointDocuments());
+
+ aggregationSearchVnfTarget =
+ EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(), config.getSearchEndpoint(),
+ config.getSearchAggregationVnfIndex(), config.getSearchEndpointDocuments());
+
+ this.externalOxmModelProcessors = new ArrayList<ExternalOxmModelProcessor>();
+ this.externalOxmModelProcessors.add(EntityOxmReferenceHelper.getInstance());
+ OxmModelLoader.registerExternalOxmModelProcessors(externalOxmModelProcessors);
+ OxmModelLoader.loadModels();
+ oxmVersionContextMap = OxmModelLoader.getVersionContextMap();
+ parseLatestOxmVersion();
+ }
+
+ 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, 2));
+
+ 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, "");
+ }
+ }
+
+ public void startup() {
+
+ // Create the indexes in the search service if they do not already exist.
+ createSearchIndex(entityIndexTarget, entitySearchSchema);
+ createSearchIndex(topographicalIndexTarget, topographicalSearchSchema);
+
+ logger.info(EntityEventPolicyMsgs.ENTITY_EVENT_POLICY_REGISTERED);
+ }
+
+ /**
+ * Creates an index through the search db abstraction
+ *
+ * @param searchRESTClient
+ * the REST client configured to contact the search db
+ * abstraction
+ * @param searchTarget
+ * the URL to attempt to create the search index
+ * @param schemaLocation
+ * the location of the mappings file for the index
+ */
+ private void createSearchIndex(String searchTarget, String schemaLocation) {
+
+ logger.debug("Creating search index, searchTarget = " + searchTarget + ", 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()));
+
+ try {
+
+ OperationResult result = searchClient.put(searchTarget, loadFileData(schemaLocation), headers,
+ MediaType.APPLICATION_JSON_TYPE, null);
+
+ if (!HttpUtil.isHttpResponseClassSuccess(result.getResultCode())) {
+ logger.error(EntityEventPolicyMsgs.FAIL_TO_CREATE_SEARCH_INDEX, searchTarget, result.getFailureCause());
+ } else {
+ logger.info(EntityEventPolicyMsgs.SEARCH_INDEX_CREATE_SUCCESS, searchTarget);
+ }
+
+ } catch (Exception e) {
+ logger.error(EntityEventPolicyMsgs.FAIL_TO_CREATE_SEARCH_INDEX, searchTarget, e.getLocalizedMessage());
+ }
+ }
+
+ /**
+ * Convenience method to load up all the data from a file into a string
+ *
+ * @param filename the filename to read from disk
+ * @return the data contained within the file
+ * @throws Exception
+ */
+ protected String loadFileData(String filename) throws Exception {
+ StringBuilder data = new StringBuilder();
+ try {
+ BufferedReader in = new BufferedReader(new InputStreamReader(
+ EntityEventPolicy.class.getClassLoader().getResourceAsStream("/" + filename),
+ StandardCharsets.UTF_8));
+ String line;
+
+ while ((line = in.readLine()) != null) {
+ data.append(line);
+ }
+ } catch (Exception e) {
+ throw new Exception("Failed to read from file = " + filename + ".", e);
+ }
+
+ return data.toString();
+ }
+
+
+ /**
+ * Convert object to json.
+ *
+ * @param object the object
+ * @param pretty the pretty
+ * @return the string
+ * @throws JsonProcessingException the json processing exception
+ */
+ public static String convertObjectToJson(Object object, boolean pretty)
+ throws JsonProcessingException {
+ ObjectWriter ow = null;
+
+ if (pretty) {
+ ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
+
+ } else {
+ ow = new ObjectMapper().writer();
+ }
+
+ return ow.writeValueAsString(object);
+ }
+
+ public void returnWithError(Exchange exchange, String payload, String errorMsg){
+ logger.error(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_NONVERBOSE, errorMsg);
+ logger.debug(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE, errorMsg, payload);
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ }
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+
+ long startTime = System.currentTimeMillis();
+
+ String uebPayload = exchange.getIn().getBody().toString();
+
+ JsonNode uebAsJson =null;
+ ObjectMapper mapper = new ObjectMapper();
+ try{
+ uebAsJson = mapper.readTree(uebPayload);
+ } catch (IOException e){
+ returnWithError(exchange, uebPayload, "Invalid Payload");
+ return;
+ }
+
+ // Load the UEB payload data, any errors will result in a failure and discard
+ JSONObject uebObjHeader = getUebHeaderAsJson(uebPayload);
+ if (uebObjHeader == null) {
+ returnWithError(exchange, uebPayload, "Payload is missing event-header");
+ return;
+ }
+
+ UebEventHeader eventHeader = null;
+ eventHeader = initializeUebEventHeader(uebObjHeader.toString());
+
+ // Get src domain from header; discard event if not originated from same domain
+ String payloadSrcDomain = eventHeader.getDomain();
+ if (payloadSrcDomain == null || !payloadSrcDomain.equalsIgnoreCase(this.srcDomain)) {
+ logger.debug(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE,
+ "Unrecognized source domain '" + payloadSrcDomain + "'", uebPayload);
+ logger.error(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_NONVERBOSE,
+ "Unrecognized source domain '" + payloadSrcDomain + "'");
+
+ setResponse(exchange, ResponseType.SUCCESS, additionalInfo);
+ return;
+ }
+
+ DynamicJAXBContext oxmJaxbContext = loadOxmContext(oxmVersion.toLowerCase());
+ if (oxmJaxbContext == null) {
+ logger.error(EntityEventPolicyMsgs.OXM_VERSION_NOT_SUPPORTED, oxmVersion);
+ logger.debug(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE, "OXM version mismatch",
+ uebPayload);
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return;
+ }
+
+ String action = eventHeader.getAction();
+ if (action == null || !SUPPORTED_ACTIONS.contains(action.toLowerCase())) {
+ logger.debug(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE,
+ "Unrecognized action '" + action + "'", uebPayload);
+ logger.error(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_NONVERBOSE,
+ "Unrecognized action '" + action + "'");
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return;
+ }
+
+ String entityType = eventHeader.getEntityType();
+ if (entityType == null) {
+ logger.debug(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE,
+ "Payload header missing entity type", uebPayload);
+ logger.error(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_NONVERBOSE,
+ "Payload header missing entity type");
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return;
+ }
+
+ String topEntityType = eventHeader.getTopEntityType();
+ if (topEntityType == null) {
+ logger.debug(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE,
+ "Payload header missing top entity type", uebPayload);
+ logger.error(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_NONVERBOSE,
+ "Payload header top missing entity type");
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return;
+ }
+
+ String entityLink = eventHeader.getEntityLink();
+ if (entityLink == null) {
+ logger.debug(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE,
+ "Payload header missing entity link", uebPayload);
+ logger.error(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_NONVERBOSE,
+ "Payload header missing entity link");
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return;
+ }
+
+ // log the fact that all data are in good shape
+ logger.info(EntityEventPolicyMsgs.PROCESS_AAI_ENTITY_EVENT_POLICY_NONVERBOSE, action,
+ entityType);
+ logger.debug(EntityEventPolicyMsgs.PROCESS_AAI_ENTITY_EVENT_POLICY_VERBOSE, action, entityType,
+ uebPayload);
+
+
+ // Process for building AaiEventEntity object
+ String[] entityTypeArr = entityType.split("-");
+ String oxmEntityType = "";
+ for (String entityWord : entityTypeArr) {
+ oxmEntityType += entityWord.substring(0, 1).toUpperCase() + entityWord.substring(1);
+ }
+
+ List<String> searchableAttr =
+ getOxmAttributes(uebPayload, oxmJaxbContext, oxmEntityType, entityType, "searchable");
+ if (searchableAttr == null) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_NONVERBOSE,
+ "Searchable attribute not found for payload entity type '" + entityType + "'");
+ logger.debug(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE,
+ "Searchable attribute not found for payload entity type '" + entityType + "'",
+ uebPayload);
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return;
+ }
+
+ String entityPrimaryKeyFieldName =
+ getEntityPrimaryKeyFieldName(oxmJaxbContext, uebPayload, oxmEntityType, entityType);
+ String entityPrimaryKeyFieldValue = lookupValueUsingKey(uebPayload, entityPrimaryKeyFieldName);
+ if (entityPrimaryKeyFieldValue == null || entityPrimaryKeyFieldValue.isEmpty()) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_NONVERBOSE,
+ "Payload missing primary key attribute");
+ logger.debug(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE,
+ "Payload missing primary key attribute", uebPayload);
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return;
+ }
+
+ AaiEventEntity aaiEventEntity = new AaiEventEntity();
+
+ /*
+ * Use the OXM Model to determine the primary key field name based on the entity-type
+ */
+
+ aaiEventEntity.setEntityPrimaryKeyName(entityPrimaryKeyFieldName);
+ aaiEventEntity.setEntityPrimaryKeyValue(entityPrimaryKeyFieldValue);
+ aaiEventEntity.setEntityType(entityType);
+ aaiEventEntity.setLink(entityLink);
+
+ if (!getSearchTags(aaiEventEntity, searchableAttr, uebPayload, action)) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_NONVERBOSE,
+ "Payload missing searchable attribute for entity type '" + entityType + "'");
+ logger.debug(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE,
+ "Payload missing searchable attribute for entity type '" + entityType + "'", uebPayload);
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return;
+
+ }
+
+ try {
+ aaiEventEntity.deriveFields();
+
+ } catch (NoSuchAlgorithmException e) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE,
+ "Cannot create unique SHA digest");
+ logger.debug(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE,
+ "Cannot create unique SHA digest", uebPayload);
+
+ setResponse(exchange, ResponseType.FAILURE, additionalInfo);
+ return;
+ }
+
+ handleSearchServiceOperation(aaiEventEntity, action, this.entitySearchTarget);
+
+ handleTopographicalData(uebPayload, action, entityType, oxmEntityType, oxmJaxbContext,
+ entityPrimaryKeyFieldName, entityPrimaryKeyFieldValue);
+
+ /*
+ * Use the versioned OXM Entity class to get access to cross-entity reference helper collections
+ */
+ VersionedOxmEntities oxmEntities =
+ EntityOxmReferenceHelper.getInstance().getVersionedOxmEntities(Version.valueOf(oxmVersion));
+
+ /**
+ * If the entity type is "customer", the below check will return true if any nested entityType
+ * in that model could contain a CER based on the OXM model version that has been loaded.
+ */
+
+ if (oxmEntities != null && oxmEntities.entityModelContainsCrossEntityReference(topEntityType)) {
+
+ // We know the model "can" contain a CER reference definition, let's process a bit more
+
+ HashMap<String, CrossEntityReference> crossEntityRefMap =
+ oxmEntities.getCrossEntityReferences();
+
+ JSONObject entityJsonObject = getUebEntity(uebPayload);
+
+ JsonNode entityJsonNode = convertToJsonNode(entityJsonObject.toString());
+
+ for (String key : crossEntityRefMap.keySet()) {
+
+ /*
+ * if we know service-subscription is in the tree, then we can pull our all instances and
+ * process from there.
+ */
+
+ CrossEntityReference cerDescriptor = crossEntityRefMap.get(key);
+
+ ArrayList<JsonNode> foundNodes = new ArrayList<JsonNode>();
+
+ RouterServiceUtil.extractObjectsByKey(entityJsonNode, key, foundNodes);
+
+ if (foundNodes.size() > 0) {
+
+ for (JsonNode n : foundNodes) {
+
+ List<String> extractedParentEntityAttributeValues = new ArrayList<String>();
+
+ RouterServiceUtil.extractFieldValuesFromObject(n, cerDescriptor.getAttributeNames(),
+ extractedParentEntityAttributeValues);
+
+ List<JsonNode> nestedTargetEntityInstances = new ArrayList<JsonNode>();
+ RouterServiceUtil.extractObjectsByKey(n, cerDescriptor.getTargetEntityType(),
+ nestedTargetEntityInstances);
+
+ for (JsonNode targetEntityInstance : nestedTargetEntityInstances) {
+ /*
+ * Now:
+ * 1. build the AAIEntityType (IndexDocument) based on the extract entity
+ * 2. Get data from ES
+ * 3. Extract ETAG
+ * 4. Merge ES Doc + AAIEntityType + Extracted Parent Cross-Entity-Reference Values
+ * 5. Put data into ES with ETAG + updated doc
+ */
+
+ OxmEntityDescriptor searchableDescriptor =
+ oxmEntities.getSearchableEntityDescriptor(cerDescriptor.getTargetEntityType());
+
+ if (searchableDescriptor != null) {
+
+ if (!searchableDescriptor.getSearchableAttributes().isEmpty()) {
+
+ AaiEventEntity entityToSync = null;
+
+ try {
+
+ entityToSync = getPopulatedEntity(targetEntityInstance, searchableDescriptor);
+
+ /*
+ * Ready to do some ElasticSearch ops
+ */
+
+ for (String parentCrossEntityReferenceAttributeValue : extractedParentEntityAttributeValues) {
+ entityToSync
+ .addCrossEntityReferenceValue(parentCrossEntityReferenceAttributeValue);
+ }
+
+ entityToSync.setEntityPrimaryKeyName(entityPrimaryKeyFieldName);
+ entityToSync.setLink(entityLink);
+ entityToSync.deriveFields();
+
+ syncEntity(entityToSync);
+
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ }
+ } else {
+ logger.debug(EntityEventPolicyMsgs.CROSS_ENTITY_REFERENCE_SYNC,
+ "failure to find searchable descriptor for type "
+ + cerDescriptor.getTargetEntityType());
+ }
+ }
+
+ }
+
+ } else {
+ logger.debug(EntityEventPolicyMsgs.CROSS_ENTITY_REFERENCE_SYNC,
+ "failed to find 0 instances of cross-entity-reference with entity " + key);
+ }
+
+ }
+
+ } else {
+ logger.info(EntityEventPolicyMsgs.CROSS_ENTITY_REFERENCE_SYNC, "skipped due to OXM model for "
+ + topEntityType + " does not contain a cross-entity-reference entity");
+ }
+
+ /*
+ * Process for autosuggestable entities
+ */
+ if (oxmEntities != null) {
+ Map<String, OxmEntityDescriptor> rootDescriptor =
+ oxmEntities.getSuggestableEntityDescriptors();
+ if (!rootDescriptor.isEmpty()) {
+ List<String> suggestibleAttributes = extractSuggestableAttr(oxmEntities, entityType);
+
+ if (suggestibleAttributes == null) {
+ return;
+ }
+
+ List<String> suggestionAliases = extractAliasForSuggestableEntity(oxmEntities, entityType);
+ AggregationEntity ae = new AggregationEntity();
+ ae.setLink(entityLink);
+ ae.deriveFields(uebAsJson);
+
+ handleSuggestiveSearchData(ae, action, this.aggregationSearchVnfTarget);
+
+ /*
+ * 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)) {
+ SearchSuggestionPermutation searchSuggestionPermutation =
+ new SearchSuggestionPermutation();
+ List<ArrayList<String>> permutationsOfStatuses =
+ searchSuggestionPermutation.getSuggestionsPermutation(suggestibleAttributes);
+
+ // Now we have a list of all possible permutations for the status that are
+ // defined for this entity type. Try inserting a document for every combination.
+ for (ArrayList<String> permutation : permutationsOfStatuses) {
+ SuggestionSearchEntity suggestionSearchEntity = new SuggestionSearchEntity();
+ suggestionSearchEntity.setEntityType(entityType);
+ suggestionSearchEntity.setSuggestableAttr(permutation);
+ suggestionSearchEntity.setPayloadFromResponse(uebAsJson);
+ suggestionSearchEntity.setEntityTypeAliases(suggestionAliases);
+ suggestionSearchEntity.setSuggestionInputPermutations(
+ suggestionSearchEntity.generateSuggestionInputPermutations());
+
+ if (suggestionSearchEntity.isSuggestableDoc()) {
+ try {
+ suggestionSearchEntity.deriveFields();
+ } catch (NoSuchAlgorithmException e) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_UPDATING_SEARCH_SUGGESTION_DATA,
+ "Cannot create unique SHA digest for search suggestion data. Exception: "
+ + e.getLocalizedMessage());
+ }
+
+ handleSuggestiveSearchData(suggestionSearchEntity, action,
+ this.autoSuggestSearchTarget);
+ }
+ }
+ }
+ }
+ }
+
+ long stopTime = System.currentTimeMillis();
+
+ metricsLogger.info(EntityEventPolicyMsgs.OPERATION_RESULT_NO_ERRORS, PROCESS_AAI_EVENT,
+ String.valueOf(stopTime - startTime));
+
+ setResponse(exchange, ResponseType.SUCCESS, additionalInfo);
+ return;
+ }
+
+ public List<String> extractSuggestableAttr(VersionedOxmEntities oxmEntities, String entityType) {
+ // Extract suggestable attributes
+ Map<String, OxmEntityDescriptor> rootDescriptor = oxmEntities.getSuggestableEntityDescriptors();
+
+ if (rootDescriptor == null) {
+ return null;
+ }
+
+ OxmEntityDescriptor desc = rootDescriptor.get(entityType);
+
+ if (desc == null) {
+ return null;
+ }
+
+ return desc.getSuggestableAttributes();
+ }
+
+ public List<String> extractAliasForSuggestableEntity(VersionedOxmEntities oxmEntities,
+ String entityType) {
+
+ // Extract alias
+ Map<String, OxmEntityDescriptor> rootDescriptor = oxmEntities.getEntityAliasDescriptors();
+
+ if (rootDescriptor == null) {
+ return null;
+ }
+
+ OxmEntityDescriptor desc = rootDescriptor.get(entityType);
+ return desc.getAlias();
+ }
+
+ private void setResponse(Exchange exchange, ResponseType responseType, String additionalInfo) {
+
+ exchange.getOut().setHeader("ResponseType", responseType.toString());
+ exchange.getOut().setBody(additionalInfo);
+ }
+
+ public void extractDetailsForAutosuggestion(VersionedOxmEntities oxmEntities, String entityType,
+ List<String> suggestableAttr, List<String> alias) {
+
+ // Extract suggestable attributes
+ Map<String, OxmEntityDescriptor> rootDescriptor = oxmEntities.getSuggestableEntityDescriptors();
+
+ OxmEntityDescriptor desc = rootDescriptor.get(entityType);
+ suggestableAttr = desc.getSuggestableAttributes();
+
+ // Extract alias
+ rootDescriptor = oxmEntities.getEntityAliasDescriptors();
+ desc = rootDescriptor.get(entityType);
+ alias = desc.getAlias();
+ }
+
+ /*
+ * Load the UEB JSON payload, any errors would result to a failure case response.
+ */
+ private JSONObject getUebHeaderAsJson(String payload) {
+
+ JSONObject uebJsonObj;
+ JSONObject uebObjHeader;
+
+ 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(EVENT_HEADER)) {
+ uebObjHeader = uebJsonObj.getJSONObject(EVENT_HEADER);
+ } else {
+ logger.debug(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, EVENT_HEADER);
+ logger.error(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, EVENT_HEADER);
+ return null;
+ }
+
+ return uebObjHeader;
+ }
+
+
+ private UebEventHeader initializeUebEventHeader(String payload) {
+
+ UebEventHeader eventHeader = 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_HEADER);
+ logger.error(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, EVENT_HEADER);
+
+ return eventHeader;
+ }
+
+ // Marshal the supplied string into a UebEventHeader object.
+ try {
+ eventHeader = mapper.readValue(payload, UebEventHeader.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 (eventHeader != null) {
+ logger.debug(EntityEventPolicyMsgs.UEB_EVENT_HEADER_PARSED, eventHeader.toString());
+ }
+
+ return eventHeader;
+
+ }
+
+
+ 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, ENTITY_HEADER + " missing",
+ payload.toString());
+ logger.error(EntityEventPolicyMsgs.FAILED_TO_PARSE_UEB_PAYLOAD, ENTITY_HEADER + " missing",
+ "");
+ }
+
+ return jsonNode;
+ }
+
+ private boolean getSearchTags(AaiEventEntity aaiEventEntity, List<String> searchableAttr,
+ String payload, String action) {
+
+ boolean hasSearchableAttr = false;
+ for (String searchTagField : searchableAttr) {
+ String searchTagValue = null;
+ if (searchTagField.equalsIgnoreCase(aaiEventEntity.getEntityPrimaryKeyName())) {
+ searchTagValue = aaiEventEntity.getEntityPrimaryKeyValue();
+ } else {
+ searchTagValue = this.lookupValueUsingKey(payload, searchTagField);
+ }
+
+ if (searchTagValue != null && !searchTagValue.isEmpty()) {
+ hasSearchableAttr = true;
+ aaiEventEntity.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(String payload, 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;
+ }
+
+ private JSONObject getUebEntity(String payload) {
+ JSONObject uebJsonObj;
+
+ try {
+ uebJsonObj = new JSONObject(payload);
+ } catch (JSONException e) {
+ logger.debug(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_VERBOSE,
+ "Payload has invalid JSON Format", payload.toString());
+ logger.error(EntityEventPolicyMsgs.DISCARD_AAI_EVENT_NONVERBOSE,
+ "Payload has invalid JSON Format");
+ return null;
+ }
+
+ if (uebJsonObj.has(ENTITY_HEADER)) {
+ return uebJsonObj.getJSONObject(ENTITY_HEADER);
+ } else {
+ logger.debug(EntityEventPolicyMsgs.FAILED_TO_PARSE_UEB_PAYLOAD, ENTITY_HEADER + " missing",
+ payload.toString());
+ logger.error(EntityEventPolicyMsgs.FAILED_TO_PARSE_UEB_PAYLOAD, ENTITY_HEADER + " missing");
+ return null;
+ }
+ }
+
+ protected AaiEventEntity getPopulatedEntity(JsonNode entityNode,
+ OxmEntityDescriptor resultDescriptor) {
+ AaiEventEntity d = new AaiEventEntity();
+
+ d.setEntityType(resultDescriptor.getEntityName());
+
+ List<String> primaryKeyValues = new ArrayList<String>();
+ String pkeyValue = null;
+
+ for (String keyName : resultDescriptor.getPrimaryKeyAttributeName()) {
+ pkeyValue = RouterServiceUtil.getNodeFieldAsText(entityNode, keyName);
+ if (pkeyValue != null) {
+ primaryKeyValues.add(pkeyValue);
+ } 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 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;
+ }
+
+ private void syncEntity(AaiEventEntity aaiEventEntity) {
+ 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 = aaiEventEntity.getId();
+
+ // Run the GET to retrieve the ETAG from the search service
+ OperationResult storedEntity =
+ searchClient.get(entitySearchTarget + entityId, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) {
+ List<String> etag = storedEntity.getHeaders().get(Headers.ETAG);
+
+ if (etag != null && etag.size() > 0) {
+ headers.put(Headers.IF_MATCH, etag);
+ } else {
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE,
+ entitySearchTarget + entityId, entityId);
+ }
+
+ searchClient.put(entitySearchTarget + entityId, aaiEventEntity.getAsJson(), headers,
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+ } else {
+
+ if (storedEntity.getResultCode() == 404) {
+ // entity not found, so attempt to do a PUT
+ searchClient.put(entitySearchTarget + entityId, aaiEventEntity.getAsJson(), headers,
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+ } else {
+ logger.error(EntityEventPolicyMsgs.FAILED_TO_UPDATE_ENTITY_IN_DOCSTORE,
+ aaiEventEntity.getId(), "SYNC_ENTITY");
+ }
+ }
+ } catch (IOException e) {
+ logger.error(EntityEventPolicyMsgs.FAILED_TO_UPDATE_ENTITY_IN_DOCSTORE,
+ aaiEventEntity.getId(), "SYNC_ENTITY");
+ }
+ }
+
+ /**
+ * 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
+ * @param target Resource to perform the operation on
+ * @param allowDeleteEvent Allow delete operation to be performed on resource
+ */
+ private void handleSuggestiveSearchData(DocumentStoreDataEntity eventEntity, String action,
+ String target) {
+ 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 =
+ searchClient.get(target + entityId, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) {
+ List<String> etag = storedEntity.getHeaders().get(Headers.ETAG);
+
+ if (etag != null && etag.size() > 0) {
+ headers.put(Headers.IF_MATCH, etag);
+ } else {
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId,
+ entityId);
+ }
+ }
+
+ String eventEntityStr = eventEntity.getAsJson();
+
+ if (eventEntityStr != null) {
+ searchClient.put(target + entityId, eventEntity.getAsJson(), headers,
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+ }
+ } else if (action.equalsIgnoreCase(ACTION_CREATE)) {
+ String eventEntityStr = eventEntity.getAsJson();
+
+ if (eventEntityStr != null) {
+ searchClient.post(target, eventEntityStr, headers, MediaType.APPLICATION_JSON_TYPE,
+ MediaType.APPLICATION_JSON_TYPE);
+ }
+ } else if (action.equalsIgnoreCase(ACTION_DELETE)) {
+ // Run the GET to retrieve the ETAG from the search service
+ OperationResult storedEntity =
+ searchClient.get(target + entityId, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) {
+ List<String> etag = storedEntity.getHeaders().get(Headers.ETAG);
+
+ if (etag != null && etag.size() > 0) {
+ headers.put(Headers.IF_MATCH, etag);
+ } else {
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId,
+ entityId);
+ }
+
+ searchClient.delete(target + eventEntity.getId(), headers, null);
+ } else {
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId,
+ 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);
+ }
+ }
+
+ private void handleSearchServiceOperation(DocumentStoreDataEntity eventEntity, String action,
+ String target) {
+ 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();
+
+ // System.out.println("aaiEventEntity as json = " + aaiEventEntity.getAsJson());
+
+ if ((action.equalsIgnoreCase(ACTION_CREATE) && entityId != null)
+ || action.equalsIgnoreCase(ACTION_UPDATE)) {
+
+ // Run the GET to retrieve the ETAG from the search service
+ OperationResult storedEntity =
+ searchClient.get(target + entityId, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) {
+ List<String> etag = storedEntity.getHeaders().get(Headers.ETAG);
+
+ if (etag != null && etag.size() > 0) {
+ headers.put(Headers.IF_MATCH, etag);
+ } else {
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId,
+ entityId);
+ }
+ }
+
+ searchClient.put(target + entityId, eventEntity.getAsJson(), headers,
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+ } else if (action.equalsIgnoreCase(ACTION_CREATE)) {
+ searchClient.post(target, eventEntity.getAsJson(), headers, MediaType.APPLICATION_JSON_TYPE,
+ MediaType.APPLICATION_JSON_TYPE);
+ } else if (action.equalsIgnoreCase(ACTION_DELETE)) {
+ // Run the GET to retrieve the ETAG from the search service
+ OperationResult storedEntity =
+ searchClient.get(target + entityId, headers, MediaType.APPLICATION_JSON_TYPE);
+
+ if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) {
+ List<String> etag = storedEntity.getHeaders().get(Headers.ETAG);
+
+ if (etag != null && etag.size() > 0) {
+ headers.put(Headers.IF_MATCH, etag);
+ } else {
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId,
+ entityId);
+ }
+
+ searchClient.delete(target + eventEntity.getId(), headers, null);
+ } else {
+ logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId,
+ 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);
+ }
+ }
+
+ private void handleTopographicalData(String payload, String action, String entityType,
+ String oxmEntityType, DynamicJAXBContext oxmJaxbContext, String entityPrimaryKeyFieldName,
+ String entityPrimaryKeyFieldValue) {
+
+ Map<String, String> topoData = new HashMap<>();
+ String entityLink = "";
+ List<String> topographicalAttr =
+ getOxmAttributes(payload, oxmJaxbContext, oxmEntityType, entityType, "geoProps");
+ if (topographicalAttr == null) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_UPDATING_TOPOGRAPHY_DATA_NONVERBOSE,
+ "Topograhical attribute not found for payload entity type '" + entityType + "'");
+ logger.debug(EntityEventPolicyMsgs.DISCARD_UPDATING_TOPOGRAPHY_DATA_VERBOSE,
+ "Topograhical attribute not found for payload entity type '" + entityType + "'",
+ payload.toString());
+ } else {
+ entityLink = lookupValueUsingKey(payload, "entity-link");
+ for (String topoAttr : topographicalAttr) {
+ topoData.put(topoAttr, lookupValueUsingKey(payload, topoAttr));
+ }
+ updateTopographicalSearchDb(topoData, entityType, action, entityPrimaryKeyFieldName,
+ entityPrimaryKeyFieldValue, entityLink);
+ }
+
+ }
+
+ private void updateTopographicalSearchDb(Map<String, String> topoData, String entityType,
+ String action, String entityPrimaryKeyName, String entityPrimaryKeyValue, String entityLink) {
+
+ TopographicalEntity topoEntity = new TopographicalEntity();
+ topoEntity.setEntityPrimaryKeyName(entityPrimaryKeyName);
+ topoEntity.setEntityPrimaryKeyValue(entityPrimaryKeyValue);
+ topoEntity.setEntityType(entityType);
+ topoEntity.setLatitude(topoData.get(TOPO_LAT));
+ topoEntity.setLongitude(topoData.get(TOPO_LONG));
+ topoEntity.setSelfLink(entityLink);
+ try {
+ topoEntity.setId(TopographicalEntity.generateUniqueShaDigest(entityType, entityPrimaryKeyName,
+ entityPrimaryKeyValue));
+ } catch (NoSuchAlgorithmException e) {
+ logger.error(EntityEventPolicyMsgs.DISCARD_UPDATING_TOPOGRAPHY_DATA_VERBOSE,
+ "Cannot create unique SHA digest for topographical data.");
+ }
+
+ this.handleSearchServiceOperation(topoEntity, action, this.topographicalSearchTarget);
+ }
+
+
+ // 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
+ */
+ public 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;
+ }
+}