X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Forg%2Fopenecomp%2Fdatarouter%2Fpolicy%2FEntityEventPolicy.java;h=1cb8a6785829f4873b0822f7e767e980945e5dda;hb=b23528b8b1f60ff4f2f87a654f7a5d3f3edbbd0f;hp=afddad2604932d02d5badab22137940c7a8cd2d5;hpb=46e875640387b64c95ed1d70e8d38966dec75387;p=aai%2Fdata-router.git diff --git a/src/main/java/org/openecomp/datarouter/policy/EntityEventPolicy.java b/src/main/java/org/openecomp/datarouter/policy/EntityEventPolicy.java index afddad2..1cb8a67 100644 --- a/src/main/java/org/openecomp/datarouter/policy/EntityEventPolicy.java +++ b/src/main/java/org/openecomp/datarouter/policy/EntityEventPolicy.java @@ -1,16 +1,15 @@ /** * ============LICENSE_START======================================================= - * DataRouter + * org.onap.aai * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. * 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 + * 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, @@ -19,18 +18,10 @@ * limitations under the License. * ============LICENSE_END========================================================= * - * ECOMP and OpenECOMP are trademarks - * and service marks of AT&T Intellectual Property. + * ECOMP is a trademark and service mark 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.fasterxml.jackson.databind.node.ObjectNode; -import com.sun.jersey.core.util.MultivaluedMapImpl; - import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -71,25 +62,33 @@ 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.NodeUtils; import org.openecomp.datarouter.util.OxmModelLoader; import org.openecomp.datarouter.util.RouterServiceUtil; +import org.openecomp.datarouter.util.SearchServiceAgent; 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.enums.RestAuthenticationMode; import org.openecomp.restclient.rest.HttpUtil; -import org.openecomp.datarouter.util.NodeUtils; 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; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.sun.jersey.core.util.MultivaluedMapImpl; + 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 externalOxmModelProcessors; - RestClient searchClient = null; private final String EVENT_HEADER = "event-header"; private final String ENTITY_HEADER = "entity"; @@ -106,9 +105,19 @@ public class EntityEventPolicy implements Processor { Map oxmVersionContextMap = new HashMap<>(); private String oxmVersion = null; - private String entityIndexTarget = null; + /** Agent for communicating with the Search Service. */ + private SearchServiceAgent searchAgent = null; + + /** Search index name for storing AAI event entities. */ + private String entitySearchIndex; + + /** Search index name for storing topographical search data. */ + private String topographicalSearchIndex; + + /** Search index name for suggestive search data. */ + private String aggregateGenericVnfIndex; + private String entitySearchTarget = null; - private String topographicalIndexTarget = null; private String topographicalSearchTarget = null; private String autoSuggestSearchTarget = null; private String aggregationSearchVnfTarget = null; @@ -131,27 +140,27 @@ public class EntityEventPolicy implements Processor { srcDomain = config.getSourceDomain(); - entityIndexTarget = - EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(), config.getSearchEndpoint(), - config.getSearchEntitySearchIndex()); + // Populate the index names. + entitySearchIndex = config.getSearchEntitySearchIndex(); + topographicalSearchIndex = config.getSearchTopographySearchIndex(); + aggregateGenericVnfIndex = config.getSearchAggregationVnfIndex(); + + // Instantiate the agent that we will use for interacting with the Search Service. + searchAgent = new SearchServiceAgent(config.getSearchCertName(), + config.getSearchKeystore(), + config.getSearchKeystorePwd(), + EntityEventPolicy.concatSubUri(config.getSearchBaseUrl(), + config.getSearchEndpoint()), + config.getSearchEndpointDocuments(), + logger); 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()); @@ -193,73 +202,12 @@ public class EntityEventPolicy implements Processor { public void startup() { // Create the indexes in the search service if they do not already exist. - createSearchIndex(entityIndexTarget, entitySearchSchema); - createSearchIndex(topographicalIndexTarget, topographicalSearchSchema); + searchAgent.createSearchIndex(entitySearchIndex, entitySearchSchema); + searchAgent.createSearchIndex(topographicalSearchIndex, 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 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. @@ -306,9 +254,15 @@ public class EntityEventPolicy implements Processor { } // Load the UEB payload data, any errors will result in a failure and discard - JSONObject uebObjHeader = getUebHeaderAsJson(uebPayload); + JSONObject uebObjHeader = getUebContentAsJson(uebPayload, EVENT_HEADER); if (uebObjHeader == null) { - returnWithError(exchange, uebPayload, "Payload is missing event-header"); + returnWithError(exchange, uebPayload, "Payload is missing " + EVENT_HEADER); + return; + } + + JSONObject uebObjEntity = getUebContentAsJson(uebPayload, ENTITY_HEADER); + if (uebObjEntity == null) { + returnWithError(exchange, uebPayload, "Payload is missing " + ENTITY_HEADER); return; } @@ -456,7 +410,7 @@ public class EntityEventPolicy implements Processor { return; } - handleSearchServiceOperation(aaiEventEntity, action, this.entitySearchTarget); + handleSearchServiceOperation(aaiEventEntity, action, entitySearchIndex); handleTopographicalData(uebPayload, action, entityType, oxmEntityType, oxmJaxbContext, entityPrimaryKeyFieldName, entityPrimaryKeyFieldValue); @@ -612,9 +566,17 @@ public class EntityEventPolicy implements Processor { Map rootDescriptor = oxmEntities.getSuggestableEntityDescriptors(); if (!rootDescriptor.isEmpty()) { - List suggestibleAttributes = extractSuggestableAttr(oxmEntities, entityType); + List suggestibleAttrInPayload = new ArrayList(); + List suggestibleAttrInOxm = extractSuggestableAttr(oxmEntities, entityType); + if (suggestibleAttrInOxm != null) { + for (String attr: suggestibleAttrInOxm){ + if ( uebObjEntity.has(attr) ){ + suggestibleAttrInPayload.add(attr); + } + } + } - if (suggestibleAttributes == null) { + if (suggestibleAttrInPayload.isEmpty()) { return; } @@ -623,39 +585,38 @@ public class EntityEventPolicy implements Processor { ae.setLink(entityLink); ae.deriveFields(uebAsJson); - handleSuggestiveSearchData(ae, action, this.aggregationSearchVnfTarget); + handleSearchServiceOperation(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> 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 permutation : permutationsOfStatuses) { + List> 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 list : listOfValidPowerSetElements) { SuggestionSearchEntity suggestionSearchEntity = new SuggestionSearchEntity(); suggestionSearchEntity.setEntityType(entityType); - suggestionSearchEntity.setSuggestableAttr(permutation); - suggestionSearchEntity.setPayloadFromResponse(uebAsJson); + suggestionSearchEntity.setSuggestableAttr(list); suggestionSearchEntity.setEntityTypeAliases(suggestionAliases); + suggestionSearchEntity.setFilterBasedPayloadFromResponse(uebAsJson.get("entity"), + suggestibleAttrInOxm, list); suggestionSearchEntity.setSuggestionInputPermutations( suggestionSearchEntity.generateSuggestionInputPermutations()); if (suggestionSearchEntity.isSuggestableDoc()) { try { - suggestionSearchEntity.deriveFields(); + 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()); } - handleSuggestiveSearchData(suggestionSearchEntity, action, + handleSearchServiceOperation(suggestionSearchEntity, action, this.autoSuggestSearchTarget); } } @@ -727,10 +688,10 @@ public class EntityEventPolicy implements Processor { /* * Load the UEB JSON payload, any errors would result to a failure case response. */ - private JSONObject getUebHeaderAsJson(String payload) { + private JSONObject getUebContentAsJson(String payload, String contentKey) { JSONObject uebJsonObj; - JSONObject uebObjHeader; + JSONObject uebObjContent; try { uebJsonObj = new JSONObject(payload); @@ -740,15 +701,15 @@ public class EntityEventPolicy implements Processor { return null; } - if (uebJsonObj.has(EVENT_HEADER)) { - uebObjHeader = uebJsonObj.getJSONObject(EVENT_HEADER); + if (uebJsonObj.has(contentKey)) { + uebObjContent = uebJsonObj.getJSONObject(contentKey); } else { - logger.debug(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, EVENT_HEADER); - logger.error(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, EVENT_HEADER); + logger.debug(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, contentKey); + logger.error(EntityEventPolicyMsgs.UEB_FAILED_TO_PARSE_PAYLOAD, contentKey); return null; } - return uebObjHeader; + return uebObjContent; } @@ -955,8 +916,7 @@ public class EntityEventPolicy implements Processor { String jsonPayload = aaiEventEntity.getAsJson(); // Run the GET to retrieve the ETAG from the search service - OperationResult storedEntity = - searchClient.get(entitySearchTarget+entityId, headers, MediaType.APPLICATION_JSON_TYPE); + OperationResult storedEntity = searchAgent.getDocument(entitySearchIndex, entityId); if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) { /* @@ -997,16 +957,14 @@ public class EntityEventPolicy implements Processor { // Do the PUT with new CER ((ObjectNode)node).put("crossEntityReferenceValues", newCer); jsonPayload = NodeUtils.convertObjectToJson(node, false); - searchClient.put(entitySearchTarget + entityId, jsonPayload, headers, - MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE); + searchAgent.putDocument(entitySearchIndex, entityId, jsonPayload, headers); } } } 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); + searchAgent.putDocument(entitySearchIndex, entityId, aaiEventEntity.getAsJson(), headers); } else { logger.error(EntityEventPolicyMsgs.FAILED_TO_UPDATE_ENTITY_IN_DOCSTORE, aaiEventEntity.getId(), "SYNC_ENTITY"); @@ -1027,76 +985,9 @@ public class EntityEventPolicy implements Processor { * @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> 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 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 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) { + private void handleSearchServiceOperation(DocumentStoreDataEntity eventEntity, + String action, + String index) { try { Map> headers = new HashMap<>(); @@ -1111,8 +1002,7 @@ public class EntityEventPolicy implements Processor { || 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); + OperationResult storedEntity = searchAgent.getDocument(index, entityId); if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) { List etag = storedEntity.getHeaders().get(Headers.ETAG); @@ -1120,20 +1010,21 @@ public class EntityEventPolicy implements Processor { if (etag != null && etag.size() > 0) { headers.put(Headers.IF_MATCH, etag); } else { - logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId, + logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, index, entityId); } } - searchClient.put(target + entityId, eventEntity.getAsJson(), headers, - MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE); + // Write the entity to the search service. + // PUT + searchAgent.putDocument(index, entityId, eventEntity.getAsJson(), headers); } else if (action.equalsIgnoreCase(ACTION_CREATE)) { - searchClient.post(target, eventEntity.getAsJson(), headers, MediaType.APPLICATION_JSON_TYPE, - MediaType.APPLICATION_JSON_TYPE); + // 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 = - searchClient.get(target + entityId, headers, MediaType.APPLICATION_JSON_TYPE); + OperationResult storedEntity = searchAgent.getDocument(index, entityId); if (HttpUtil.isHttpResponseClassSuccess(storedEntity.getResultCode())) { List etag = storedEntity.getHeaders().get(Headers.ETAG); @@ -1141,13 +1032,13 @@ public class EntityEventPolicy implements Processor { if (etag != null && etag.size() > 0) { headers.put(Headers.IF_MATCH, etag); } else { - logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId, + logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, index, entityId); } - searchClient.delete(target + eventEntity.getId(), headers, null); + searchAgent.deleteDocument(index, eventEntity.getId(), headers); } else { - logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, target + entityId, + logger.error(EntityEventPolicyMsgs.NO_ETAG_AVAILABLE_FAILURE, index, entityId); } } else {