From 60f7f5e11d7d0d7870a4650956921bd1afa309fd Mon Sep 17 00:00:00 2001 From: abatos Date: Fri, 12 May 2017 14:11:30 -0400 Subject: Initial ONAP Synapse commit Change-Id: I3a0ed659dbb8f8faeeb54093b5d6f10414cd886e Signed-off-by: abatos --- .../datarouter/entity/AaiEventEntity.java | 315 ++++++ .../datarouter/entity/AggregationEntity.java | 124 +++ .../datarouter/entity/DocumentStoreDataEntity.java | 35 + .../datarouter/entity/OxmEntityDescriptor.java | 126 +++ .../datarouter/entity/PolicyResponse.java | 72 ++ .../datarouter/entity/SuggestionSearchEntity.java | 281 +++++ .../datarouter/entity/TopographicalEntity.java | 191 ++++ .../datarouter/entity/UebEventHeader.java | 169 +++ .../exception/BaseDataRouterException.java | 89 ++ .../datarouter/exception/DataRouterError.java | 106 ++ .../datarouter/logging/DataRouterMsgs.java | 161 +++ .../datarouter/logging/EntityEventPolicyMsgs.java | 218 ++++ .../datarouter/policy/EntityEventPolicy.java | 1162 ++++++++++++++++++++ .../datarouter/policy/EntityEventPolicyConfig.java | 129 +++ .../openecomp/datarouter/service/EchoService.java | 97 ++ .../datarouter/util/CrossEntityReference.java | 97 ++ .../datarouter/util/DataRouterConstants.java | 57 + .../datarouter/util/DataRouterProperties.java | 53 + .../datarouter/util/EntityOxmReferenceHelper.java | 62 ++ .../datarouter/util/ExternalOxmModelProcessor.java | 37 + .../org/openecomp/datarouter/util/FileWatcher.java | 49 + .../org/openecomp/datarouter/util/NodeUtils.java | 46 + .../openecomp/datarouter/util/OxmModelLoader.java | 166 +++ .../datarouter/util/RouterServiceUtil.java | 226 ++++ .../util/SearchSuggestionPermutation.java | 89 ++ .../org/openecomp/datarouter/util/Version.java | 29 + .../datarouter/util/VersionedOxmEntities.java | 352 ++++++ 27 files changed, 4538 insertions(+) create mode 100644 src/main/java/org/openecomp/datarouter/entity/AaiEventEntity.java create mode 100644 src/main/java/org/openecomp/datarouter/entity/AggregationEntity.java create mode 100644 src/main/java/org/openecomp/datarouter/entity/DocumentStoreDataEntity.java create mode 100644 src/main/java/org/openecomp/datarouter/entity/OxmEntityDescriptor.java create mode 100644 src/main/java/org/openecomp/datarouter/entity/PolicyResponse.java create mode 100644 src/main/java/org/openecomp/datarouter/entity/SuggestionSearchEntity.java create mode 100644 src/main/java/org/openecomp/datarouter/entity/TopographicalEntity.java create mode 100644 src/main/java/org/openecomp/datarouter/entity/UebEventHeader.java create mode 100644 src/main/java/org/openecomp/datarouter/exception/BaseDataRouterException.java create mode 100644 src/main/java/org/openecomp/datarouter/exception/DataRouterError.java create mode 100644 src/main/java/org/openecomp/datarouter/logging/DataRouterMsgs.java create mode 100644 src/main/java/org/openecomp/datarouter/logging/EntityEventPolicyMsgs.java create mode 100644 src/main/java/org/openecomp/datarouter/policy/EntityEventPolicy.java create mode 100644 src/main/java/org/openecomp/datarouter/policy/EntityEventPolicyConfig.java create mode 100644 src/main/java/org/openecomp/datarouter/service/EchoService.java create mode 100644 src/main/java/org/openecomp/datarouter/util/CrossEntityReference.java create mode 100644 src/main/java/org/openecomp/datarouter/util/DataRouterConstants.java create mode 100644 src/main/java/org/openecomp/datarouter/util/DataRouterProperties.java create mode 100644 src/main/java/org/openecomp/datarouter/util/EntityOxmReferenceHelper.java create mode 100644 src/main/java/org/openecomp/datarouter/util/ExternalOxmModelProcessor.java create mode 100644 src/main/java/org/openecomp/datarouter/util/FileWatcher.java create mode 100644 src/main/java/org/openecomp/datarouter/util/NodeUtils.java create mode 100644 src/main/java/org/openecomp/datarouter/util/OxmModelLoader.java create mode 100644 src/main/java/org/openecomp/datarouter/util/RouterServiceUtil.java create mode 100644 src/main/java/org/openecomp/datarouter/util/SearchSuggestionPermutation.java create mode 100644 src/main/java/org/openecomp/datarouter/util/Version.java create mode 100644 src/main/java/org/openecomp/datarouter/util/VersionedOxmEntities.java (limited to 'src/main/java') diff --git a/src/main/java/org/openecomp/datarouter/entity/AaiEventEntity.java b/src/main/java/org/openecomp/datarouter/entity/AaiEventEntity.java new file mode 100644 index 0000000..418c0d3 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/entity/AaiEventEntity.java @@ -0,0 +1,315 @@ +/** + * ============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. + */ +/* +* ============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.entity; + +import java.io.IOException; +import java.io.Serializable; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +import javax.json.Json; +import javax.json.JsonObject; + +/** + * Note: AAIEventEntity is a port forward of IndexDocument Has been renamed here to move forward + * with abstraction of document store technology. + */ +public class AaiEventEntity implements DocumentStoreDataEntity, Serializable { + + private static final long serialVersionUID = -5188479658230319058L; + + protected String entityType; + protected String entityPrimaryKeyName; + protected String entityPrimaryKeyValue; + protected ArrayList searchTagCollection = new ArrayList(); + protected ArrayList searchTagIdCollection = new ArrayList(); + protected ArrayList crossEntityReferenceCollection = new ArrayList(); + protected String lastmodTimestamp; + protected String link; + + private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; + /* + * Generated fields, leave the settings for junit overrides + */ + + // generated, SHA-256 digest + protected String id; + + /* + * generated based on searchTagCollection values + */ + protected String searchTags; + protected String searchTagIds; + protected String crossReferenceEntityValues; + + + private static String convertBytesToHexString(byte[] bytesToConvert) { + StringBuffer hexString = new StringBuffer(); + for (int i = 0; i < bytesToConvert.length; i++) { + hexString.append(Integer.toHexString(0xFF & bytesToConvert[i])); + } + return hexString.toString(); + } + + private static String concatArray(List list, char delimiter) { + + if (list == null || list.size() == 0) { + return ""; + } + + StringBuilder result = new StringBuilder(64); + + int listSize = list.size(); + boolean firstValue = true; + + for (String item : list) { + + if (firstValue) { + result.append(item); + firstValue = false; + } else { + result.append(delimiter).append(item); + } + + } + + return result.toString(); + + } + + /* + * We'll try and create a unique identity key that we can use for differencing the previously + * imported record sets as we won't have granular control of what is created/removed and when. The + * best we can hope for is identification of resources by generated Id until the Identity-Service + * UUID is tagged against all resources, then we can use that instead. + */ + + private static String generateUniqueShaDigest(String entityType, String fieldName, + String fieldValue) throws NoSuchAlgorithmException { + + /* + * Basically SHA-256 will result in an identity with a guaranteed uniqueness compared to just a + * java hashcode value. + */ + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + digest.update(String.format("%s.%s.%s", entityType, fieldName, fieldValue).getBytes()); + return convertBytesToHexString(digest.digest()); + } + + + public AaiEventEntity() { + SimpleDateFormat dateFormat = new SimpleDateFormat(TIMESTAMP_FORMAT); + Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + String currentFormattedTimeStamp = dateFormat.format(timestamp); + this.lastmodTimestamp = currentFormattedTimeStamp; + } + + public void deriveFields() throws NoSuchAlgorithmException { + this.id = generateUniqueShaDigest(entityType, entityPrimaryKeyName, entityPrimaryKeyValue); + this.searchTags = concatArray(searchTagCollection, ';'); + this.searchTagIds = concatArray(searchTagIdCollection, ';'); + this.crossReferenceEntityValues = concatArray(crossEntityReferenceCollection, ';'); + } + + + /* + * (non-Javadoc) + * + * @see org.openecomp.datarouter.entity.AAIEventEntity#getAsJson() + */ + @Override + public String getAsJson() throws IOException { + + JsonObject obj = Json.createObjectBuilder().add("entityType", entityType) + .add("entityPrimaryKeyValue", entityPrimaryKeyValue).add("searchTagIDs", searchTagIds) + .add("searchTags", searchTags).add("crossEntityReferenceValues", crossReferenceEntityValues) + .add("lastmodTimestamp", lastmodTimestamp).add("link", link).build(); + + return obj.toString(); + } + + + public void addSearchTagWithKey(String searchTag, String key) { + searchTagIdCollection.add(key); + searchTagCollection.add(searchTag); + } + + public void addCrossEntityReferenceValue(String crossEntityReferenceValue) { + if (!crossEntityReferenceCollection.contains(crossEntityReferenceValue)) { + crossEntityReferenceCollection.add(crossEntityReferenceValue); + } + } + + public String getEntityType() { + return entityType; + } + + public String getEntityPrimaryKeyName() { + return entityPrimaryKeyName; + } + + public String getEntityPrimaryKeyValue() { + return entityPrimaryKeyValue; + } + + + /* + * (non-Javadoc) + * + * @see org.openecomp.datarouter.entity.AAIEventEntity#getId() + */ + @Override + public String getId() { + return id; + } + + public ArrayList getSearchTagCollection() { + return searchTagCollection; + } + + public String getSearchTags() { + return searchTags; + } + + public String getSearchTagIDs() { + return searchTagIds; + } + + public void setSearchTagIDs(String searchTagIDs) { + this.searchTagIds = searchTagIDs; + } + + public void setEntityType(String entityType) { + this.entityType = entityType; + } + + public void setId(String id) { + this.id = id; + } + + public void setSearchTagCollection(ArrayList searchTagCollection) { + this.searchTagCollection = searchTagCollection; + } + + public void setSearchTags(String searchTags) { + this.searchTags = searchTags; + } + + public ArrayList getSearchTagIdCollection() { + return searchTagIdCollection; + } + + public void setSearchTagIdCollection(ArrayList searchTagIdCollection) { + this.searchTagIdCollection = searchTagIdCollection; + } + + public String getLastmodTimestamp() { + return lastmodTimestamp; + } + + public void setLastmodTimestamp(String lastmodTimestamp) { + this.lastmodTimestamp = lastmodTimestamp; + } + + public void setEntityPrimaryKeyName(String entityPrimaryKeyName) { + this.entityPrimaryKeyName = entityPrimaryKeyName; + } + + public void setEntityPrimaryKeyValue(String entityPrimaryKeyValue) { + this.entityPrimaryKeyValue = entityPrimaryKeyValue; + } + + public String getLink() { + return link; + } + + public void setLink(String link) { + this.link = link; + } + + /* + * public void mergeEntity(AAIEventEntity entityToMergeIn) { + * + * if ( entityToMergeIn == null ) { return; } + * + * if ( !entityToMergeIn.getEntityType().equals( entityType )) { entityType = + * entityToMergeIn.getEntityType(); } + * + * if ( !entityToMergeIn.getEntityType().equals( entityType )) { entityType = + * entityToMergeIn.getEntityType(); } + * + * } + */ + + @Override + public String toString() { + return "AAIEventEntity [" + (entityType != null ? "entityType=" + entityType + ", " : "") + + (entityPrimaryKeyName != null ? "entityPrimaryKeyName=" + entityPrimaryKeyName + ", " + : "") + + (entityPrimaryKeyValue != null ? "entityPrimaryKeyValue=" + entityPrimaryKeyValue + ", " + : "") + + (searchTagCollection != null ? "searchTagCollection=" + searchTagCollection + ", " : "") + + (searchTagIdCollection != null ? "searchTagIDCollection=" + searchTagIdCollection + ", " + : "") + + (crossEntityReferenceCollection != null + ? "crossEntityReferenceCollection=" + crossEntityReferenceCollection + ", " : "") + + "lastmodTimestamp=" + lastmodTimestamp + ", " + (id != null ? "id=" + id + ", " : "") + + (searchTags != null ? "searchTags=" + searchTags + ", " : "") + + (searchTagIds != null ? "searchTagIDs=" + searchTagIds + ", " : "") + + (crossReferenceEntityValues != null + ? "crossReferenceEntityValues=" + crossReferenceEntityValues : "") + + "]"; + } + +} diff --git a/src/main/java/org/openecomp/datarouter/entity/AggregationEntity.java b/src/main/java/org/openecomp/datarouter/entity/AggregationEntity.java new file mode 100644 index 0000000..4830d67 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/entity/AggregationEntity.java @@ -0,0 +1,124 @@ +/** + * ============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.entity; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import org.openecomp.datarouter.util.NodeUtils; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * The Class AggregationEntity. Mimics functionality of AAIUI's AggregationEntity + */ +public class AggregationEntity 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; + } + 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 attributes = new HashMap(); + ObjectMapper mapper = new ObjectMapper(); + + /** + * Instantiates a new aggregation entity. + */ + public AggregationEntity() { } + + public void deriveFields(JsonNode uebPayload) { + + this.setId(NodeUtils.generateUniqueShaDigest(link)); + + this.setLastmodTimestamp(Long.toString(System.currentTimeMillis())); + + JsonNode entityNode = uebPayload.get("entity"); + + Iterator> nodes = entityNode.fields(); + + while (nodes.hasNext()) { + Map.Entry entry = (Map.Entry) nodes.next(); + if (!entry.getKey().equalsIgnoreCase("relationship-list")){ + attributes.put(entry.getKey(), entry.getValue().asText()); + } + } + } + + public void copyAttributeKeyValuePair(Map map){ + for(String key: map.keySet()){ + if (!key.equalsIgnoreCase("relationship-list")){ // ignore relationship data which is not required in aggregation + this.attributes.put(key, map.get(key).toString()); // not sure if entity attribute can contain an object as value + } + } + } + + public void addAttributeKeyValuePair(String key, String value){ + this.attributes.put(key, value); + } + + public String getAsJson() { + ObjectNode rootNode = mapper.createObjectNode(); + rootNode.put("link", this.getLink()); + rootNode.put("lastmodTimestamp", lastmodTimestamp); + for (String key: this.attributes.keySet()){ + rootNode.put(key, this.attributes.get(key)); + } + return rootNode.toString(); + } + + @Override + public String toString() { + return "AggregationEntity [id=" + id + ", link=" + link + ", attributes=" + attributes + + ", mapper=" + mapper + "]"; + } +} diff --git a/src/main/java/org/openecomp/datarouter/entity/DocumentStoreDataEntity.java b/src/main/java/org/openecomp/datarouter/entity/DocumentStoreDataEntity.java new file mode 100644 index 0000000..61df316 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/entity/DocumentStoreDataEntity.java @@ -0,0 +1,35 @@ +/** + * ============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.entity; + +import java.io.IOException; + +public interface DocumentStoreDataEntity { + + public String getId(); + + public String getAsJson() throws IOException; + +} diff --git a/src/main/java/org/openecomp/datarouter/entity/OxmEntityDescriptor.java b/src/main/java/org/openecomp/datarouter/entity/OxmEntityDescriptor.java new file mode 100644 index 0000000..9f486e4 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/entity/OxmEntityDescriptor.java @@ -0,0 +1,126 @@ +/** + * ============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.entity; + +import java.util.List; + +import org.openecomp.datarouter.util.CrossEntityReference; + + +public class OxmEntityDescriptor { + + private String entityName; + + private List primaryKeyAttributeName; + + private List searchableAttributes; + + private CrossEntityReference crossEntityReference; + + private List alias; + + private List suggestableAttributes; + + boolean isSuggestableEntity; + + public String getEntityName() { + return entityName; + } + + public void setEntityName(String entityName) { + this.entityName = entityName; + } + + public List getPrimaryKeyAttributeName() { + return primaryKeyAttributeName; + } + + public void setPrimaryKeyAttributeName(List primaryKeyAttributeName) { + this.primaryKeyAttributeName = primaryKeyAttributeName; + } + + public List getSearchableAttributes() { + return searchableAttributes; + } + + public void setSearchableAttributes(List searchableAttributes) { + this.searchableAttributes = searchableAttributes; + } + + public boolean hasSearchableAttributes() { + + if ( this.searchableAttributes == null) { + return false; + } + + if ( this.searchableAttributes.size() > 0 ) { + return true; + } + + return false; + + } + + public CrossEntityReference getCrossEntityReference() { + return crossEntityReference; + } + + public void setCrossEntityReference(CrossEntityReference crossEntityReference) { + this.crossEntityReference = crossEntityReference; + } + + public List getAlias() { + return alias; + } + + public void setAlias(List alias) { + this.alias = alias; + } + + public List getSuggestableAttributes() { + return suggestableAttributes; + } + + public void setSuggestableAttributes(List suggestableAttributes) { + this.suggestableAttributes = suggestableAttributes; + } + + public boolean isSuggestableEntity() { + return isSuggestableEntity; + } + + public void setSuggestableEntity(boolean isSuggestableEntity) { + this.isSuggestableEntity = isSuggestableEntity; + } + + @Override + public String toString() { + return "OxmEntityDescriptor [entityName=" + entityName + ", primaryKeyAttributeName=" + + primaryKeyAttributeName + ", searchableAttributes=" + searchableAttributes + + ", crossEntityReference=" + crossEntityReference + ", alias=" + alias + + ", suggestableAttributes=" + suggestableAttributes + ", isSuggestableEntity=" + + isSuggestableEntity + "]"; + } +} \ No newline at end of file diff --git a/src/main/java/org/openecomp/datarouter/entity/PolicyResponse.java b/src/main/java/org/openecomp/datarouter/entity/PolicyResponse.java new file mode 100644 index 0000000..fd577fa --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/entity/PolicyResponse.java @@ -0,0 +1,72 @@ +/** + * ============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.entity; + +/** + * Provides information about the level of success of a policy execution against a routed query. + */ +public class PolicyResponse { + + private ResponseType responseType; + + private String responseData; + + private int httpResponseCode; + + public PolicyResponse(ResponseType responseType, String responseData) { + super(); + this.responseType = responseType; + this.responseData = responseData; + } + + public ResponseType getResponseType() { + return responseType; + } + + public String getResponseData() { + return responseData; + } + + + public int getHttpResponseCode() { + return httpResponseCode; + } + + public void setHttpResponseCode(int httpResponseCode) { + this.httpResponseCode = httpResponseCode; + } + + @Override + public String toString() { + return "PolicyResponse [responseType=" + responseType + ", responseData=" + responseData + + ", httpResponseCode=" + httpResponseCode + "]"; + } + + + + public enum ResponseType { + SUCCESS, PARTIAL_SUCCESS, FAILURE; + } +} diff --git a/src/main/java/org/openecomp/datarouter/entity/SuggestionSearchEntity.java b/src/main/java/org/openecomp/datarouter/entity/SuggestionSearchEntity.java new file mode 100644 index 0000000..ae2711b --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/entity/SuggestionSearchEntity.java @@ -0,0 +1,281 @@ +/** + * ============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.entity; + +import java.io.IOException; +import java.io.Serializable; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.openecomp.datarouter.util.NodeUtils; + +import com.fasterxml.jackson.databind.JsonNode; + +public class SuggestionSearchEntity implements DocumentStoreDataEntity, Serializable { + private static final long serialVersionUID = -3636393943669310760L; + + protected String id; // generated SHA-256 digest + private String entityType; + private List entityTypeAliases; + private List suggestionInputPermutations = new ArrayList<>(); + private List statusPermutations = new ArrayList<>(); + private List suggestableAttr = new ArrayList<>(); + private Map payload = new HashMap<>(); + private JSONObject payloadJsonNode = new JSONObject(); + private StringBuffer outputString = new StringBuffer(); + + public void deriveFields() throws NoSuchAlgorithmException { + int payloadEntryCounter = 1; + + for (Map.Entry payload : getPayload().entrySet()) { + if (payload.getValue() != null && payload.getValue().length() > 0) { + this.getPayloadJsonNode().put(payload.getKey(), payload.getValue()); + this.outputString.append(payload.getValue()); + + if (payloadEntryCounter < getPayload().entrySet().size()) { + this.outputString.append(" and "); + } else { + this.outputString.append(" "); + } + } + + payloadEntryCounter++; + } + + this.outputString.append(getEntityTypeAliases().get(0)); + this.id = NodeUtils.generateUniqueShaDigest(outputString.toString()); + } + + /** + * Launch pad for performing permutations of the entity type, aliases, prov status and orchestration status. + * SHA-256 will result in an ID with a guaranteed uniqueness compared to just a java hashcode value. + * @return + */ + public List generateSuggestionInputPermutations() { + List entityNames = new ArrayList<>(); + entityNames.add(entityType); + + if ((entityTypeAliases != null) && !(entityTypeAliases.isEmpty())) { + for (String alias : entityTypeAliases) { + entityNames.add(alias); + } + } + + ArrayList listToPermutate = new ArrayList<>(statusPermutations); + ArrayList listOfSearchSuggestionPermutations = new ArrayList<>(); + + for (String entityName : entityNames) { + listToPermutate.add(entityName); + permutateList(listToPermutate, new ArrayList(), listToPermutate.size(), listOfSearchSuggestionPermutations); + listToPermutate.remove(entityName); + } + + return listOfSearchSuggestionPermutations; + } + + public boolean isSuggestableDoc() { + return this.getPayload().size() != 0; + } + + /** + * Generate all permutations of Entity Type and (Prov Status and/or Orchestration Status) + * @param list The list of unique elements to create permutations of + * @param permutation A list to hold the current permutation used during + * @param size To keep track of the original size of the number of unique elements + * @param listOfSearchSuggestionPermutationList The list to hold all of the different permutations + */ + private void permutateList(List list, List permutation, int size, + List listOfSearchSuggestionPermutationList) { + if (permutation.size() == size) { + StringBuilder newPermutation = new StringBuilder(); + + for (int i = 0; i < permutation.size(); i++) { + newPermutation.append(permutation.get(i)).append(" "); + } + + listOfSearchSuggestionPermutationList.add(newPermutation.toString().trim()); + + return; + } + + String[] availableItems = list.toArray(new String[0]); + + for (String i : availableItems) { + permutation.add(i); + list.remove(i); + permutateList(list, permutation, size, listOfSearchSuggestionPermutationList); + list.add(i); + permutation.remove(i); + } + } + + /** + * return Custom-built JSON representation of this class + */ + @Override + public String getAsJson() throws IOException { + if (entityType == null || suggestionInputPermutations == null) { + return null; + } + + JSONObject rootNode = new JSONObject(); + JSONArray inputArray = new JSONArray(); + JSONObject payloadNode = new JSONObject(); + StringBuffer outputString = new StringBuffer(); + + int payloadEntryCounter = 1; + + // Add prov and orchestration status to search suggestion string + for (Map.Entry payload : getPayload().entrySet()) { + payloadNode.put(payload.getKey(), payload.getValue()); + outputString.append(payload.getValue()); + + if (payloadEntryCounter < getPayload().entrySet().size()) { + // Add the word "and" between prov and orchestration statuses, if both are present + outputString.append(" and "); + payloadEntryCounter++; + } + } + + // Add entity type to search suggestion string. We've decided to use the first entity type alias from the OXM + outputString.append(" ").append(getEntityTypeAliases().get(0)); + + for (String permutation : suggestionInputPermutations) { + inputArray.put(permutation); + } + + // Build up the search suggestion as JSON + JSONObject entitySuggest = new JSONObject(); + entitySuggest.put("input", inputArray); + entitySuggest.put("output", outputString); + entitySuggest.put("payload", payloadNode); + rootNode.put("entity_suggest", entitySuggest); + + return rootNode.toString(); + } + + public String getEntityType() { + return entityType; + } + + public void setEntityType(String entityType) { + this.entityType = entityType; + } + + public List getEntityTypeAliases() { + return entityTypeAliases; + } + + public void setEntityTypeAliases(List entityTypeAliases) { + this.entityTypeAliases = entityTypeAliases; + } + + @Override + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public StringBuffer getOutputString() { + return outputString; + } + + public void setOutputString(StringBuffer outputString) { + this.outputString = outputString; + } + + public Map getPayload() { + return payload; + } + + public void setPayloadFromResponse(JsonNode node) { + Map nodePayload = new HashMap<>(); + JsonNode entityNode = node.get("entity"); + if (suggestableAttr != null) { + for (String attribute : suggestableAttr) { + if (entityNode.get(attribute) != null && !entityNode.get(attribute).asText().trim().isEmpty()) { + nodePayload.put(attribute, entityNode.get(attribute).asText()); + this.statusPermutations.add(entityNode.get(attribute).asText()); + } + } + this.setPayload(nodePayload); + } + } + + public void setPayload(Map payload) { + this.payload = payload; + } + + public JSONObject getPayloadJsonNode() { + return payloadJsonNode; + } + + public void setPayloadJsonNode(JSONObject payloadJsonNode) { + this.payloadJsonNode = payloadJsonNode; + } + + public List getStatusPermutations() { + return statusPermutations; + } + + public List getSuggestableAttr() { + return suggestableAttr; + } + + public List getSuggestionInputPermutations() { + return this.suggestionInputPermutations; + } + + public void setStatusPermutations(List statusPermutations) { + this.statusPermutations = statusPermutations; + } + + public void setSuggestableAttr(ArrayList attributes) { + for (String attribute : attributes) { + this.suggestableAttr.add(attribute); + } + } + + public void setSuggestionInputPermutations(List permutations) { + this.suggestionInputPermutations = permutations; + } + + @Override + public String toString() { + return "SuggestionSearchEntity [id=" + id + ", entityType=" + entityType + + ", entityTypeAliases=" + entityTypeAliases + ", suggestionInputPermutations=" + + suggestionInputPermutations + ", statusPermutations=" + statusPermutations + + ", suggestableAttr=" + suggestableAttr + ", payload=" + payload + ", payloadJsonNode=" + + payloadJsonNode + ", outputString=" + outputString + "]"; + } +} diff --git a/src/main/java/org/openecomp/datarouter/entity/TopographicalEntity.java b/src/main/java/org/openecomp/datarouter/entity/TopographicalEntity.java new file mode 100644 index 0000000..79cdfcd --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/entity/TopographicalEntity.java @@ -0,0 +1,191 @@ +/** + * ============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.entity; + +import java.io.IOException; +import java.io.Serializable; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.List; + +import javax.json.Json; +import javax.json.JsonObject; + +public class TopographicalEntity implements DocumentStoreDataEntity, Serializable { + + private static final long serialVersionUID = -5188479658230319058L; + + protected String entityType; + protected String entityPrimaryKeyValue; + protected String entityPrimaryKeyName; + protected String latitude; + protected String longitude; + protected String selfLink; + + // generated, SHA-256 digest + protected String id; + + private static String convertBytesToHexString(byte[] bytesToConvert) { + StringBuffer hexString = new StringBuffer(); + for (int i = 0; i < bytesToConvert.length; i++) { + hexString.append(Integer.toHexString(0xFF & bytesToConvert[i])); + } + return hexString.toString(); + } + + private static String concatArray(List list, char delimiter) { + + if (list == null || list.size() == 0) { + return ""; + } + + StringBuilder result = new StringBuilder(64); + + int listSize = list.size(); + boolean firstValue = true; + + for (String item : list) { + + if (firstValue) { + result.append(item); + firstValue = false; + } else { + result.append(delimiter).append(item); + } + } + + return result.toString(); + } + + /* + * We'll try and create a unique identity key that we can use for + * differencing the previously imported record sets as we won't have granular + * control of what is created/removed and when. The best we can hope for is + * identification of resources by generated Id until the Identity-Service + * UUID is tagged against all resources, then we can use that instead. + */ + public static String generateUniqueShaDigest(String entityType, String fieldName, + String fieldValue) throws NoSuchAlgorithmException { + + /* + * Basically SHA-256 will result in an identity with a guaranteed + * uniqueness compared to just a java hashcode value. + */ + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + digest.update(String.format("%s.%s.%s", entityType, fieldName, fieldValue).getBytes()); + return convertBytesToHexString(digest.digest()); + } + + public TopographicalEntity() {} + + /* + * (non-Javadoc) + * + * @see org.openecomp.datarouter.entity.TopographicalEntity#getAsJson() + */ + public String getAsJson() throws IOException { + + JsonObject obj = + Json.createObjectBuilder().add("entityType", entityType) + .add("pkey", entityPrimaryKeyValue) + .add("location", Json.createObjectBuilder() + .add("lat", latitude) + .add("lon", longitude)) + .add("selfLink", selfLink).build(); + + return obj.toString(); + } + + + @Override + public String toString() { + return "TopographicalEntity [" + ("entityType=" + entityType + ", ") + + ("entityPrimaryKeyValue=" + entityPrimaryKeyValue + ", ") + + ("latitude=" + latitude + ", ") + ("longitude=" + longitude + ", ") + + ("ID=" + id + ", ") + + ("selfLink=" + selfLink) + "]"; + } + + @Override + public String getId() { + return this.id; + } + + public String getEntityType() { + return entityType; + } + + public void setEntityType(String entityType) { + this.entityType = entityType; + } + + public String getEntityPrimaryKeyValue() { + return entityPrimaryKeyValue; + } + + public void setEntityPrimaryKeyValue(String entityPrimaryKeyValue) { + this.entityPrimaryKeyValue = entityPrimaryKeyValue; + } + + public String getEntityPrimaryKeyName() { + return entityPrimaryKeyName; + } + + public void setEntityPrimaryKeyName(String entityPrimaryKeyName) { + this.entityPrimaryKeyName = entityPrimaryKeyName; + } + + public String getLatitude() { + return latitude; + } + + public void setLatitude(String latitude) { + this.latitude = latitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; + } + + public String getSelfLink() { + return selfLink; + } + + public void setSelfLink(String selfLink) { + this.selfLink = selfLink; + } + + public static long getSerialversionuid() { + return serialVersionUID; + } + + public void setId(String id) { + this.id = id; + } +} diff --git a/src/main/java/org/openecomp/datarouter/entity/UebEventHeader.java b/src/main/java/org/openecomp/datarouter/entity/UebEventHeader.java new file mode 100644 index 0000000..5eab97f --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/entity/UebEventHeader.java @@ -0,0 +1,169 @@ +/** + * ============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.entity; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A convenience POJO for mapping the UebEventHeader from a UEB Event. + * + * @author davea + */ + +@JsonIgnoreProperties(ignoreUnknown = true) +public class UebEventHeader { + + private String timestamp; + + private String id; + + private String action; + + private String domain; + + private String sourceName; + + private String entityLink; + + private String entityType; + + private String topEntityType; + + private String sequenceNumber; + + private String eventType; + + private String version; + + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + public String getSourceName() { + return sourceName; + } + + @JsonProperty("source-name") + public void setSourceName(String sourceName) { + this.sourceName = sourceName; + } + + public String getEntityLink() { + return entityLink; + } + + @JsonProperty("entity-link") + public void setEntityLink(String entityLink) { + this.entityLink = entityLink; + } + + public String getEntityType() { + return entityType; + } + + @JsonProperty("entity-type") + public void setEntityType(String entityType) { + this.entityType = entityType; + } + + public String getTopEntityType() { + return topEntityType; + } + + @JsonProperty("top-entity-type") + public void setTopEntityType(String topEntityType) { + this.topEntityType = topEntityType; + } + + public String getSequenceNumber() { + return sequenceNumber; + } + + @JsonProperty("sequence-number") + public void setSequenceNumber(String sequenceNumber) { + this.sequenceNumber = sequenceNumber; + } + + public String getEventType() { + return eventType; + } + + @JsonProperty("event-type") + public void setEventType(String eventType) { + this.eventType = eventType; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + @Override + public String toString() { + return "UebEventHeader [" + (timestamp != null ? "timestamp=" + timestamp + ", " : "") + + (id != null ? "id=" + id + ", " : "") + (action != null ? "action=" + action + ", " : "") + + (domain != null ? "domain=" + domain + ", " : "") + + (sourceName != null ? "sourceName=" + sourceName + ", " : "") + + (entityLink != null ? "entityLink=" + entityLink + ", " : "") + + (entityType != null ? "entityType=" + entityType + ", " : "") + + (topEntityType != null ? "topEntityType=" + topEntityType + ", " : "") + + (sequenceNumber != null ? "sequenceNumber=" + sequenceNumber + ", " : "") + + (eventType != null ? "eventType=" + eventType + ", " : "") + + (version != null ? "version=" + version : "") + "]"; + } + +} diff --git a/src/main/java/org/openecomp/datarouter/exception/BaseDataRouterException.java b/src/main/java/org/openecomp/datarouter/exception/BaseDataRouterException.java new file mode 100644 index 0000000..0cd0381 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/exception/BaseDataRouterException.java @@ -0,0 +1,89 @@ +/** + * ============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.exception; + +/* + * COPYRIGHT NOTICE: Copyright (c) 2016 Team Pacifica (Amdocs & AT&T) The contents and intellectual + * property contained herein, remain the property of Team Pacifica (Amdocs & AT&T). + */ + +import java.util.Locale; + +/** + * Base SMAdaptor exception class. + */ +public class BaseDataRouterException extends Exception { + + /** Force serialVersionUID. */ + private static final long serialVersionUID = -6663403070792969748L; + + /** Default locale. */ + public static final Locale LOCALE = Locale.US; + + /** Exception id. */ + private final String id; + + /** + * Constructor. + * + * @param id the incoming id. + */ + public BaseDataRouterException(final String id) { + super(); + this.id = id; + } + + /** + * Constructor. + * + * @param id the incoming id + * @param message the incoming message + */ + public BaseDataRouterException(final String id, final String message) { + super(message); + this.id = id; + } + + /** + * Constructor. + * + * @param id the incoming id + * @param message the incoming message + * @param cause the incoming throwable + */ + public BaseDataRouterException(final String id, final String message, final Throwable cause) { + super(message, cause); + this.id = id; + } + + /** + * Get the exception id. + * + * @return the exception id + */ + public String getId() { + return this.id; + } +} diff --git a/src/main/java/org/openecomp/datarouter/exception/DataRouterError.java b/src/main/java/org/openecomp/datarouter/exception/DataRouterError.java new file mode 100644 index 0000000..4920591 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/exception/DataRouterError.java @@ -0,0 +1,106 @@ +/** + * ============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.exception; + +/* + * COPYRIGHT NOTICE: Copyright (c) 2016 Team Pacifica (Amdocs & AT&T) The contents and intellectual + * property contained herein, remain the property of Team Pacifica (Amdocs & AT&T). + */ + +import java.text.MessageFormat; + +import javax.ws.rs.core.Response.Status; + +/** + * DL enum for error conditions. + */ +public enum DataRouterError { + + /** Parsing exceptions - Range 100..199. */ + DL_PARSE_100("DL-100", "Unable to find resource {0} in the model", Status.BAD_REQUEST), + DL_PARSE_101("DL-101", "Unable to parse ", Status.BAD_REQUEST), + DL_PARSE_102("DL-102", "Sot Filter error: {0} ", Status.INTERNAL_SERVER_ERROR), + DL_PARSE_103("DL-103", "URL Parsing error: {0} ", Status.BAD_REQUEST), + DL_PARSE_104("DL-104", "Missing Ids filter: {0} ", Status.BAD_REQUEST), + DL_PARSE_105("DL-105", "Invalid Ids filter: {0} ", Status.BAD_REQUEST), + + /** Validation exceptions - Range 200..299. */ + DL_VALIDATION_200("DL-200", "Missing X-TransactionId in header ", Status.BAD_REQUEST), + + /** Other components integration errors - Range 300..399. */ + DL_INTEGRATION_300("DL-300", "Unable to decorate Graph ", Status.INTERNAL_SERVER_ERROR), + + /** Environment related exceptions - Range 400..499. */ + DL_ENV_400("DL-400", "Unable to find file {0} ", Status.INTERNAL_SERVER_ERROR), + DL_ENV_401("DL-401", "Unable to Load OXM Models", Status.INTERNAL_SERVER_ERROR), + + /** Other components integration errors - Range 500..599. */ + DL_AUTH_500("DL-500", "Unable to authorize User ", Status.FORBIDDEN); + + /** The error id. */ + private String id; + /** The error message. */ + private String message; + /** The error http return code. */ + private Status status; + + /** + * Constructor. + * + * @param id the error id + * @param message the error message + */ + DataRouterError(final String id, final String message, final Status status) { + this.id = id; + this.message = message; + this.status = status; + } + + /** + * Get the id. + * + * @return the error id + */ + public String getId() { + return this.id; + } + + /** + * Get the message. + * + * @param args the error arguments + * @return the error message + */ + public String getMessage(final Object... args) { + final MessageFormat formatter = new MessageFormat(""); + formatter.applyPattern(this.message); + return formatter.format(args); + } + + public Status getHttpStatus() { + return this.status; + } + +} diff --git a/src/main/java/org/openecomp/datarouter/logging/DataRouterMsgs.java b/src/main/java/org/openecomp/datarouter/logging/DataRouterMsgs.java new file mode 100644 index 0000000..8304c96 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/logging/DataRouterMsgs.java @@ -0,0 +1,161 @@ +/** + * ============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.logging; + +import com.att.eelf.i18n.EELFResourceManager; + +import org.openecomp.cl.eelf.LogMessageEnum; + +public enum DataRouterMsgs implements LogMessageEnum { + + /** Data Layer Service started. */ + SERVICE_STARTED, + + /** + * Data Layer Service failed to start. + * Arguments: {0} = Exception message. + */ + STARTUP_FAILURE, + + /** + * File has been changed. + * Arguments: {0} = File name. + */ + FILE_CHANGED, + + /** + * File has been reloaded. + * Arguments: {0} = File name. + */ + FILE_RELOADED, + + /** + * Reports the configuration watcher interval. + * Arguments: {0} = Interval + */ + REPORT_CONFIG_WATCHER_INT, + + /** + * Loading properties file. + * Arguments: {0} = File name. + */ + LOADING_PROPERTIES, + + /** + * Properties file has been loaded. + * Arguments: {0} = File name. + */ + PROPERTIES_LOADED, + + /** + * UEB no events received. + * Arguments: {0} = Topic name + */ + UEB_NO_EVENTS_RECEIVED, + + /** + * Routing policies are being configured. + */ + CONFIGURING_ROUTING_POLICIES, + + /** + * A properties file could not be successfully loaded. + * Arguments: {0} = File name. + */ + LOAD_PROPERTIES_FAILURE, + + /** + * Failed to register for an event topic with UEB. + * Arguments: {0} = Topic {1} = Error reason + */ + UEB_CONNECT_ERR, + + /** + * An error occurred while trying to route a query. + * Arguments: {0} = Query {1} = Error reason + */ + QUERY_ROUTING_ERR, + + /** + * Error in file monitor block. + */ + FILE_MON_BLOCK_ERR, + + /** + * Failure to create a property map. + */ + CREATE_PROPERTY_MAP_ERR, + + /** + * An error occurred reading from a file stream. + */ + FILE_STREAM_ERR, + + /** + * An error occurred while trying to configure a routing policy. + * Arguments: {0} = policy name {1} = source of the routing policy {2} = action of the routing + * policy + */ + ROUTING_POLICY_CONFIGURATION_ERROR, + + /** + * Received request {0} {1} from {2}. Sending response: {3} + * Arguments: {0} = operation {1} = target URL {2} = source {3} = response code + */ + PROCESS_REST_REQUEST, + + /** + * Processed event {0}. Result: {1} + * Arguments: {0} = event topic {1} = result + */ + PROCESS_EVENT, + + /** + * Arguments: {0} = Error + */ + + BAD_REST_REQUEST, + + /** + * Arguments: {0} = Search index URL {1} = Reason + */ + FAIL_TO_CREATE_SEARCH_INDEX, + + /** + * Arguments: {0} = Successfully created index at endpoint + */ + SEARCH_INDEX_CREATE_SUCCESS, + + INVALID_OXM_FILE, + + INVALID_OXM_DIR; + + /** + * Static initializer to ensure the resource bundles for this class are loaded... + */ + static { + EELFResourceManager.loadMessageBundle("logging/DataRouterMsgs"); + } +} diff --git a/src/main/java/org/openecomp/datarouter/logging/EntityEventPolicyMsgs.java b/src/main/java/org/openecomp/datarouter/logging/EntityEventPolicyMsgs.java new file mode 100644 index 0000000..09be3a0 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/logging/EntityEventPolicyMsgs.java @@ -0,0 +1,218 @@ +/** + * ============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.logging; + +import com.att.eelf.i18n.EELFResourceManager; + +import org.openecomp.cl.eelf.LogMessageEnum; + +public enum EntityEventPolicyMsgs implements LogMessageEnum { + + // Error Messages + /** + * Discarding event. + * Arguments: + * {0} = reason + * {1} = Payload: + */ + DISCARD_AAI_EVENT_VERBOSE, + + /** + * Discarding event. + * Arguments: + * {0} = Reason + */ + DISCARD_AAI_EVENT_NONVERBOSE, + + /** + * OXM version: {0} is not supported. + * Arguments: + * {0} = OXM Version + */ + OXM_VERSION_NOT_SUPPORTED, + + /** + * Failed to parse UEB payload. + * Arguments: + * {0} + * {1} + */ + FAILED_TO_PARSE_UEB_PAYLOAD, + + /** + * Unable to retrieve etag at {0} for entity with id {1} + * Arguments: + * {0} = Resource endpoint. + * {1} = Entity id. + */ + NO_ETAG_AVAILABLE_FAILURE, + + /** + * Failed to update entity {0} with operation {1}. + * Arguments: + * {0} = Entity + * {1} = Operation + */ + FAILED_TO_UPDATE_ENTITY_IN_DOCSTORE, + + + /** + * Action: {0} is not supported. + * Argument: + * {0} = Operation + */ + ENTITY_OPERATION_NOT_SUPPORTED, + + /** + * Arguments: + * {0} = reason + */ + DISCARD_UPDATING_SEARCH_SUGGESTION_DATA, + + /** + * Discarding topographical data. Reason: {0}. Payload: {1} + * Arguments: + * {0} = Reason for discarding data. + * {1} = Payload + */ + DISCARD_UPDATING_TOPOGRAPHY_DATA_VERBOSE, + + /** + * Discarding topographical data. Reason: {0} + * Arguments: + * {0} = Reason for discarding data. + */ + DISCARD_UPDATING_TOPOGRAPHY_DATA_NONVERBOSE, + + /** + * Failed to load OXM Model. + */ + PROCESS_OXM_MODEL_MISSING, + + /** + * Failed to create Search index {0} due to: {1} + * + * Arguments: + * {0} = Search index + * {1} = Error cause + */ + FAIL_TO_CREATE_SEARCH_INDEX, + + /** + * Failed to find OXM version in UEB payload. {0} + * Arguments: + * {0} = OXM version. + */ + FAILED_TO_FIND_OXM_VERSION, + + + // Info Messages + + /** + * Processing AAI Entity Event Policy: + * Arguments: + * {0} = Action + * {1} = Entity Type + * {2} = Payload + */ + PROCESS_AAI_ENTITY_EVENT_POLICY_VERBOSE, + + /** + * Processing AAI Entity Event Policy: + * Arguments: + * {0} = Action + * {1} = Entity Type + */ + PROCESS_AAI_ENTITY_EVENT_POLICY_NONVERBOSE, + + /** + * Cross Entity Reference synchronization {0} + * Arguments: + * {0} = Error string + * + */ + CROSS_ENTITY_REFERENCE_SYNC, + + /** + * Operation {0} completed in {1} ms with no errors + * Arguments: + * {0} = Operation type + * {1} = Time in ms. + */ + OPERATION_RESULT_NO_ERRORS, + + /** + * Found OXM model: {0} + * Arguments: + * {0} = Key pair. + */ + PROCESS_OXM_MODEL_FOUND, + + /** + * Successfully created index at {0} + * + * Arguments: + * {0} = Index resource endpoint + */ + SEARCH_INDEX_CREATE_SUCCESS, + + /** + * Entity Event Policy component started. + */ + ENTITY_EVENT_POLICY_REGISTERED, + + /** + * Arguments: + * {0} = Entity name + */ + PRIMARY_KEY_NULL_FOR_ENTITY_TYPE, + + /** + * Arguments: {0} = UEB payload + */ + UEB_INVALID_PAYLOAD_JSON_FORMAT, + + /** + * Arguments: {0} = Event header + */ + UEB_FAILED_TO_PARSE_PAYLOAD, + + /** + * Arguments: {0} = Exception + */ + UEB_FAILED_UEBEVENTHEADER_CONVERSION, + + /** + * Arguments: {0} = UEB event header + */ + UEB_EVENT_HEADER_PARSED; + + /** + * Static initializer to ensure the resource bundles for this class are loaded... + */ + static { + EELFResourceManager.loadMessageBundle("logging/EntityEventPolicyMsgs"); + } +} 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 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 SUPPORTED_ACTIONS = + Arrays.asList(ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE); + + Map 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(); + 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 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 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 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 foundNodes = new ArrayList(); + + RouterServiceUtil.extractObjectsByKey(entityJsonNode, key, foundNodes); + + if (foundNodes.size() > 0) { + + for (JsonNode n : foundNodes) { + + List extractedParentEntityAttributeValues = new ArrayList(); + + RouterServiceUtil.extractFieldValuesFromObject(n, cerDescriptor.getAttributeNames(), + extractedParentEntityAttributeValues); + + List nestedTargetEntityInstances = new ArrayList(); + 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 rootDescriptor = + oxmEntities.getSuggestableEntityDescriptors(); + if (!rootDescriptor.isEmpty()) { + List suggestibleAttributes = extractSuggestableAttr(oxmEntities, entityType); + + if (suggestibleAttributes == null) { + return; + } + + List 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> 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) { + 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 extractSuggestableAttr(VersionedOxmEntities oxmEntities, String entityType) { + // Extract suggestable attributes + Map rootDescriptor = oxmEntities.getSuggestableEntityDescriptors(); + + if (rootDescriptor == null) { + return null; + } + + OxmEntityDescriptor desc = rootDescriptor.get(entityType); + + if (desc == null) { + return null; + } + + return desc.getSuggestableAttributes(); + } + + public List extractAliasForSuggestableEntity(VersionedOxmEntities oxmEntities, + String entityType) { + + // Extract alias + Map 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 suggestableAttr, List alias) { + + // Extract suggestable attributes + Map 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 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 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 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 fieldValues = null; + Map properties = entity.getDescriptor().getProperties(); + for (Map.Entry 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 primaryKeyValues = new ArrayList(); + 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 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> 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 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> 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) { + 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(); + + // 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 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 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 topoData = new HashMap<>(); + String entityLink = ""; + List 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 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; + } +} diff --git a/src/main/java/org/openecomp/datarouter/policy/EntityEventPolicyConfig.java b/src/main/java/org/openecomp/datarouter/policy/EntityEventPolicyConfig.java new file mode 100644 index 0000000..8e14be1 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/policy/EntityEventPolicyConfig.java @@ -0,0 +1,129 @@ +/** + * ============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; + +public class EntityEventPolicyConfig { + + private String sourceDomain; + private String searchBaseUrl; + private String searchEndpoint; + private String searchEndpointDocuments; + private String searchEntitySearchIndex; + private String searchTopographySearchIndex; + private String searchEntityAutoSuggestIndex; + private String searchAggregationVnfIndex; + 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 getSearchEntitySearchIndex() { + return searchEntitySearchIndex; + } + + public void setSearchEntitySearchIndex(String searchEntitySearchIndex) { + this.searchEntitySearchIndex = searchEntitySearchIndex; + } + + public String getSearchTopographySearchIndex() { + return searchTopographySearchIndex; + } + + public void setSearchTopographySearchIndex(String searchTopographySearchIndex) { + this.searchTopographySearchIndex = searchTopographySearchIndex; + } + + public String getSearchEntityAutoSuggestIndex() { + return searchEntityAutoSuggestIndex; + } + + public void setSearchEntityAutoSuggestIndex(String autoSuggestibleSearchEntitySearchIndex) { + this.searchEntityAutoSuggestIndex = autoSuggestibleSearchEntitySearchIndex; + } + + 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; + } + +public String getSearchAggregationVnfIndex() { + return searchAggregationVnfIndex; +} + +public void setSearchAggregationVnfIndex(String searchAggregationVnfIndex) { + this.searchAggregationVnfIndex = searchAggregationVnfIndex; +} +} diff --git a/src/main/java/org/openecomp/datarouter/service/EchoService.java b/src/main/java/org/openecomp/datarouter/service/EchoService.java new file mode 100644 index 0000000..e7f6368 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/service/EchoService.java @@ -0,0 +1,97 @@ +/** + * ============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.service; + +import org.openecomp.cl.api.LogFields; +import org.openecomp.cl.api.LogLine; +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.cl.mdc.MdcContext; +import org.openecomp.datarouter.logging.DataRouterMsgs; +import org.openecomp.datarouter.util.DataRouterConstants; +import org.slf4j.MDC; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +public class EchoService { + + private static Logger logger = LoggerFactory.getInstance().getLogger(EchoService.class.getName()); + private static Logger auditLogger = + LoggerFactory.getInstance().getAuditLogger(EchoService.class.getName()); + + @GET + @Path("echo/{input}") + @Produces("text/plain") + public String ping(@PathParam("input") String input, @Context HttpHeaders headers, + @Context UriInfo info, @Context HttpServletRequest req) { + + String fromIp = req.getRemoteAddr(); + String fromAppId = ""; + String transId = null; + + if (headers.getRequestHeaders().getFirst("X-FromAppId") != null) { + fromAppId = headers.getRequestHeaders().getFirst("X-FromAppId"); + } + + if ((headers.getRequestHeaders().getFirst("X-TransactionId") == null) + || headers.getRequestHeaders().getFirst("X-TransactionId").isEmpty()) { + transId = java.util.UUID.randomUUID().toString(); + } else { + transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + } + + MdcContext.initialize(transId, DataRouterConstants.DATA_ROUTER_SERVICE_NAME, "", fromAppId, + fromIp); + + int status = 200; + String respStatusString = ""; + if (Response.Status.fromStatusCode(status) != null) { + respStatusString = Response.Status.fromStatusCode(status).toString(); + } + + // Generate error log + logger.info(DataRouterMsgs.PROCESS_REST_REQUEST, req.getMethod(), + req.getRequestURL().toString(), req.getRemoteHost(), Integer.toString(status)); + + // Generate audit log. + auditLogger.info(DataRouterMsgs.PROCESS_REST_REQUEST, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, status) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, respStatusString), + (req != null) ? req.getMethod() : "Unknown", + (req != null) ? req.getRequestURL().toString() : "Unknown", + (req != null) ? req.getRemoteHost() : "Unknown", Integer.toString(status)); + MDC.clear(); + + return "Hello, " + input + "."; + } +} diff --git a/src/main/java/org/openecomp/datarouter/util/CrossEntityReference.java b/src/main/java/org/openecomp/datarouter/util/CrossEntityReference.java new file mode 100644 index 0000000..48f3c27 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/util/CrossEntityReference.java @@ -0,0 +1,97 @@ +/** + * ============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.util; + +import java.util.ArrayList; +import java.util.List; + +/** + * Processing and entity wrapper for property transposition logic and UEB processing + * + * @author DAVEA + */ +public class CrossEntityReference { + + private String targetEntityType; + + private List attributeNames; + + public CrossEntityReference() { + this.targetEntityType = null; + this.attributeNames = new ArrayList(); + } + + public String getTargetEntityType() { + return targetEntityType; + } + + public void setTargetEntityType(String targetEntityType) { + this.targetEntityType = targetEntityType; + } + + public List getAttributeNames() { + return attributeNames; + } + + public void setAttributeNames(List attributeNames) { + this.attributeNames = attributeNames; + } + + public void addAttributeName(String attributeName) { + if (!this.attributeNames.contains(attributeName)) { + this.attributeNames.add(attributeName); + } + } + + public void initialize(String crossEntityReferenceValueFromModel) { + + if (crossEntityReferenceValueFromModel == null + || crossEntityReferenceValueFromModel.length() == 0) { + // or throw an exception due to failure to initialize + return; + } + + String[] tokens = crossEntityReferenceValueFromModel.split(","); + + if (tokens.length >= 2) { + this.targetEntityType = tokens[0]; + + for (int x = 1; x < tokens.length; x++) { + this.attributeNames.add(tokens[x]); + } + } else { + // throw a CrossEntityReferenceInitializationException?? + } + + } + + @Override + public String toString() { + return "CrossEntityReference [" + + (targetEntityType != null ? "entityType=" + targetEntityType + ", " : "") + + (attributeNames != null ? "attributeNames=" + attributeNames : "") + "]"; + } + +} diff --git a/src/main/java/org/openecomp/datarouter/util/DataRouterConstants.java b/src/main/java/org/openecomp/datarouter/util/DataRouterConstants.java new file mode 100644 index 0000000..f9f5df3 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/util/DataRouterConstants.java @@ -0,0 +1,57 @@ +/** + * ============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.util; + +public class DataRouterConstants { + public static final String DR_FILESEP = (System.getProperty("file.separator") == null) ? "/" + : System.getProperty("file.separator"); + + public static final String DR_SPECIFIC_CONFIG = System.getProperty("CONFIG_HOME") + DR_FILESEP; + + public static final String DR_BUNDLECONFIG_NAME = (System.getProperty("BUNDLECONFIG_DIR") == null) + ? "bundleconfig" : System.getProperty("BUNDLECONFIG_DIR"); + + public static final String DR_HOME_BUNDLECONFIG = (System.getProperty("AJSC_HOME") == null) + ? DR_FILESEP + "opt" + DR_FILESEP + "app" + DR_FILESEP + + "datalayer" + DR_FILESEP + DR_BUNDLECONFIG_NAME + : System.getProperty("AJSC_HOME") + DR_FILESEP + DR_BUNDLECONFIG_NAME; + + /** This is the etc directory, relative to AAI_HOME. */ + public static final String DR_HOME_ETC = DR_HOME_BUNDLECONFIG + DR_FILESEP + "etc" + DR_FILESEP; + + public static final String DR_HOME_MODEL = DR_SPECIFIC_CONFIG + "model" + DR_FILESEP; + public static final String DR_HOME_AUTH = DR_SPECIFIC_CONFIG + "auth" + DR_FILESEP; + + public static final String DR_CONFIG_FILE = DR_SPECIFIC_CONFIG + "data-router.properties"; + + public static final String DR_HOME_ETC_OXM = DR_HOME_ETC + "oxm" + DR_FILESEP; + + + // AAI Related + public static final String AAI_ECHO_SERVICE = "/util/echo"; + + // Logging related + public static final String DATA_ROUTER_SERVICE_NAME = "DataRouter"; +} diff --git a/src/main/java/org/openecomp/datarouter/util/DataRouterProperties.java b/src/main/java/org/openecomp/datarouter/util/DataRouterProperties.java new file mode 100644 index 0000000..7e18363 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/util/DataRouterProperties.java @@ -0,0 +1,53 @@ +/** + * ============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.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Properties; + +public class DataRouterProperties { + + private static Properties properties; + + static { + properties = new Properties(); + File file = new File(DataRouterConstants.DR_CONFIG_FILE); + try { + properties.load(new FileInputStream(file)); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static String get(String key) { + return properties.getProperty(key); + } + +} diff --git a/src/main/java/org/openecomp/datarouter/util/EntityOxmReferenceHelper.java b/src/main/java/org/openecomp/datarouter/util/EntityOxmReferenceHelper.java new file mode 100644 index 0000000..c9e1746 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/util/EntityOxmReferenceHelper.java @@ -0,0 +1,62 @@ +/** + * ============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.util; + +import java.util.HashMap; + +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; + +public class EntityOxmReferenceHelper implements ExternalOxmModelProcessor { + + private static EntityOxmReferenceHelper _instance = null; + + private HashMap versionedModels; + + protected EntityOxmReferenceHelper() { + this.versionedModels = new HashMap(); + } + + public static EntityOxmReferenceHelper getInstance() { + if ( _instance == null ) { + _instance = new EntityOxmReferenceHelper(); + } + + return _instance; + } + + + @Override + public void onOxmVersionChange(Version version, DynamicJAXBContext context) { + VersionedOxmEntities oxmEntities = new VersionedOxmEntities(); + oxmEntities.initialize(context); + this.versionedModels.put(version, oxmEntities); + + } + + public VersionedOxmEntities getVersionedOxmEntities(Version version){ + return this.versionedModels.get(version); + } + +} \ No newline at end of file diff --git a/src/main/java/org/openecomp/datarouter/util/ExternalOxmModelProcessor.java b/src/main/java/org/openecomp/datarouter/util/ExternalOxmModelProcessor.java new file mode 100644 index 0000000..9fcef6f --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/util/ExternalOxmModelProcessor.java @@ -0,0 +1,37 @@ +/** + * ============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.util; + +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; + +/** + * Exposes a registration and processing contract so that any load/change of an oxm version will + * inform registered model processors. + * + * @author davea + */ +public interface ExternalOxmModelProcessor { + public void onOxmVersionChange(Version version, DynamicJAXBContext context); +} diff --git a/src/main/java/org/openecomp/datarouter/util/FileWatcher.java b/src/main/java/org/openecomp/datarouter/util/FileWatcher.java new file mode 100644 index 0000000..e382c21 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/util/FileWatcher.java @@ -0,0 +1,49 @@ +/** + * ============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.util; + +import java.io.File; +import java.util.TimerTask; + +public abstract class FileWatcher extends TimerTask { + private long timeStamp; + private File file; + + public FileWatcher(File file) { + this.file = file; + this.timeStamp = file.lastModified(); + } + + public final void run() { + long timeStamp = file.lastModified(); + + if ((timeStamp - this.timeStamp) > 500) { + this.timeStamp = timeStamp; + onChange(file); + } + } + + protected abstract void onChange(File file); +} \ No newline at end of file diff --git a/src/main/java/org/openecomp/datarouter/util/NodeUtils.java b/src/main/java/org/openecomp/datarouter/util/NodeUtils.java new file mode 100644 index 0000000..f957247 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/util/NodeUtils.java @@ -0,0 +1,46 @@ +/** + * ============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.util; + +import java.util.Arrays; + +public class NodeUtils { + /** + * Generate unique sha digest. This method is copy over from NodeUtils class in AAIUI + * + * @param keys the keys + * @return the string + */ + public static String generateUniqueShaDigest(String... keys) { + if ((keys == null) || keys.length == 0) { + return null; + } + + final String keysStr = Arrays.asList(keys).toString(); + final String hashedId = org.apache.commons.codec.digest.DigestUtils.sha256Hex(keysStr); + + return hashedId; + } +} diff --git a/src/main/java/org/openecomp/datarouter/util/OxmModelLoader.java b/src/main/java/org/openecomp/datarouter/util/OxmModelLoader.java new file mode 100644 index 0000000..2919ba2 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/util/OxmModelLoader.java @@ -0,0 +1,166 @@ +/** + * ============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.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.ws.rs.core.Response.Status; +import javax.xml.bind.JAXBException; + +import org.eclipse.persistence.jaxb.JAXBContextProperties; +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.datarouter.logging.DataRouterMsgs; + +import org.openecomp.datarouter.util.ExternalOxmModelProcessor; + +public class OxmModelLoader { + + private static Map versionContextMap = new ConcurrentHashMap(); + private static Map timers = new ConcurrentHashMap(); + private static List oxmModelProcessorRegistry = new ArrayList(); + final static Pattern p = Pattern.compile("aai_oxm_(.*).xml"); + + + + private static org.openecomp.cl.api.Logger logger = LoggerFactory.getInstance() + .getLogger(OxmModelLoader.class.getName()); + + public synchronized static void loadModels() { + + File[] listOfFiles = new File(DataRouterConstants.DR_HOME_MODEL).listFiles(); + + if (listOfFiles != null) { + for (File file : listOfFiles) { + if (file.isFile()) { + Matcher m = p.matcher(file.getName()); + if (m.matches()) { + try { + OxmModelLoader.loadModel(m.group(1), file); + } catch (Exception e) { + logger.error(DataRouterMsgs.INVALID_OXM_FILE, file.getName(), e.getMessage()); + } + } + + } + } + } else { + logger.error(DataRouterMsgs.INVALID_OXM_DIR, DataRouterConstants.DR_HOME_MODEL); + } + + + } + + private static void addtimer(String version,File file){ + TimerTask task = null; + task = new FileWatcher( + file) { + protected void onChange(File file) { + // here we implement the onChange + logger.info(DataRouterMsgs.FILE_CHANGED, file.getName()); + + try { + OxmModelLoader.loadModel(version,file); + } catch (Exception e) { + e.printStackTrace(); + } + + } + }; + + if (!timers.containsKey(version)) { + Timer timer = new Timer("oxm-"+version); + timer.schedule(task, new Date(), 10000); + timers.put(version, timer); + + } + } + + private synchronized static void loadModel(String version,File file) throws JAXBException, FileNotFoundException { + + + InputStream iStream = new FileInputStream(file); + Map properties = new HashMap(); + properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, iStream); + final DynamicJAXBContext jaxbContext = DynamicJAXBContextFactory + .createContextFromOXM(Thread.currentThread().getContextClassLoader(), properties); + versionContextMap.put(version, jaxbContext); + if ( oxmModelProcessorRegistry != null) { + for ( ExternalOxmModelProcessor processor : oxmModelProcessorRegistry ) { + processor.onOxmVersionChange(Version.valueOf(version), jaxbContext ); + } + } + addtimer(version,file); + + } + + public static DynamicJAXBContext getContextForVersion(String version) throws Exception { + if (versionContextMap == null || versionContextMap.isEmpty()) { + loadModels(); + } else if (!versionContextMap.containsKey(version)) { + try { + loadModel(version,new File (DataRouterConstants.DR_HOME_MODEL + "aai_oxm_" + version + ".xml")); + } catch (Exception e) { + throw new Exception(Status.NOT_FOUND.toString()); + } + } + + return versionContextMap.get(version); + } + + public static Map getVersionContextMap() { + return versionContextMap; + } + + public static void setVersionContextMap(Map versionContextMap) { + OxmModelLoader.versionContextMap = versionContextMap; + } + + public synchronized static void registerExternalOxmModelProcessors(Collection processors) { + if(processors != null) { + for(ExternalOxmModelProcessor processor : processors) { + if(!oxmModelProcessorRegistry.contains(processor)) { + oxmModelProcessorRegistry.add(processor); + } + } + } + } + +} diff --git a/src/main/java/org/openecomp/datarouter/util/RouterServiceUtil.java b/src/main/java/org/openecomp/datarouter/util/RouterServiceUtil.java new file mode 100644 index 0000000..b30c9f9 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/util/RouterServiceUtil.java @@ -0,0 +1,226 @@ +/** + * ============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.util; + +import com.fasterxml.jackson.databind.JsonNode; + +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class RouterServiceUtil { + + public static Map parseJsonPayloadIntoMap(String jsonPayload) { + + JSONObject jsonObject = new JSONObject(jsonPayload); + Map map = new HashMap(); + Iterator iter = jsonObject.keys(); + while (iter.hasNext()) { + String key = (String) iter.next(); + String value = jsonObject.getString(key); + map.put(key, value); + } + return map; + } + + public static String getNodeFieldAsText(JsonNode node, String fieldName) { + + String fieldValue = null; + + JsonNode valueNode = node.get(fieldName); + + if (valueNode != null) { + fieldValue = valueNode.asText(); + } + + return fieldValue; + } + + public static String concatArray(List list) { + return concatArray(list, " "); + } + + public static String concatArray(List list, String delimiter) { + + if (list == null || list.size() == 0) { + return ""; + } + + StringBuilder result = new StringBuilder(64); + + boolean firstValue = true; + + for (String item : list) { + + if (firstValue) { + result.append(item); + firstValue = false; + } else { + result.append(delimiter).append(item); + } + } + + return result.toString(); + + } + + public static String concatArray(String[] values) { + + if (values == null || values.length == 0) { + return ""; + } + + StringBuilder result = new StringBuilder(64); + + boolean firstValue = true; + + for (String item : values) { + + if (firstValue) { + result.append(item); + firstValue = false; + } else { + result.append(".").append(item); + } + + } + + return result.toString(); + + } + + public static String recursivelyLookupJsonPayload(JsonNode node, String key) { + String value = null; + if (node.isObject()) { + Iterator> nodeIterator = node.fields(); + + while (nodeIterator.hasNext()) { + Map.Entry entry = (Map.Entry) nodeIterator.next(); + if (!entry.getValue().isValueNode()) { + value = recursivelyLookupJsonPayload(entry.getValue(), key); + if (value != null) { + return value; + } + } + + String name = entry.getKey(); + if (name.equalsIgnoreCase(key)) { + return entry.getValue().asText(); + } + } + } else if (node.isArray()) { + Iterator arrayItemsIterator = node.elements(); + while (arrayItemsIterator.hasNext()) { + value = recursivelyLookupJsonPayload(arrayItemsIterator.next(), key); + if (value != null) { + return value; + } + } + } + return value; + } + + public static void extractObjectsByKey(JsonNode node, String searchKey, + Collection foundObjects) { + + if (node.isObject()) { + Iterator> nodeIterator = node.fields(); + + while (nodeIterator.hasNext()) { + Map.Entry entry = (Map.Entry) nodeIterator.next(); + if (!entry.getValue().isValueNode()) { + extractObjectsByKey(entry.getValue(), searchKey, foundObjects); + } + + String name = entry.getKey(); + if (name.equalsIgnoreCase(searchKey)) { + + JsonNode entryValue = entry.getValue(); + + if (entryValue.isArray()) { + + Iterator arrayItemsIterator = entryValue.elements(); + while (arrayItemsIterator.hasNext()) { + foundObjects.add(arrayItemsIterator.next()); + } + + } else { + foundObjects.add(entry.getValue()); + } + } + } + } else if (node.isArray()) { + Iterator arrayItemsIterator = node.elements(); + while (arrayItemsIterator.hasNext()) { + extractObjectsByKey(arrayItemsIterator.next(), searchKey, foundObjects); + } + } + } + + public static void convertArrayIntoList(JsonNode node, Collection instances) { + + if (node.isArray()) { + Iterator arrayItemsIterator = node.elements(); + while (arrayItemsIterator.hasNext()) { + instances.add(arrayItemsIterator.next()); + } + } else { + instances.add(node); + } + } + + public static void extractFieldValuesFromObject(JsonNode node, + Collection attributesToExtract, Collection fieldValues) { + + if (node.isObject()) { + + JsonNode valueNode = null; + + for (String attrToExtract : attributesToExtract) { + + valueNode = node.get(attrToExtract); + + if (valueNode != null) { + + if (valueNode.isValueNode()) { + fieldValues.add(valueNode.asText()); + } + } + } + } + } + + + public static String objToJson(Object obj) { + JSONObject jsonObject = new JSONObject(obj); + String json = jsonObject.toString(); + return json; + } +} diff --git a/src/main/java/org/openecomp/datarouter/util/SearchSuggestionPermutation.java b/src/main/java/org/openecomp/datarouter/util/SearchSuggestionPermutation.java new file mode 100644 index 0000000..91f5910 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/util/SearchSuggestionPermutation.java @@ -0,0 +1,89 @@ +/** + * ============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.util; + +import java.util.ArrayList; +import java.util.List; + +public class SearchSuggestionPermutation { + /* + * Will return all the unique combinations of the suggestions provided. + * The order of the permutation is not taken into account when computing + * the uniqueness. + * e.g.: A list of A,B,C,D will return + * [[A], [A, B, C, D], [A, C, D], [A, D], [B], [B, C, D], [B, D], [C], [C, D], [D]] + * + * @param list The list of statuses to create permutations of + * @return A list which contains a array list of all possible combinations + */ + @SuppressWarnings("serial") + public List> getSuggestionsPermutation(List list) { + List statusList = new ArrayList<>(list); + List dupStatusList; + ArrayList> uniqueList = new ArrayList<>(); + int mainLoopIndexCounter = 0; + + for (String status : statusList) { + // Add the single entity subset + //This will add the unique single values eg [A],[B],[C],[D] + uniqueList.add(new ArrayList() { + { + add(status); + } + }); + + // Remove all the elements to left till the current index + dupStatusList = truncateListUntill(statusList, mainLoopIndexCounter); + + while (!dupStatusList.isEmpty()) { + ArrayList suggListInIterate= new ArrayList<>(); + suggListInIterate.add(status); + + for (String dupStatus : dupStatusList) { + suggListInIterate.add(dupStatus); + } + + uniqueList.add(suggListInIterate); + dupStatusList.remove(0); + } + + mainLoopIndexCounter++; + } + + return uniqueList; + } + + private List truncateListUntill(List lists, int index) { + List truncatedList = new ArrayList<>(lists); + int counter = 0; + + while (counter <= index) { + truncatedList.remove(0); + counter++; + } + + return truncatedList; + } +} diff --git a/src/main/java/org/openecomp/datarouter/util/Version.java b/src/main/java/org/openecomp/datarouter/util/Version.java new file mode 100644 index 0000000..a0b3e5f --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/util/Version.java @@ -0,0 +1,29 @@ +/** + * ============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.util; + +public enum Version { + v2, v3, v4, v5, v6, v7, v8, v9, v10; +} \ No newline at end of file diff --git a/src/main/java/org/openecomp/datarouter/util/VersionedOxmEntities.java b/src/main/java/org/openecomp/datarouter/util/VersionedOxmEntities.java new file mode 100644 index 0000000..46c4a76 --- /dev/null +++ b/src/main/java/org/openecomp/datarouter/util/VersionedOxmEntities.java @@ -0,0 +1,352 @@ +/** + * ============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.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import org.eclipse.persistence.dynamic.DynamicType; +import org.eclipse.persistence.internal.helper.DatabaseField; +import org.eclipse.persistence.internal.oxm.XPathFragment; +import org.eclipse.persistence.internal.oxm.mappings.Descriptor; +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; +import org.eclipse.persistence.mappings.DatabaseMapping; +import org.eclipse.persistence.oxm.XMLField; +import org.openecomp.datarouter.entity.OxmEntityDescriptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Builds up a representation of the versioned entities in a way that they can be cross referenced + * in a data-driven way + * @author DAVEA + */ +public class VersionedOxmEntities { + + private static final Logger logger = LoggerFactory.getLogger(VersionedOxmEntities.class); + private static final String REST_ROOT_ENTITY = "inventory"; + + private HashMap crossEntityReferenceContainerLookup = new HashMap(); + private HashMap crossEntityReferenceLookup = new HashMap(); + private Map entityTypeLookup = new LinkedHashMap(); + private Map searchableEntityDescriptors = new HashMap(); + private Map suggestableEntityDescriptors = new HashMap(); + private Map entityAliasDescriptors = new HashMap(); + + + public void initialize(DynamicJAXBContext context) { + parseOxmContext(context); + buildCrossEntityReferenceCollections(REST_ROOT_ENTITY, new HashSet()); + populateSearchableDescriptors(context); + } + + /** + * The big goal for these methods is to make the processing as generic and model driven as possible. There are only two + * exceptions to this rule, at the moment. I needed to hard-coded the top level REST data model entity type, which is + * "inventory" for now. And as this class is heavily focused and coupled towards building a version specific set of + * lookup structures for the "crossEntityReference" model attribute, it possesses knowledge of that attribute whether it + * exists or not in the DynamicJAXBContext we are currently analyzing. + * + * This method will build two collections: + * + * 1) A list of entity types that can have nested entities containing cross entity reference definitions. The purpose + * of this collection is a fail-fast test when processing UEB events so we can quickly determine if it is necessary + * to deeply parse the event looking for cross entity reference attributes which not exist. + * + * For example, looking at a service-instance <=> inventory path: + * + * inventory (true) + * -> business (true) + * -> customers (true) + * -> customer (true) + * -> service-subscriptions (true) + * -> service-subscription (CER defined here in the model) (true) + * -> service-instances (false) + * -> service-instance (false) + * + * Because service-subscription contains a model definition of CER, in the first collection all the types in the tree will + * indicate that it possesses one or more contained entity types with a cross-entity-reference definition. + * + * 2) A lookup for { entityType => CrossEntityReference } so we can quickly access the model definition of a CER for + * a specific entity type when we begin extracting parent attributes for transposition into nested child entity types. + * + * + * @param entityType + * @param checked + * @return + */ + protected boolean buildCrossEntityReferenceCollections(String entityType, HashSet checked) { + + /* + * To short-circuit infinite loops, make sure this entityType hasn't + * already been checked + */ + + if(checked.contains(entityType)) { + return false; + } + else { + checked.add(entityType); + } + + DynamicType parentType = entityTypeLookup.get(entityType); + DynamicType childType = null; + boolean returnValue = false; + + if(parentType == null) { + return returnValue; + } + + /* + * Check if current descriptor contains the cross-entity-reference + * attribute. If it does not walk the entity model looking for nested + * entity types that may contain the reference. + */ + + Map properties = parentType.getDescriptor().getProperties(); + if(properties != null) { + for(Map.Entry entry : properties.entrySet()) { + if(entry.getKey().equalsIgnoreCase("crossEntityReference")) { + returnValue = true; + CrossEntityReference cer = new CrossEntityReference(); + cer.initialize(entry.getValue()); + crossEntityReferenceLookup.put( entityType, cer); + //System.out.println("entityType = " + entityType + " contains a CER instance = " + returnValue); + // return true; + } + } + } + + Vector fields = parentType.getDescriptor().getAllFields(); + + if(fields != null) { + + XMLField xmlField = null; + for(DatabaseField f : fields) { + + if(f instanceof XMLField) { + xmlField = (XMLField)f; + XPathFragment xpathFragment = xmlField.getXPathFragment(); + String entityShortName = xpathFragment.getLocalName(); + + childType = entityTypeLookup.get(entityShortName); + + if(childType != null) { + + if(!checked.contains(entityShortName)) { + + if(buildCrossEntityReferenceCollections(entityShortName,checked)) { + returnValue = true; + } + + } + + checked.add(entityShortName); + + } + + } + + } + + } + + crossEntityReferenceContainerLookup.put(entityType, Boolean.valueOf(returnValue)); + return returnValue; + } + + private void populateSearchableDescriptors(DynamicJAXBContext oxmContext) { + List descriptorsList = oxmContext.getXMLContext().getDescriptors(); + OxmEntityDescriptor newOxmEntity = null; + + for (Descriptor desc: descriptorsList) { + + DynamicType entity = (DynamicType) oxmContext.getDynamicType(desc.getAlias()); + + //LinkedHashMap oxmProperties = new LinkedHashMap(); + String primaryKeyAttributeNames = null; + + //Not all fields have key attributes + if (desc.getPrimaryKeyFields() != null) { + primaryKeyAttributeNames = desc.getPrimaryKeyFields().toString().replaceAll("/text\\(\\)", "").replaceAll("\\[", "").replaceAll("\\]", ""); + } + + String entityName = desc.getDefaultRootElement(); + + Map properties = entity.getDescriptor().getProperties(); + if (properties != null) { + for (Map.Entry entry : properties.entrySet()) { + if (entry.getKey().equalsIgnoreCase("searchable")) { + + /* + * we can do all the work here, we don't have a create additional collections for + * subsequent passes + */ + newOxmEntity = new OxmEntityDescriptor(); + newOxmEntity.setEntityName(entityName); + newOxmEntity.setPrimaryKeyAttributeName(Arrays.asList(primaryKeyAttributeNames.split(","))); + newOxmEntity.setSearchableAttributes(Arrays.asList(entry.getValue().split(","))); + searchableEntityDescriptors.put(entityName, newOxmEntity); + } else if (entry.getKey().equalsIgnoreCase("containsSuggestibleProps")) { + newOxmEntity = new OxmEntityDescriptor(); + newOxmEntity.setEntityName(entityName); + newOxmEntity.setSuggestableEntity(true); + Vector descriptorMaps = entity.getDescriptor().getMappings(); + List listOfSuggestableAttributes = new ArrayList(); + + for (DatabaseMapping descMap : descriptorMaps) { + if (descMap.isAbstractDirectMapping()) { + + if (descMap.getProperties().get("suggestibleOnSearch") != null) { + String suggestableOnSearchString = String.valueOf( + descMap.getProperties().get("suggestibleOnSearch")); + + boolean isSuggestibleOnSearch = Boolean.valueOf(suggestableOnSearchString); + + if (isSuggestibleOnSearch) { + /* Grab attribute types for suggestion */ + String attributeName = descMap.getField().getName() + .replaceAll("/text\\(\\)", ""); + listOfSuggestableAttributes.add(attributeName); + } + } + } + } + newOxmEntity.setSuggestableAttributes(listOfSuggestableAttributes); + suggestableEntityDescriptors.put(entityName, newOxmEntity); + } else if (entry.getKey().equalsIgnoreCase("suggestionAliases")) { + newOxmEntity = new OxmEntityDescriptor(); + newOxmEntity.setEntityName(entityName); + newOxmEntity.setAlias(Arrays.asList(entry.getValue().split(","))); + entityAliasDescriptors.put(entityName, newOxmEntity); + } + } + } + + } + + } + + public Map getSearchableEntityDescriptors() { + return searchableEntityDescriptors; + } + + public OxmEntityDescriptor getSearchableEntityDescriptor(String entityType) { + return searchableEntityDescriptors.get(entityType); + } + + + public HashMap getCrossEntityReferenceContainers() { + return crossEntityReferenceContainerLookup; + } + + public HashMap getCrossEntityReferences() { + return crossEntityReferenceLookup; + } + + + private void parseOxmContext(DynamicJAXBContext oxmContext) { + List descriptorsList = oxmContext.getXMLContext().getDescriptors(); + + for(Descriptor desc : descriptorsList) { + + DynamicType entity = (DynamicType)oxmContext.getDynamicType(desc.getAlias()); + + String entityName = desc.getDefaultRootElement(); + + entityTypeLookup.put(entityName, entity); + + } + + } + + public boolean entityModelContainsCrossEntityReference(String containerEntityType) { + Boolean v = crossEntityReferenceContainerLookup.get(containerEntityType); + + if(v == null) { + return false; + } + + return v; + } + + public boolean entityContainsCrossEntityReference(String entityType) { + return (crossEntityReferenceLookup.get(entityType) != null); + } + + public CrossEntityReference getCrossEntityReference(String entityType) { + return crossEntityReferenceLookup.get(entityType); + } + + public Map getSuggestableEntityDescriptors() { + return suggestableEntityDescriptors; + } + + public void setSuggestableEntityDescriptors( + Map suggestableEntityDescriptors) { + this.suggestableEntityDescriptors = suggestableEntityDescriptors; + } + + public Map getEntityAliasDescriptors() { + return entityAliasDescriptors; + } + + public void setEntityAliasDescriptors(Map entityAliasDescriptors) { + this.entityAliasDescriptors = entityAliasDescriptors; + } + + public void extractEntities(String entityType, DynamicJAXBContext context, Collection entities) { + + + + + } + + public String dumpCrossEntityReferenceContainers() { + + Set keys = crossEntityReferenceContainerLookup.keySet(); + StringBuilder sb = new StringBuilder(128); + + for ( String key : keys ) { + + if ( crossEntityReferenceContainerLookup.get(key) ) { + sb.append("\n").append("Entity-Type = '" + key + "' contains a Cross-Entity-Reference."); + } + } + + + return sb.toString(); + + } + +} \ No newline at end of file -- cgit 1.2.3-korg