aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/onap/aai/entity/OxmEntityDescriptor.java122
-rw-r--r--src/main/java/org/onap/aai/logging/RouterCoreMsgs.java11
-rw-r--r--src/main/java/org/onap/aai/schema/OxmConfigTranslator.java98
-rw-r--r--src/main/java/org/onap/aai/schema/OxmModelLoader.java101
-rw-r--r--src/main/java/org/onap/aai/schema/SchemaIngestPropertiesReader.java88
-rw-r--r--src/main/java/org/onap/aai/util/CrossEntityReference.java93
-rw-r--r--src/main/java/org/onap/aai/util/EntityOxmReferenceHelper.java58
-rw-r--r--src/main/java/org/onap/aai/util/ExternalOxmModelProcessor.java33
-rw-r--r--src/main/java/org/onap/aai/util/Version.java25
-rw-r--r--src/main/java/org/onap/aai/util/VersionedOxmEntities.java349
-rw-r--r--src/main/resources/logging/RouterCoreMsgs.properties10
11 files changed, 987 insertions, 1 deletions
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<String> primaryKeyAttributeName;
+
+ private List<String> searchableAttributes;
+
+ private CrossEntityReference crossEntityReference;
+
+ private List<String> alias;
+
+ private List<String> suggestableAttributes;
+
+ boolean isSuggestableEntity;
+
+ public String getEntityName() {
+ return entityName;
+ }
+
+ public void setEntityName(String entityName) {
+ this.entityName = entityName;
+ }
+
+ public List<String> getPrimaryKeyAttributeName() {
+ return primaryKeyAttributeName;
+ }
+
+ public void setPrimaryKeyAttributeName(List<String> primaryKeyAttributeName) {
+ this.primaryKeyAttributeName = primaryKeyAttributeName;
+ }
+
+ public List<String> getSearchableAttributes() {
+ return searchableAttributes;
+ }
+
+ public void setSearchableAttributes(List<String> 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<String> getAlias() {
+ return alias;
+ }
+
+ public void setAlias(List<String> alias) {
+ this.alias = alias;
+ }
+
+ public List<String> getSuggestableAttributes() {
+ return suggestableAttributes;
+ }
+
+ public void setSuggestableAttributes(List<String> 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
@@ -37,6 +37,17 @@ public enum RouterCoreMsgs implements LogMessageEnum {
EVENT_PROCESSING_EXCEPTION,
/**
+ * Successfully loaded schema: {0}
+ *
+ * <p>Arguments:
+ * {0} = oxm filename
+ */
+ LOADED_OXM_FILE,
+
+ /** Failed to load the schemaIngest.properties file */
+ SCHEMA_INGEST_LOAD_ERROR,
+
+ /**
* Arguments: {0} = Creation exception
*/
EVENT_CONSUMER_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<Version, List<String>> 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<Version, List<String>> 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<Version, List<String>> getVersionMap(Path folderPath, String globPattern) throws IOException {
+ final PathMatcher filter = folderPath.getFileSystem().getPathMatcher("glob:**/" + globPattern);
+ try (final Stream<Path> 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<String, DynamicJAXBContext> versionContextMap = new ConcurrentHashMap<>();
+ private static List<ExternalOxmModelProcessor> 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<ExternalOxmModelProcessor> processors) {
+ if (processors != null) {
+ for (ExternalOxmModelProcessor processor : processors) {
+ if (!oxmModelProcessorRegistry.contains(processor)) {
+ oxmModelProcessorRegistry.add(processor);
+ }
+ }
+ }
+ }
+
+ public static Map<String, DynamicJAXBContext> 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<String> 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<String> getAttributeNames() {
+ return attributeNames;
+ }
+
+ public void setAttributeNames(List<String> 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<Version, VersionedOxmEntities> 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<String, Boolean> crossEntityReferenceContainerLookup = new HashMap<>();
+ private HashMap<String, CrossEntityReference> crossEntityReferenceLookup = new HashMap<>();
+ private Map<String, DynamicType> entityTypeLookup = new LinkedHashMap<>();
+ private Map<String, OxmEntityDescriptor> searchableEntityDescriptors = new HashMap<>();
+ private Map<String, OxmEntityDescriptor> suggestableEntityDescriptors = new HashMap<>();
+ private Map<String, OxmEntityDescriptor> entityAliasDescriptors = new HashMap<>();
+
+
+ public void initialize(DynamicJAXBContext context) {
+ parseOxmContext(context);
+ buildCrossEntityReferenceCollections(REST_ROOT_ENTITY, new HashSet<String>());
+ 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.
+ * <p>
+ * This method will build two collections:
+ * <p>
+ * 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.
+ * <p>
+ * For example, looking at a service-instance <=> inventory path:
+ * <p>
+ * 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)
+ * <p>
+ * 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.
+ * <p>
+ * 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<String> 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<String, String> properties = parentType.getDescriptor().getProperties();
+ if (properties != null) {
+ for (Map.Entry<String, String> 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<DatabaseField> 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<Descriptor> descriptorsList = oxmContext.getXMLContext().getDescriptors();
+ OxmEntityDescriptor newOxmEntity;
+
+ for (Descriptor desc : descriptorsList) {
+
+ DynamicType entity = (DynamicType) oxmContext.getDynamicType(desc.getAlias());
+
+ //LinkedHashMap<String, String> oxmProperties = new LinkedHashMap<String, String>();
+ 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<String, String> properties = entity.getDescriptor().getProperties();
+ if (properties != null) {
+ for (Map.Entry<String, String> 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<DatabaseMapping> descriptorMaps = entity.getDescriptor().getMappings();
+ List<String> 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<String, OxmEntityDescriptor> getSearchableEntityDescriptors() {
+ return searchableEntityDescriptors;
+ }
+
+ public OxmEntityDescriptor getSearchableEntityDescriptor(String entityType) {
+ return searchableEntityDescriptors.get(entityType);
+ }
+
+
+ public HashMap<String, Boolean> getCrossEntityReferenceContainers() {
+ return crossEntityReferenceContainerLookup;
+ }
+
+ public HashMap<String, CrossEntityReference> getCrossEntityReferences() {
+ return crossEntityReferenceLookup;
+ }
+
+
+ private void parseOxmContext(DynamicJAXBContext oxmContext) {
+ List<Descriptor> 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<String, OxmEntityDescriptor> getSuggestableEntityDescriptors() {
+ return suggestableEntityDescriptors;
+ }
+
+ public void setSuggestableEntityDescriptors(
+ Map<String, OxmEntityDescriptor> suggestableEntityDescriptors) {
+ this.suggestableEntityDescriptors = suggestableEntityDescriptors;
+ }
+
+ public Map<String, OxmEntityDescriptor> getEntityAliasDescriptors() {
+ return entityAliasDescriptors;
+ }
+
+ public void setEntityAliasDescriptors(Map<String, OxmEntityDescriptor> entityAliasDescriptors) {
+ this.entityAliasDescriptors = entityAliasDescriptors;
+ }
+
+ public void extractEntities(String entityType, DynamicJAXBContext context, Collection<DynamicType> entities) {
+
+
+ }
+
+ public String dumpCrossEntityReferenceContainers() {
+
+ Set<String> 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<String, DynamicType> getEntityTypeLookup() {
+ return entityTypeLookup;
+ }
+
+}
diff --git a/src/main/resources/logging/RouterCoreMsgs.properties b/src/main/resources/logging/RouterCoreMsgs.properties
index 5c8c183..e8fa332 100644
--- a/src/main/resources/logging/RouterCoreMsgs.properties
+++ b/src/main/resources/logging/RouterCoreMsgs.properties
@@ -31,4 +31,12 @@ EVENT_PROCESSING_EXCEPTION=\
EVENT_CONSUMER_CREATION_EXCEPTION=\
AC0502E|\
- Could not create event consumer due to the following exception: {0} \ No newline at end of file
+ Could not create event consumer due to the following exception: {0}
+
+LOADED_OXM_FILE=\
+ DR0014I|\
+ Successfully loaded schema: {0}
+
+SCHEMA_INGEST_LOAD_ERROR=\
+ DR5001E|\
+ Unable to load schema ingest properties file due to : {0} \ No newline at end of file