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/util/VersionedOxmEntities.java | 352 +++++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 src/main/java/org/openecomp/datarouter/util/VersionedOxmEntities.java (limited to 'src/main/java/org/openecomp/datarouter/util/VersionedOxmEntities.java') 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