From cbd5b9b82dddb4ae467571ef86dcdccc2268175f Mon Sep 17 00:00:00 2001 From: Daniel Silverthorn Date: Wed, 27 Jun 2018 14:41:31 -0400 Subject: Migrate common code to router-core from DR Change-Id: I3803d2c866b36ace8fda73bb23dff4825e39e846 Signed-off-by: Daniel Silverthorn Issue-ID: AAI-1339 --- .../org/onap/aai/entity/OxmEntityDescriptor.java | 122 +++++++ .../java/org/onap/aai/logging/RouterCoreMsgs.java | 11 + .../org/onap/aai/schema/OxmConfigTranslator.java | 98 ++++++ .../java/org/onap/aai/schema/OxmModelLoader.java | 101 ++++++ .../aai/schema/SchemaIngestPropertiesReader.java | 88 ++++++ .../org/onap/aai/util/CrossEntityReference.java | 93 ++++++ .../onap/aai/util/EntityOxmReferenceHelper.java | 58 ++++ .../onap/aai/util/ExternalOxmModelProcessor.java | 33 ++ src/main/java/org/onap/aai/util/Version.java | 25 ++ .../org/onap/aai/util/VersionedOxmEntities.java | 349 +++++++++++++++++++++ 10 files changed, 978 insertions(+) create mode 100644 src/main/java/org/onap/aai/entity/OxmEntityDescriptor.java create mode 100644 src/main/java/org/onap/aai/schema/OxmConfigTranslator.java create mode 100644 src/main/java/org/onap/aai/schema/OxmModelLoader.java create mode 100644 src/main/java/org/onap/aai/schema/SchemaIngestPropertiesReader.java create mode 100644 src/main/java/org/onap/aai/util/CrossEntityReference.java create mode 100644 src/main/java/org/onap/aai/util/EntityOxmReferenceHelper.java create mode 100644 src/main/java/org/onap/aai/util/ExternalOxmModelProcessor.java create mode 100644 src/main/java/org/onap/aai/util/Version.java create mode 100644 src/main/java/org/onap/aai/util/VersionedOxmEntities.java (limited to 'src/main/java/org') diff --git a/src/main/java/org/onap/aai/entity/OxmEntityDescriptor.java b/src/main/java/org/onap/aai/entity/OxmEntityDescriptor.java new file mode 100644 index 0000000..48ec6e9 --- /dev/null +++ b/src/main/java/org/onap/aai/entity/OxmEntityDescriptor.java @@ -0,0 +1,122 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.entity; + +import java.util.List; + +import org.onap.aai.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.isEmpty() ) { + 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 + "]"; + } +} diff --git a/src/main/java/org/onap/aai/logging/RouterCoreMsgs.java b/src/main/java/org/onap/aai/logging/RouterCoreMsgs.java index 6d34516..f693daf 100644 --- a/src/main/java/org/onap/aai/logging/RouterCoreMsgs.java +++ b/src/main/java/org/onap/aai/logging/RouterCoreMsgs.java @@ -36,6 +36,17 @@ public enum RouterCoreMsgs implements LogMessageEnum { */ EVENT_PROCESSING_EXCEPTION, + /** + * Successfully loaded schema: {0} + * + *

Arguments: + * {0} = oxm filename + */ + LOADED_OXM_FILE, + + /** Failed to load the schemaIngest.properties file */ + SCHEMA_INGEST_LOAD_ERROR, + /** * Arguments: {0} = Creation exception */ diff --git a/src/main/java/org/onap/aai/schema/OxmConfigTranslator.java b/src/main/java/org/onap/aai/schema/OxmConfigTranslator.java new file mode 100644 index 0000000..a829002 --- /dev/null +++ b/src/main/java/org/onap/aai/schema/OxmConfigTranslator.java @@ -0,0 +1,98 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.schema; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.nio.file.Paths; +import java.util.List; +import java.util.Map; +import java.util.ServiceConfigurationError; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.onap.aai.setup.ConfigTranslator; +import org.onap.aai.setup.SchemaLocationsBean; +import org.onap.aai.setup.Version; + +public class OxmConfigTranslator extends ConfigTranslator { + public OxmConfigTranslator(SchemaLocationsBean bean) { + super(bean); + } + + @Override + public Map> getNodeFiles() { + String nodeDirectory = bean.getNodeDirectory(); + if (nodeDirectory == null) { + throw new ServiceConfigurationError( + "Node(s) directory is empty in the schema location bean (" + bean.getSchemaConfigLocation() + ")"); + } + try { + return getVersionMap(Paths.get(nodeDirectory), "*_v*.xml"); + } catch (IOException e) { + throw new ServiceConfigurationError("Failed to read node(s) directory " + getPath(nodeDirectory), e); + } + } + + @Override + public Map> getEdgeFiles() { + String edgeDirectory = bean.getEdgeDirectory(); + if (edgeDirectory == null) { + throw new ServiceConfigurationError( + "Edge(s) directory is empty in the schema location bean (" + bean.getSchemaConfigLocation() + ")"); + } + try { + return getVersionMap(Paths.get(edgeDirectory), "*_v*.json"); + } catch (IOException e) { + throw new ServiceConfigurationError("Failed to read edge(s) directory " + getPath(edgeDirectory), e); + } + } + + private String getPath(String nodeDirectory) { + return Paths.get(nodeDirectory).toAbsolutePath().toString(); + } + + /** + * Creates a map containing each OXM Version and the matching OXM file path(s) + * + * @param folderPath the folder/directory containing the OXM files + * @param fileSuffix + * @return a new Map object (may be empty) + * @throws IOException if there is a problem reading the specified directory path + */ + private Map> getVersionMap(Path folderPath, String globPattern) throws IOException { + final PathMatcher filter = folderPath.getFileSystem().getPathMatcher("glob:**/" + globPattern); + try (final Stream stream = Files.list(folderPath)) { + return stream.filter(filter::matches).map(Path::toString).filter(p -> getVersionFromPath(p) != null) + .collect(Collectors.groupingBy(this::getVersionFromPath)); + } + } + + private Version getVersionFromPath(String pathName) { + String version = "V" + pathName.replaceAll("^.*\\/", "").replaceAll("\\D+", ""); + try { + return Version.valueOf(version); + } catch (IllegalArgumentException e) { + return null; + } + } +} diff --git a/src/main/java/org/onap/aai/schema/OxmModelLoader.java b/src/main/java/org/onap/aai/schema/OxmModelLoader.java new file mode 100644 index 0000000..1e62cfc --- /dev/null +++ b/src/main/java/org/onap/aai/schema/OxmModelLoader.java @@ -0,0 +1,101 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.schema; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.concurrent.ConcurrentHashMap; +import javax.ws.rs.core.Response.Status; +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.logging.RouterCoreMsgs; +import org.onap.aai.util.ExternalOxmModelProcessor; +import org.onap.aai.nodes.NodeIngestor; +import org.onap.aai.setup.ConfigTranslator; +import org.onap.aai.setup.SchemaLocationsBean; +import org.onap.aai.setup.Version; + +public class OxmModelLoader { + + private static Map versionContextMap = new ConcurrentHashMap<>(); + private static List oxmModelProcessorRegistry = new ArrayList<>(); + + private static final org.onap.aai.cl.api.Logger logger = + LoggerFactory.getInstance().getLogger(OxmModelLoader.class.getName()); + + private OxmModelLoader() { + throw new IllegalStateException("Utility class"); + } + + public static synchronized void loadModels() { + SchemaIngestPropertiesReader schemaIngestPropReader = new SchemaIngestPropertiesReader(); + SchemaLocationsBean schemaLocationsBean = new SchemaLocationsBean(); + schemaLocationsBean.setNodeDirectory(schemaIngestPropReader.getNodeDir()); + ConfigTranslator configTranslator = new OxmConfigTranslator(schemaLocationsBean); + NodeIngestor nodeIngestor = new NodeIngestor(configTranslator); + + for (Version oxmVersion : Version.values()) { + DynamicJAXBContext jaxbContext = nodeIngestor.getContextForVersion(oxmVersion); + if (jaxbContext != null) { + loadModel(oxmVersion.toString(), jaxbContext); + } + } + } + + public static DynamicJAXBContext getContextForVersion(String version) { + if (versionContextMap == null || versionContextMap.isEmpty()) { + loadModels(); + } else if (!versionContextMap.containsKey(version)) { + throw new NoSuchElementException(Status.NOT_FOUND.toString()); + } + return versionContextMap.get(version); + } + + public static synchronized void registerExternalOxmModelProcessors( + Collection processors) { + if (processors != null) { + for (ExternalOxmModelProcessor processor : processors) { + if (!oxmModelProcessorRegistry.contains(processor)) { + oxmModelProcessorRegistry.add(processor); + } + } + } + } + + public static Map getVersionContextMap() { + return versionContextMap; + } + + private static synchronized void loadModel(String oxmVersion, DynamicJAXBContext jaxbContext) { + versionContextMap.put(oxmVersion, jaxbContext); + if (oxmModelProcessorRegistry != null) { + for (ExternalOxmModelProcessor processor : oxmModelProcessorRegistry) { + processor.onOxmVersionChange(org.onap.aai.util.Version.valueOf(oxmVersion.toLowerCase()), + jaxbContext); + } + } + logger.info(RouterCoreMsgs.LOADED_OXM_FILE, oxmVersion); + } + +} diff --git a/src/main/java/org/onap/aai/schema/SchemaIngestPropertiesReader.java b/src/main/java/org/onap/aai/schema/SchemaIngestPropertiesReader.java new file mode 100644 index 0000000..d2903e6 --- /dev/null +++ b/src/main/java/org/onap/aai/schema/SchemaIngestPropertiesReader.java @@ -0,0 +1,88 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.schema; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.logging.RouterCoreMsgs; + +public class SchemaIngestPropertiesReader { + + private static final String SCHEMA_INGEST_PROPERTIES_FILE = "schemaIngest.properties"; + private static final String MSG_FAILED_LOAD_SCHEMA_INGEST_PROPERTIES = "Failed to load " + SCHEMA_INGEST_PROPERTIES_FILE; + + private static final String SCHEMA_INGEST_PROPERTIES_LOCATION = + System.getProperty("CONFIG_HOME") + "/" + SCHEMA_INGEST_PROPERTIES_FILE; + + private static org.onap.aai.cl.api.Logger logger = + LoggerFactory.getInstance().getLogger(SchemaIngestPropertiesReader.class.getName()); + + /** + * Gets the location of the OXM. + * + * @return the directory containing the OXM files + */ + public String getNodeDir() { + + Properties prop = new Properties(); + try { + prop = loadFromFile(SCHEMA_INGEST_PROPERTIES_LOCATION); + } catch (NoSuchFileException e) { + try { + prop = loadFromClasspath(SCHEMA_INGEST_PROPERTIES_FILE); + } catch (URISyntaxException | IOException ef) { + logger.error(RouterCoreMsgs.SCHEMA_INGEST_LOAD_ERROR, ef.getMessage()); + throw new RuntimeException(MSG_FAILED_LOAD_SCHEMA_INGEST_PROPERTIES); + } + } catch (IOException ec) { + logger.error(RouterCoreMsgs.SCHEMA_INGEST_LOAD_ERROR, ec.getMessage()); + throw new RuntimeException(MSG_FAILED_LOAD_SCHEMA_INGEST_PROPERTIES); + } + return prop.getProperty("nodeDir"); + } + + private Properties loadFromFile(String filename) throws IOException { + Path configLocation = Paths.get(filename); + try (InputStream stream = Files.newInputStream(configLocation)) { + return loadProperties(stream); + } + } + + private Properties loadFromClasspath(String resourceName) throws URISyntaxException, IOException { + Path path = Paths.get(ClassLoader.getSystemResource(resourceName).toURI()); + try (InputStream stream = Files.newInputStream(path)) { + return loadProperties(stream); + } + } + + private Properties loadProperties(InputStream stream) throws IOException { + Properties config = new Properties(); + config.load(stream); + return config; + } +} diff --git a/src/main/java/org/onap/aai/util/CrossEntityReference.java b/src/main/java/org/onap/aai/util/CrossEntityReference.java new file mode 100644 index 0000000..b8b2737 --- /dev/null +++ b/src/main/java/org/onap/aai/util/CrossEntityReference.java @@ -0,0 +1,93 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.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/onap/aai/util/EntityOxmReferenceHelper.java b/src/main/java/org/onap/aai/util/EntityOxmReferenceHelper.java new file mode 100644 index 0000000..00cdbdf --- /dev/null +++ b/src/main/java/org/onap/aai/util/EntityOxmReferenceHelper.java @@ -0,0 +1,58 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.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); + } + +} diff --git a/src/main/java/org/onap/aai/util/ExternalOxmModelProcessor.java b/src/main/java/org/onap/aai/util/ExternalOxmModelProcessor.java new file mode 100644 index 0000000..b6a009c --- /dev/null +++ b/src/main/java/org/onap/aai/util/ExternalOxmModelProcessor.java @@ -0,0 +1,33 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.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/onap/aai/util/Version.java b/src/main/java/org/onap/aai/util/Version.java new file mode 100644 index 0000000..debbb51 --- /dev/null +++ b/src/main/java/org/onap/aai/util/Version.java @@ -0,0 +1,25 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util; + +public enum Version { + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20; +} \ No newline at end of file diff --git a/src/main/java/org/onap/aai/util/VersionedOxmEntities.java b/src/main/java/org/onap/aai/util/VersionedOxmEntities.java new file mode 100644 index 0000000..609ff26 --- /dev/null +++ b/src/main/java/org/onap/aai/util/VersionedOxmEntities.java @@ -0,0 +1,349 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util; + +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.onap.aai.entity.OxmEntityDescriptor; + +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; + +/** + * 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 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; + 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 ("crossEntityReference".equalsIgnoreCase(entry.getKey())) { + 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; + 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; + + 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 ("searchable".equalsIgnoreCase(entry.getKey())) { + + /* + * 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 ("containsSuggestibleProps".equalsIgnoreCase(entry.getKey())) { + 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 ("suggestionAliases".equalsIgnoreCase(entry.getKey())) { + 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(); + + } + + public Map getEntityTypeLookup() { + return entityTypeLookup; + } + +} -- cgit 1.2.3-korg