Add the nodes endpoint to the schema service
Issue-ID: AAI-1861
Change-Id: I33cf346f1c2a8875945631e437636f65d76a75c8
Signed-off-by: Kajur, Harish (vk250x) <vk250x@att.com>
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/AAIConfigTranslator.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/AAIConfigTranslator.java
new file mode 100644
index 0000000..51417b4
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/AAIConfigTranslator.java
@@ -0,0 +1,118 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.config;
+
+import org.onap.aai.schemaservice.nodeschema.SchemaVersion;
+import org.onap.aai.schemaservice.nodeschema.SchemaVersions;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * <b>AAIConfigTranslator</b> is responsible for looking at the
+ * schema files and edge files based on the available versions
+ * Also has the ability to exclude them based on the node.exclusion.pattern
+ */
+public class AAIConfigTranslator extends ConfigTranslator {
+
+ private static final String FILESEP = (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator");
+
+ public AAIConfigTranslator(SchemaLocationsBean bean, SchemaVersions schemaVersions) {
+ super(bean, schemaVersions);
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.aai.setup.ConfigTranslator#getNodeFiles()
+ */
+ @Override
+ public Map<SchemaVersion, List<String>> getNodeFiles() {
+
+ Map<SchemaVersion, List<String>> files = new TreeMap<>();
+ for (SchemaVersion v : schemaVersions.getVersions()) {
+ List<String> container = getVersionNodeFiles(v);
+ files.put(v, container);
+ }
+
+ return files;
+ }
+
+
+ private List<String> getVersionNodeFiles(SchemaVersion v) {
+
+ return getVersionFiles(
+ bean.getNodeDirectory(),
+ v,
+ () -> bean.getNodesInclusionPattern().stream(),
+ () -> bean.getNodesExclusionPattern().stream()
+ );
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.onap.aai.setup.ConfigTranslator#getEdgeFiles()
+ */
+ @Override
+ public Map<SchemaVersion, List<String>> getEdgeFiles() {
+
+ Map<SchemaVersion, List<String>> files = new TreeMap<>();
+ for (SchemaVersion v : schemaVersions.getVersions()) {
+ List<String> container = getVersionEdgeFiles(v);
+ files.put(v, container);
+ }
+
+ return files;
+ }
+
+ private List<String> getVersionEdgeFiles(SchemaVersion v) {
+
+ return getVersionFiles(
+ bean.getEdgeDirectory(),
+ v,
+ () -> bean.getEdgesInclusionPattern().stream(),
+ () -> bean.getEdgesExclusionPattern().stream()
+ );
+ }
+
+ private List<String> getVersionFiles(
+ String startDirectory,
+ SchemaVersion schemaVersion,
+ Supplier<Stream<String>> inclusionPattern,
+ Supplier<Stream<String>> exclusionPattern
+ ){
+
+ List<String> container;
+ final String directoryName = startDirectory + FILESEP + schemaVersion.toString() + FILESEP;
+
+ container = Arrays.stream(new File(directoryName).listFiles())
+ .map(File::getName)
+ .filter(name -> inclusionPattern.get().anyMatch(name::matches))
+ .map(name -> directoryName + name)
+ .filter(name -> exclusionPattern.get().noneMatch(name::matches))
+ .collect(Collectors.toList());
+
+ return container;
+ }
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/AuthorizationConfiguration.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/AuthorizationConfiguration.java
new file mode 100644
index 0000000..76dd084
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/AuthorizationConfiguration.java
@@ -0,0 +1,39 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.config;
+
+import org.onap.aai.auth.AAIAuthCore;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+@Profile("two-way-ssl")
+@Configuration
+public class AuthorizationConfiguration {
+
+ @Value("${schema.uri.base.path}")
+ private String basePath;
+
+ @Bean
+ public AAIAuthCore aaiAuthCore(){
+ return new AAIAuthCore(basePath);
+ }
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/ConfigTranslator.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/ConfigTranslator.java
new file mode 100644
index 0000000..a177c6d
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/ConfigTranslator.java
@@ -0,0 +1,66 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.config;
+
+import org.onap.aai.schemaservice.nodeschema.SchemaVersion;
+import org.onap.aai.schemaservice.nodeschema.SchemaVersions;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Converts the contents of the schema config file
+ * (which lists which schema files to be loaded) to
+ * the format the Ingestors can work with.
+ *
+ */
+public abstract class ConfigTranslator {
+ protected SchemaLocationsBean bean;
+ protected SchemaVersions schemaVersions;
+
+ @Autowired
+ public ConfigTranslator(SchemaLocationsBean schemaLocationbean, SchemaVersions schemaVersions) {
+ this.bean = schemaLocationbean;
+ this.schemaVersions = schemaVersions;
+ }
+
+ /**
+ * Translates the contents of the schema config file
+ * into the input for the NodeIngestor
+ *
+ * @return Map of Version to the list of (string) filenames to be
+ * ingested for that version
+ */
+ public abstract Map<SchemaVersion, List<String>> getNodeFiles();
+
+ /**
+ * Translates the contents of the schema config file
+ * into the input for the EdgeIngestor
+ *
+ * @return Map of Version to the List of (String) filenames to be
+ * ingested for that version
+ */
+ public abstract Map<SchemaVersion, List<String>> getEdgeFiles();
+
+ public SchemaVersions getSchemaVersions(){
+ return schemaVersions;
+ }
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/SchemaConfiguration.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/SchemaConfiguration.java
new file mode 100644
index 0000000..390525b
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/SchemaConfiguration.java
@@ -0,0 +1,69 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.config;
+
+import org.onap.aai.schemaservice.nodeschema.NodeIngestor;
+import org.onap.aai.schemaservice.nodeschema.SchemaVersions;
+import org.onap.aai.schemaservice.nodeschema.validation.*;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SchemaConfiguration {
+
+ @Bean(name = "nodeIngestor")
+ public NodeIngestor nodeIngestor(ConfigTranslator configTranslator) {
+ return new NodeIngestor(configTranslator);
+ }
+
+ @Bean(name = "configTranslator")
+ public ConfigTranslator configTranslator(SchemaLocationsBean schemaLocationsBean, SchemaVersions schemaVersions) {
+ return new AAIConfigTranslator(schemaLocationsBean, schemaVersions);
+ }
+
+ @Bean
+ public SchemaErrorStrategy schemaErrorStrategy() {
+ return new CheckEverythingStrategy();
+ }
+
+ @Bean
+ public DuplicateNodeDefinitionValidationModule duplicateNodeDefinitionValidationModule() {
+ return new DefaultDuplicateNodeDefinitionValidationModule();
+ }
+
+ @Bean
+ public NodeValidator nodeValidator(
+ ConfigTranslator configTranslator,
+ SchemaErrorStrategy schemaErrorStrategy,
+ DuplicateNodeDefinitionValidationModule duplicateNodeDefinitionValidationModule
+ ) {
+ return new NodeValidator(configTranslator, schemaErrorStrategy, duplicateNodeDefinitionValidationModule);
+ }
+
+ @Bean
+ public SchemaLocationsBean schemaLocationsBean() {
+ return new SchemaLocationsBean();
+ }
+
+ @Bean
+ public SchemaVersions schemaVersions() {
+ return new SchemaVersions();
+ }
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/SchemaLocationsBean.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/SchemaLocationsBean.java
new file mode 100644
index 0000000..e24aa78
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/SchemaLocationsBean.java
@@ -0,0 +1,138 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
+
+import java.util.List;
+
+@Configuration
+@PropertySource(value = "classpath:schema-ingest.properties", ignoreResourceNotFound=true)
+@PropertySource(value = "file:${schema.ingest.file}", ignoreResourceNotFound=true)
+public class SchemaLocationsBean {
+ /*
+ * Per Spring documentation, the last PropertySource that works will
+ * be applied. Here, schema.ingest.file will be an environment variable
+ * set on install that tells Spring where to look for the schema
+ * ingest properties file (and the actual filename), but the former
+ * PropertySource gives the default of looking on the classpath for
+ * schema-ingest.properties in case that second one doesn't work.
+ *
+ * The schema-ingest.properties file (or its equivalent if you choose
+ * to name it otherwise) must contain the entries the below @Value
+ * annotations are looking for.
+ */
+
+ @Value("${schema.configuration.location}")
+ private String schemaConfigLoc;
+
+ @Value("${schema.nodes.location}")
+ private String nodeDirectory;
+
+ @Value("${schema.edges.location}")
+ private String edgeDirectory;
+
+ @Value("${schema.nodes.inclusion.list:}#{T(java.util.Arrays).asList(\".*oxm(.*).xml\")}")
+ private List<String> nodesInclusionPattern;
+
+ @Value("${schema.nodes.exclusion.list:}#{T(java.util.Collections).emptyList()}")
+ private List<String> nodesExclusionPattern;
+
+ @Value("${schema.edges.inclusion.list:}#{T(java.util.Arrays).asList(\"DbEdgeRules_.*.json\")}")
+ private List<String> edgesInclusionPattern;
+
+ @Value("${schema.edges.exclusion.list:}#{T(java.util.Collections).emptyList()}")
+ private List<String> edgesExclusionPattern;
+
+ /**
+ * @return the file name/location with the list of schema files to be ingested
+ */
+ public String getSchemaConfigLocation() {
+ return schemaConfigLoc;
+ }
+
+ /**
+ * Sets the name/location of the file with the list of schema files to ingest
+ *
+ * @param schemaConfigLoc - the file name/location
+ */
+ public void setSchemaConfigLocation(String schemaConfigLoc) {
+ this.schemaConfigLoc = schemaConfigLoc;
+ }
+
+ /**
+ * @return the location of the OXM files
+ */
+ public String getNodeDirectory() {
+ return nodeDirectory;
+ }
+
+ /**
+ * Sets the location of the OXM files
+ *
+ * @param nodeDirectory - the location of the OXM files
+ */
+ public void setNodeDirectory(String nodeDirectory) {
+ this.nodeDirectory = nodeDirectory;
+ }
+
+ /**
+ * @return the location of the edge rule json files
+ */
+ public String getEdgeDirectory() {
+ return edgeDirectory;
+ }
+
+ /**
+ * Sets the location of the edge rule json files
+ *
+ * @param edgeDirectory - the location of the edge rule files
+ */
+ public void setEdgeDirectory(String edgeDirectory) {
+ this.edgeDirectory = edgeDirectory;
+ }
+
+ public List<String> getNodesExclusionPattern(){
+ return this.nodesExclusionPattern;
+ }
+
+ public List<String> getNodesInclusionPattern(){
+ return this.nodesInclusionPattern;
+ }
+
+ public List<String> getEdgesExclusionPattern(){
+ return this.edgesExclusionPattern;
+ }
+
+ public List<String> getEdgesInclusionPattern(){
+ return this.edgesInclusionPattern;
+ }
+
+ //this allows the code to actually read the value from the config file
+ //without this those strings get set to literally "${edgeDir}" etc
+ @Bean
+ public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
+ return new PropertySourcesPlaceholderConfigurer();
+ }
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/NodeIngestor.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/NodeIngestor.java
new file mode 100644
index 0000000..e372c2a
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/NodeIngestor.java
@@ -0,0 +1,279 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.common.base.CaseFormat;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import org.eclipse.persistence.jaxb.JAXBContextProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
+import org.onap.aai.schemaservice.config.ConfigTranslator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * NodeIngestor - ingests A&AI OXM files per given config, serves DynamicJAXBContext per version
+ */
+@Component
+public class NodeIngestor {
+
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(NodeIngestor.class);
+
+ private static final Pattern classNamePattern = Pattern.compile("\\.(v\\d+)\\.");
+ private Map<SchemaVersion, DynamicJAXBContext> versionContextMap = new TreeMap<>();
+ private Map<SchemaVersion, Set<String>> typesPerVersion = new TreeMap<>();
+ private Map<SchemaVersion, Document> schemaPerVersion = new TreeMap<>();
+ private ConfigTranslator translator;
+
+
+ @Autowired
+ /**
+ * Instantiates the NodeIngestor bean.
+ *
+ * @param translator - ConfigTranslator autowired in by Spring framework which
+ * contains the configuration information needed to ingest the desired files.
+ */
+ public NodeIngestor(ConfigTranslator translator) {
+ this.translator = translator;
+ Map<SchemaVersion, List<String>> filesToIngest = translator.getNodeFiles();
+
+ try {
+ for (Entry<SchemaVersion, List<String>> verFiles : filesToIngest.entrySet()) {
+ SchemaVersion v = verFiles.getKey();
+ List<String> files = verFiles.getValue();
+ final DynamicJAXBContext ctx = ingest(files);
+ versionContextMap.put(v, ctx);
+ typesPerVersion.put(v, getAllNodeTypes(files));
+ schemaPerVersion.put(v, createCombinedSchema(files, v));
+ }
+ } catch (JAXBException | ParserConfigurationException | SAXException | IOException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ /**
+ * Ingests the given OXM files into DynamicJAXBContext
+ *
+ * @param files - List<String> of full filenames (ie including the path) to be ingested
+ * @return DynamicJAXBContext including schema information from all given files
+ * @throws FileNotFoundException if an OXM file can't be found
+ * @throws JAXBException if there's an error creating the DynamicJAXBContext
+ */
+ private DynamicJAXBContext ingest(List<String> files) throws FileNotFoundException, JAXBException {
+ List<InputStream> streams = new ArrayList<>();
+
+ for (String name : files) {
+ streams.add(new FileInputStream(new File(name)));
+ }
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, streams);
+ return DynamicJAXBContextFactory.createContextFromOXM(this.getClass().getClassLoader(), properties);
+ }
+
+
+ private Set<String> getAllNodeTypes(List<String> files) throws ParserConfigurationException, SAXException, IOException {
+ Set<String> types = new HashSet<>();
+ final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ docFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ final DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+
+ ArrayList<Node> javaTypes = new ArrayList<>();
+ for (String file : files) {
+ InputStream inputStream = new FileInputStream(file);
+
+ final Document doc = docBuilder.parse(inputStream);
+ final NodeList list = doc.getElementsByTagName("java-type");
+
+
+ for (int i = 0; i < list.getLength(); i++) {
+ String type = list.item(i).getAttributes().getNamedItem("name").getNodeValue();
+ javaTypes.add(list.item(i));
+ types.add(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, type));
+ }
+ }
+
+ return types;
+ }
+
+ private Document createCombinedSchema(List<String> files, SchemaVersion v) throws ParserConfigurationException, SAXException, IOException {
+ final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ docFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ final DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+ DocumentBuilder masterDocBuilder = docFactory.newDocumentBuilder();
+ Document combinedDoc = masterDocBuilder.parse(getShell(v));
+ NodeList masterList = combinedDoc.getElementsByTagName("java-types");
+ Node javaTypesContainer = masterList.getLength() == 0 ? combinedDoc.getDocumentElement() : masterList.item(0);
+
+ Multimap<String, Node> nodeMultimap = ArrayListMultimap.create();
+ LOGGER.debug("Started combining the schema from list of files {} for version {}", files, v);
+
+ for (String file : files) {
+ InputStream inputStream = new FileInputStream(file);
+
+ final Document doc = docBuilder.parse(inputStream);
+ final NodeList list = doc.getElementsByTagName("java-type");
+
+ for(int i = 0; i < list.getLength(); i++){
+ Node curNode = list.item(i);
+ String name = curNode.getAttributes().getNamedItem("name").getNodeValue();
+ nodeMultimap.put(name, curNode);
+ }
+ }
+
+ Map<String, Collection<Node>> map = nodeMultimap.asMap();
+ createNode(combinedDoc, javaTypesContainer, map);
+
+ LOGGER.debug("Successfully merged all schema files for version {}", v);
+
+ return combinedDoc;
+ }
+
+ private void createNode(Document combinedDoc, Node javaTypesContainer, Map<String, Collection<Node>> map){
+
+ for (Entry<String, Collection<Node>> entry : map.entrySet()) {
+
+ List<Node> listOfNodes = (List<Node>)entry.getValue();
+ LOGGER.trace("NodeType {} Occurrences {}", entry.getKey(), listOfNodes.size());
+ Node copyOfFirstElement = null;
+ Node javaAttributeElement = null;
+
+ if(listOfNodes.size() > 1){
+ for(int index = 0; index < listOfNodes.size(); index++){
+ if(index == 0){
+ Node currentNode = listOfNodes.get(index);
+ copyOfFirstElement = combinedDoc.importNode(currentNode, true);
+ if(copyOfFirstElement.getNodeType() == Node.ELEMENT_NODE){
+ Element element = (Element) copyOfFirstElement;
+ NodeList javaAttributesList = element.getElementsByTagName("java-attributes");
+ for(int javaAttributeIndex = 0; javaAttributeIndex < javaAttributesList.getLength(); javaAttributeIndex++){
+ javaAttributeElement = javaAttributesList.item(javaAttributeIndex);
+ }
+ }
+ } else {
+ Node currentNode = listOfNodes.get(index);
+ Node copyOfCurrentElement = combinedDoc.importNode(currentNode, true);
+ if(copyOfCurrentElement.getNodeType() == Node.ELEMENT_NODE){
+ Element element = (Element) copyOfCurrentElement;
+ NodeList javaAttributesList = element.getElementsByTagName("java-attributes");
+ for(int javaAttributeIndex = 0; javaAttributeIndex < javaAttributesList.getLength(); javaAttributeIndex++){
+ Node jaElement = javaAttributesList.item(javaAttributeIndex);
+ NodeList xmlElementList = jaElement.getChildNodes();
+ for(int xmlElementIndex = 0; xmlElementIndex < xmlElementList.getLength(); xmlElementIndex++){
+ if(javaAttributeElement != null){
+ Node curElem = xmlElementList.item(xmlElementIndex);
+ if(curElem != null){
+ javaAttributeElement.appendChild(curElem.cloneNode(true));
+ }
+ }
+ }
+ }
+ }
+
+ }
+ }
+ javaTypesContainer.appendChild(copyOfFirstElement);
+ } else if(listOfNodes.size() == 1){
+ javaTypesContainer.appendChild(combinedDoc.importNode(listOfNodes.get(0), true));
+ }
+ }
+ }
+
+ /**
+ * Gets the DynamicJAXBContext for the given version
+ *
+ * @param v
+ * @return DynamicJAXBContext
+ */
+ public DynamicJAXBContext getContextForVersion(SchemaVersion v) {
+ return versionContextMap.get(v);
+ }
+
+ /**
+ * Determines if the given version contains the given node type
+ *
+ * @param nodeType - node type to check, must be in lower hyphen form (ie "type-name")
+ * @param v - schema version to check against
+ * @return
+ */
+ public boolean hasNodeType(String nodeType, SchemaVersion v) {
+ return typesPerVersion.get(v).contains(nodeType);
+ }
+
+ public Set<String> getObjectsInVersion(SchemaVersion v) {
+ return typesPerVersion.get(v);
+ }
+
+ /**
+ * Determines if the given version contains the given node type
+ *
+ * @param nodeType - node type to check, must be in lower hyphen form (ie "type-name")
+ * @param v
+ * @return
+ */
+ public Document getSchema(SchemaVersion v) {
+ return schemaPerVersion.get(v);
+ }
+
+ private InputStream getShell(SchemaVersion v) {
+ String source = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<xml-bindings xmlns=\"http://www.eclipse.org/eclipselink/xsds/persistence/oxm\" package-name=\"inventory.aai.onap.org." + v.toString().toLowerCase() + "\" xml-mapping-metadata-complete=\"true\">\n" +
+ " <xml-schema element-form-default=\"QUALIFIED\">\n" +
+ " <xml-ns namespace-uri=\"http://org.onap.aai.inventory/" + v.toString().toLowerCase() + "\" />\n" +
+ " </xml-schema>\n" +
+ " <java-types>\n" +
+ " </java-types>\n" +
+ "</xml-bindings>";
+ return new ByteArrayInputStream(source.getBytes(StandardCharsets.UTF_8));
+ }
+
+
+ public SchemaVersion getVersionFromClassName(String classname) {
+ Matcher m = classNamePattern.matcher(classname);
+ String version = null;
+ if (m.find()) {
+ version = m.group(1);
+ return new SchemaVersion(version);
+ } else {
+ return translator.getSchemaVersions().getDefaultVersion();
+ }
+ }
+}
+
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/NodeSchemaResource.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/NodeSchemaResource.java
new file mode 100644
index 0000000..4eccd71
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/NodeSchemaResource.java
@@ -0,0 +1,90 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema;
+
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.restcore.HttpMethod;
+import org.onap.aai.restcore.RESTAPI;
+import org.onap.aai.schemaservice.nodeschema.validation.AAISchemaValidationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.StringUtils;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.Optional;
+
+@Path("/v1")
+public class NodeSchemaResource extends RESTAPI {
+
+ private final NodeSchemaService nodeSchemaService;
+
+ private final SchemaVersions schemaVersions;
+
+ @Autowired
+ public NodeSchemaResource(NodeSchemaService nodeSchemaService, SchemaVersions schemaVersions) {
+ this.nodeSchemaService = nodeSchemaService;
+ this.schemaVersions = schemaVersions;
+ }
+
+ @GET
+ @Path("/nodes")
+ @Produces({ "application/xml"})
+ public Response retrieveSchema(@QueryParam("version") String version,
+ @Context HttpHeaders headers,
+ @Context UriInfo info)
+ {
+ Response response;
+ Optional<String> optionalSchema = nodeSchemaService.fetch(version);
+ try {
+
+ if(StringUtils.isEmpty(version)){
+ throw new AAIException("AAI_3050");
+ }
+
+ SchemaVersion schemaVersion = new SchemaVersion(version);
+
+ if(!schemaVersions.getVersions().contains(schemaVersion)){
+ throw new AAIException("AAI_3018", version);
+ }
+
+ if (!optionalSchema.isPresent()) {
+ throw new AAIException("AAI_3001");
+ }
+
+ response = Response.ok(optionalSchema.get()).build();
+
+ } catch(AAIException ex){
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex);
+ } catch(AAISchemaValidationException ex){
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, new AAIException("AAI_3051", version));
+ } catch(Exception ex){
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, new AAIException("AAI_4000"));
+ }
+
+ return response;
+ }
+
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/NodeSchemaService.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/NodeSchemaService.java
new file mode 100644
index 0000000..07f4cf4
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/NodeSchemaService.java
@@ -0,0 +1,92 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.onap.aai.logging.LogFormatTools;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+@Service
+public class NodeSchemaService {
+
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(NodeSchemaResource.class);
+
+ private SchemaVersions schemaVersions;
+
+ private NodeIngestor nodeIngestor;
+
+ private Map<String, String> versionMap = new HashMap<>();
+
+ public NodeSchemaService(NodeIngestor nodeIngestor, SchemaVersions schemaVersions) {
+ this.nodeIngestor = nodeIngestor;
+ this.schemaVersions = schemaVersions;
+ }
+
+ @PostConstruct
+ public void initialize() {
+
+ schemaVersions.getVersions().forEach((schemaVersion -> {
+
+ TransformerFactory tf = TransformerFactory.newInstance();
+
+ Transformer transformer = null;
+ try {
+ transformer = tf.newTransformer();
+ } catch (TransformerConfigurationException e) {
+ LOGGER.warn("Encountered an transformer configuration exception" +
+ "during node schema service startup ", LogFormatTools.getStackTop(e));
+ }
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+ transformer.setOutputProperty(OutputKeys.INDENT, "no");
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ try {
+ DOMSource domSource = new DOMSource(nodeIngestor.getSchema(schemaVersion));
+
+ StreamResult streamResult = new StreamResult(new OutputStreamWriter(buffer, "UTF-8"));
+ transformer.transform(domSource, streamResult);
+ versionMap.put(schemaVersion.toString(), buffer.toString("UTF-8"));
+ } catch (TransformerException | UnsupportedEncodingException e) {
+ LOGGER.warn("Encountered an transformer or unsupported encoding exception " +
+ "during node schema service startup ", LogFormatTools.getStackTop(e));
+ }
+
+ }));
+ }
+
+ public Optional<String> fetch(String version) {
+ return Optional.ofNullable(versionMap.get(version));
+ }
+
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/SchemaVersion.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/SchemaVersion.java
new file mode 100644
index 0000000..fc5b48c
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/SchemaVersion.java
@@ -0,0 +1,84 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema;
+
+import org.onap.aai.schemaservice.nodeschema.validation.AAISchemaValidationException;
+
+import java.util.regex.Pattern;
+
+public class SchemaVersion implements Comparable<SchemaVersion> {
+
+ public static final Pattern VERSION_PATTERN = Pattern.compile("v[1-9][0-9]*");
+
+ private final String value;
+
+ public SchemaVersion(String value){
+
+ if(!VERSION_PATTERN.matcher(value).matches()){
+ throw new AAISchemaValidationException("Invalid Schema Version " + value + ", value doesn't match the expected regex: " + VERSION_PATTERN);
+ }
+
+ this.value = value;
+ }
+
+ @Override
+ public int hashCode(){
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object other){
+ if(this == other){
+ return true;
+ }
+
+ if(other == null){
+ return false;
+ }
+
+ if(!(other instanceof SchemaVersion)){
+ return false;
+ }
+
+ SchemaVersion obj = (SchemaVersion)other;
+ return this.value.equals(obj.value);
+ }
+
+ @Override
+ public String toString(){
+ return value;
+ }
+
+ @Override
+ public int compareTo(SchemaVersion o) {
+
+ if(o == null){
+ return -1;
+ }
+
+ // Requires to convert to integer to match the past behavior
+ // Otherwise the string comparison of versions aren't working as expected
+
+ Integer tVal = Integer.parseInt(this.value.replaceAll("v", ""));
+ Integer oVal = Integer.parseInt(o.value.replaceAll("v", ""));
+
+ return tVal.compareTo(oVal);
+ }
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/SchemaVersions.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/SchemaVersions.java
new file mode 100644
index 0000000..208d5d0
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/SchemaVersions.java
@@ -0,0 +1,158 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema;
+
+import org.onap.aai.schemaservice.nodeschema.validation.AAISchemaValidationException;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+@PropertySource(value = "classpath:schema-ingest.properties", ignoreResourceNotFound = true)
+@PropertySource(value = "file:${schema.ingest.file}", ignoreResourceNotFound = true)
+public class SchemaVersions {
+
+ @Value("#{'${schema.version.list}'.split(',')}")
+ private List<String> apiVersions;
+
+ @Value("${schema.version.api.default}")
+ private String defaultApiVersion;
+
+ @Value("${schema.version.edge.label.start}")
+ private String edgeLabelStartVersion;
+
+ @Value("${schema.version.depth.start}")
+ private String depthStartVersion;
+
+ @Value("${schema.version.app.root.start}")
+ private String appRootStartVersion;
+
+ @Value("${schema.version.related.link.start}")
+ private String relatedLinkStartVersion;
+
+ @Value("${schema.version.namespace.change.start}")
+ private String namespaceChangeStartVersion;
+
+ private List<SchemaVersion> versions;
+
+ private SchemaVersion edgeLabelVersion;
+ private SchemaVersion defaultVersion;
+ private SchemaVersion depthVersion;
+ private SchemaVersion appRootVersion;
+ private SchemaVersion relatedLinkVersion;
+ private SchemaVersion namespaceChangeVersion;
+
+ @PostConstruct
+ public void initialize() {
+ versions = apiVersions.stream().map(SchemaVersion::new).collect(Collectors.toList());
+
+ edgeLabelVersion = new SchemaVersion(edgeLabelStartVersion);
+ defaultVersion = new SchemaVersion(defaultApiVersion);
+ depthVersion = new SchemaVersion(depthStartVersion);
+ appRootVersion = new SchemaVersion(appRootStartVersion);
+ relatedLinkVersion = new SchemaVersion(relatedLinkStartVersion);
+ namespaceChangeVersion = new SchemaVersion(namespaceChangeStartVersion);
+
+ if (!versions.contains(edgeLabelVersion)) {
+ throw new AAISchemaValidationException(
+ "Invalid, edge label version is not in the api versions list"
+ + ", please check schema.version.list and ensure that the"
+ + " schema.version.edge.label.start is in that list"
+ );
+ }
+
+ if (!versions.contains(defaultVersion)) {
+ throw new AAISchemaValidationException(
+ "Invalid, default version is not in the api versions list"
+ + ", please check schema.version.list and ensure that the"
+ + " schema.version.api.default is in that list"
+ );
+ }
+
+ if (!versions.contains(depthVersion)) {
+ throw new AAISchemaValidationException(
+ "Invalid, depth version is not in the api versions list"
+ + ", please check schema.version.list and ensure that the"
+ + " schema.version.depth.start is in that list"
+ );
+ }
+
+ if(!versions.contains(appRootVersion)){
+ throw new AAISchemaValidationException(
+ "Invalid, app root version is not in the api versions list"
+ + ", please check schema.version.list and ensure that the"
+ + " schema.version.app.root.start is in that list"
+ );
+ }
+
+ if(!versions.contains(relatedLinkVersion)){
+ throw new AAISchemaValidationException(
+ "Invalid, related link version is not in the api versions list"
+ + ", please check schema.version.list and ensure that the"
+ + " schema.version.related.link.start is in that list"
+ );
+ }
+
+ if(!versions.contains(namespaceChangeVersion)){
+ throw new AAISchemaValidationException(
+ "Invalid, namespace change start version is not in the api versions list"
+ + ", please check schema.version.list and ensure that the"
+ + " schema.version.related.link.start is in that list"
+ );
+ }
+ }
+
+ public List<SchemaVersion> getVersions() {
+ return versions;
+ }
+
+ public SchemaVersion getEdgeLabelVersion() {
+ return edgeLabelVersion;
+ }
+
+ public SchemaVersion getDefaultVersion() {
+ return defaultVersion;
+ }
+
+ public SchemaVersion getDepthVersion() {
+ return depthVersion;
+ }
+
+ public SchemaVersion getAppRootVersion(){
+ return appRootVersion;
+ }
+
+ public SchemaVersion getRelatedLinkVersion(){
+ return relatedLinkVersion;
+ }
+
+ public SchemaVersion getNamespaceChangeVersion() {
+ return namespaceChangeVersion;
+ }
+
+ public void setNamespaceChangeVersion(SchemaVersion namespaceChangeVersion) {
+ this.namespaceChangeVersion = namespaceChangeVersion;
+ }
+
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/AAISchemaValidationException.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/AAISchemaValidationException.java
new file mode 100644
index 0000000..e096a7d
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/AAISchemaValidationException.java
@@ -0,0 +1,29 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema.validation;
+
+/**
+ * Indicates that a fatal error in the A&AI schema has been found.
+ */
+public class AAISchemaValidationException extends IllegalStateException {
+ public AAISchemaValidationException(String msg) {
+ super(msg);
+ }
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/CheckEverythingStrategy.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/CheckEverythingStrategy.java
new file mode 100644
index 0000000..de31212
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/CheckEverythingStrategy.java
@@ -0,0 +1,66 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema.validation;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * When an error is found, mark that it is NOT ok to
+ * continue with installation/whatever other caller function,
+ * and keep track of the message but
+ * keep validating so all issues are found in one run.
+ */
+public class CheckEverythingStrategy implements SchemaErrorStrategy {
+ private boolean isOK = true;
+ private List<String> errorMsgs = new ArrayList<>();
+
+ /* (non-Javadoc)
+ * @see org.onap.aai.edges.validation.SchemaErrorStrategy#isOK()
+ */
+ @Override
+ public boolean isOK() {
+ return isOK;
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.aai.edges.validation.SchemaErrorStrategy#getErrorMsg()
+ */
+ @Override
+ public String getErrorMsg() {
+ if (errorMsgs.isEmpty()) {
+ return "No errors found.";
+ } else {
+ return StringUtils.join(errorMsgs, "\n");
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.aai.edges.validation.SchemaErrorStrategy#notifyOnError(java.lang.String)
+ */
+ @Override
+ public void notifyOnError(String errorMsg) {
+ isOK = false;
+ errorMsgs.add(errorMsg);
+ }
+
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/DefaultDuplicateNodeDefinitionValidationModule.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/DefaultDuplicateNodeDefinitionValidationModule.java
new file mode 100644
index 0000000..915a54d
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/DefaultDuplicateNodeDefinitionValidationModule.java
@@ -0,0 +1,101 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema.validation;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import org.onap.aai.schemaservice.nodeschema.SchemaVersion;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Default duplicate rules for A&AI -
+ * node types may never have a duplicate definition
+ * within the same Version's file set.
+ *
+ * Finds all duplicates and what files they're in.
+ *
+ */
+public class DefaultDuplicateNodeDefinitionValidationModule implements DuplicateNodeDefinitionValidationModule {
+
+ /* (non-Javadoc)
+ * @see org.onap.aai.nodes.validation.DuplicateNodeDefinitionValidationModule#findDuplicates(java.util.List)
+ */
+ @Override
+ public String findDuplicates(List<String> files, SchemaVersion v) {
+ try {
+ final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ docFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ final DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+
+ Multimap<String, String> types = ArrayListMultimap.create();
+ boolean foundDups = false;
+ for (String file : files) {
+ InputStream inputStream = new FileInputStream(file);
+ final Document doc = docBuilder.parse(inputStream);
+ final NodeList list = doc.getElementsByTagName("java-type");
+
+ for (int i = 0; i < list.getLength(); i++) {
+ String type = list.item(i).getAttributes().getNamedItem("name").getNodeValue();
+ if (types.containsKey(type)) {
+ foundDups = true;
+ }
+ types.put(type, file);
+ }
+ }
+
+ if (foundDups) {
+ return buildErrorMsg(types, v);
+ } else {
+ return "";
+ }
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ // TODO something useful with this information
+ return e.getMessage();
+ }
+ }
+
+ private String buildErrorMsg(Multimap<String, String> types, SchemaVersion v) {
+ StringBuilder errorMsg = new StringBuilder().append("Duplicates found in version ").append(v.toString()).append(". ");
+ for (String nodeType : types.keySet()) {
+ Collection<String> files = types.get(nodeType);
+ if (files.size() == 1) {
+ continue; //only record the duplicated ones
+ }
+ errorMsg.append(nodeType).append(" has definitions in ");
+ for (String file : files) {
+ errorMsg.append(file).append(" ");
+ }
+ }
+ return errorMsg.toString();
+ }
+
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/DefaultVersionValidationModule.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/DefaultVersionValidationModule.java
new file mode 100644
index 0000000..acd4095
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/DefaultVersionValidationModule.java
@@ -0,0 +1,72 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema.validation;
+
+import org.onap.aai.schemaservice.config.ConfigTranslator;
+import org.onap.aai.schemaservice.nodeschema.SchemaVersion;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * By default, A&AI must have schema files for all current
+ * supported Versions in the Version enum
+ *
+ */
+@Component
+public class DefaultVersionValidationModule implements VersionValidationModule {
+ private ConfigTranslator config;
+
+ @Autowired
+ public DefaultVersionValidationModule(ConfigTranslator config) {
+ this.config = config;
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.aai.validation.VersionValidationModule#validate(org.onap.aai.setup.ConfigTranslator)
+ */
+ @Override
+ public String validate() {
+ Map<SchemaVersion, List<String>> nodeConfig = config.getNodeFiles();
+ Map<SchemaVersion, List<String>> edgeConfig = config.getEdgeFiles();
+
+ StringBuilder missingVers = new StringBuilder().append("Missing schema for the following versions: ");
+ boolean isMissing = false;
+ for (SchemaVersion v : config.getSchemaVersions().getVersions()) {
+ if (nodeConfig.get(v) == null) {
+ isMissing = true;
+ missingVers.append(v.toString()).append(" has no OXM configured. ");
+ }
+ if (edgeConfig.get(v) == null) {
+ isMissing = true;
+ missingVers.append(v.toString()).append(" has no edge rules configured. ");
+ }
+ }
+
+ if (isMissing) {
+ return missingVers.toString();
+ } else {
+ return "";
+ }
+ }
+
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/DuplicateNodeDefinitionValidationModule.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/DuplicateNodeDefinitionValidationModule.java
new file mode 100644
index 0000000..cb5f5e3
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/DuplicateNodeDefinitionValidationModule.java
@@ -0,0 +1,46 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema.validation;
+
+import org.onap.aai.schemaservice.nodeschema.SchemaVersion;
+
+import java.util.List;
+
+/**
+ * Defines rules for duplicate node definitions in a set of files
+ * (where the intent is the set of files is all the OXM for one version).
+ *
+ * Example Options:
+ * -Any duplicated definition found is an error
+ * -Duplicates within a namespace are OK but not across namespaces
+ * -Anything goes
+ * etc.
+ */
+public interface DuplicateNodeDefinitionValidationModule {
+ /**
+ * Finds any duplicates according to the defined rules
+ *
+ * @param files - the OXM files to use with full directory
+ * @return empty String if none found, else a String
+ * with appropriate information about what node types
+ * were found
+ */
+ String findDuplicates(List<String> files, SchemaVersion v);
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/FailFastStrategy.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/FailFastStrategy.java
new file mode 100644
index 0000000..7463a7d
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/FailFastStrategy.java
@@ -0,0 +1,57 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema.validation;
+
+/**
+ * Fails out the validation process as soon as
+ * an error is found. Tells the validation's calling
+ * process to abort.
+ */
+public class FailFastStrategy implements SchemaErrorStrategy {
+ private boolean isOK = true;
+ private String errorMsg = "No errors found.";
+
+ /* (non-Javadoc)
+ * @see org.onap.aai.edges.validation.SchemaErrorStrategy#isOK()
+ */
+ @Override
+ public boolean isOK() {
+ return isOK;
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.aai.edges.validation.SchemaErrorStrategy#getErrorMsg()
+ */
+ @Override
+ public String getErrorMsg() {
+ return errorMsg;
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.aai.edges.validation.SchemaErrorStrategy#notifyOnError(java.lang.String)
+ */
+ @Override
+ public void notifyOnError(String errorMsg) {
+ isOK = false;
+ this.errorMsg = errorMsg;
+ throw new AAISchemaValidationException(errorMsg);
+ }
+
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/NodeValidator.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/NodeValidator.java
new file mode 100644
index 0000000..e73331b
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/NodeValidator.java
@@ -0,0 +1,57 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema.validation;
+
+import org.onap.aai.schemaservice.config.ConfigTranslator;
+import org.onap.aai.schemaservice.nodeschema.SchemaVersion;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map.Entry;
+
+@Component
+public class NodeValidator {
+ private ConfigTranslator translator;
+ private SchemaErrorStrategy strat;
+ private DuplicateNodeDefinitionValidationModule dupChecker;
+
+ @Autowired
+ public NodeValidator(ConfigTranslator translator, SchemaErrorStrategy strategy, DuplicateNodeDefinitionValidationModule dupChecker) {
+ this.translator = translator;
+ this.strat = strategy;
+ this.dupChecker = dupChecker;
+ }
+
+ public boolean validate() {
+
+ for(Entry<SchemaVersion, List<String>> entry : translator.getNodeFiles().entrySet()) {
+ String result = dupChecker.findDuplicates(entry.getValue(), entry.getKey());
+ if (!"".equals(result)) {
+ strat.notifyOnError(result);
+ }
+ }
+ return strat.isOK();
+ }
+
+ public String getErrorMsg() {
+ return strat.getErrorMsg();
+ }
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/SchemaErrorStrategy.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/SchemaErrorStrategy.java
new file mode 100644
index 0000000..9df66cd
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/SchemaErrorStrategy.java
@@ -0,0 +1,58 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema.validation;
+
+/**
+ * Controls response to finding problems in the schema files.
+ */
+public interface SchemaErrorStrategy {
+ /**
+ * Gives if it is OK to proceed with whatever process
+ * invoked the validation (probably the installation of
+ * the A&AI instance).
+ *
+ * @return boolean
+ */
+ public boolean isOK();
+
+ /**
+ * Gets the error message(s) gathered in the course
+ * of validation.
+ *
+ * @return String error message or messages concatenated together
+ */
+ public String getErrorMsg();
+
+ /**
+ * Invokes the ErrorStrategy to do whatever response to
+ * an issue in the schema having been found.
+ *
+ * Options:
+ * -Throw an exception if the whole process should be
+ * immediately aborted
+ * -Set OK status to false, store the message and allow the
+ * validation process to continue and find any other issues
+ * -Completely ignore that something is wrong
+ * etc.
+ *
+ * @param String errorMsg - the error message from the validator module
+ */
+ public void notifyOnError(String errorMsg);
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/VersionValidationModule.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/VersionValidationModule.java
new file mode 100644
index 0000000..607e0df
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/VersionValidationModule.java
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema.validation;
+
+
+/**
+ * Defines the behavior for what versions are required/optional.
+ *
+ * Constructor must take ConfigTranslator via autowiring.
+ */
+public interface VersionValidationModule {
+
+ /**
+ * Validates that all required versions have schema
+ * configured for them.
+ *
+ * @return empty string if none missing or else an appropriate error
+ */
+ public String validate();
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/VersionValidator.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/VersionValidator.java
new file mode 100644
index 0000000..8394521
--- /dev/null
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/VersionValidator.java
@@ -0,0 +1,52 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. 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=========================================================
+ */
+package org.onap.aai.schemaservice.nodeschema.validation;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * Verifies that the schema config covers
+ * all required versions
+ */
+@Component
+public class VersionValidator {
+ private SchemaErrorStrategy strat;
+ private VersionValidationModule verMod;
+
+ @Autowired
+ public VersionValidator(SchemaErrorStrategy strategy, VersionValidationModule verMod) {
+ this.strat = strategy;
+ this.verMod = verMod;
+ }
+
+ public boolean validate() {
+ String result = verMod.validate();
+ if (!"".equals(result)) {
+ strat.notifyOnError(result);
+ }
+
+ return strat.isOK();
+ }
+
+ public String getErrorMsg() {
+ return strat.getErrorMsg();
+ }
+}
diff --git a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/web/JerseyConfiguration.java b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/web/JerseyConfiguration.java
index 579b9c6..606d24b 100644
--- a/aai-schema-service/src/main/java/org/onap/aai/schemaservice/web/JerseyConfiguration.java
+++ b/aai-schema-service/src/main/java/org/onap/aai/schemaservice/web/JerseyConfiguration.java
@@ -21,6 +21,7 @@
import org.glassfish.jersey.server.ResourceConfig;
import org.onap.aai.schemaservice.healthcheck.EchoResource;
+import org.onap.aai.schemaservice.nodeschema.NodeSchemaResource;
import org.onap.aai.schemaservice.versions.VersionResource;
import org.reflections.Reflections;
import org.springframework.beans.factory.annotation.Autowired;
@@ -50,6 +51,7 @@
register(VersionResource.class);
register(EchoResource.class);
+ register(NodeSchemaResource.class);
//Request Filters
registerFiltersForRequests();