From 17a7d31f50d8d2a236450fb3c6c46035524f6177 Mon Sep 17 00:00:00 2001 From: "Kajur, Harish (vk250x)" Date: Tue, 15 Jan 2019 22:46:04 -0500 Subject: Add the nodes endpoint to the schema service Issue-ID: AAI-1861 Change-Id: I33cf346f1c2a8875945631e437636f65d76a75c8 Signed-off-by: Kajur, Harish (vk250x) --- .../schemaservice/config/AAIConfigTranslator.java | 118 +++++++++ .../config/AuthorizationConfiguration.java | 39 +++ .../aai/schemaservice/config/ConfigTranslator.java | 66 +++++ .../schemaservice/config/SchemaConfiguration.java | 69 +++++ .../schemaservice/config/SchemaLocationsBean.java | 138 ++++++++++ .../aai/schemaservice/nodeschema/NodeIngestor.java | 279 +++++++++++++++++++++ .../nodeschema/NodeSchemaResource.java | 90 +++++++ .../nodeschema/NodeSchemaService.java | 92 +++++++ .../schemaservice/nodeschema/SchemaVersion.java | 84 +++++++ .../schemaservice/nodeschema/SchemaVersions.java | 158 ++++++++++++ .../validation/AAISchemaValidationException.java | 29 +++ .../validation/CheckEverythingStrategy.java | 66 +++++ ...ultDuplicateNodeDefinitionValidationModule.java | 101 ++++++++ .../validation/DefaultVersionValidationModule.java | 72 ++++++ .../DuplicateNodeDefinitionValidationModule.java | 46 ++++ .../nodeschema/validation/FailFastStrategy.java | 57 +++++ .../nodeschema/validation/NodeValidator.java | 57 +++++ .../nodeschema/validation/SchemaErrorStrategy.java | 58 +++++ .../validation/VersionValidationModule.java | 37 +++ .../nodeschema/validation/VersionValidator.java | 52 ++++ .../aai/schemaservice/web/JerseyConfiguration.java | 2 + 21 files changed, 1710 insertions(+) create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/AAIConfigTranslator.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/AuthorizationConfiguration.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/ConfigTranslator.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/SchemaConfiguration.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/config/SchemaLocationsBean.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/NodeIngestor.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/NodeSchemaResource.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/NodeSchemaService.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/SchemaVersion.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/SchemaVersions.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/AAISchemaValidationException.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/CheckEverythingStrategy.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/DefaultDuplicateNodeDefinitionValidationModule.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/DefaultVersionValidationModule.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/DuplicateNodeDefinitionValidationModule.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/FailFastStrategy.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/NodeValidator.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/SchemaErrorStrategy.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/VersionValidationModule.java create mode 100644 aai-schema-service/src/main/java/org/onap/aai/schemaservice/nodeschema/validation/VersionValidator.java 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; + +/** + * AAIConfigTranslator 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> getNodeFiles() { + + Map> files = new TreeMap<>(); + for (SchemaVersion v : schemaVersions.getVersions()) { + List container = getVersionNodeFiles(v); + files.put(v, container); + } + + return files; + } + + + private List 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> getEdgeFiles() { + + Map> files = new TreeMap<>(); + for (SchemaVersion v : schemaVersions.getVersions()) { + List container = getVersionEdgeFiles(v); + files.put(v, container); + } + + return files; + } + + private List getVersionEdgeFiles(SchemaVersion v) { + + return getVersionFiles( + bean.getEdgeDirectory(), + v, + () -> bean.getEdgesInclusionPattern().stream(), + () -> bean.getEdgesExclusionPattern().stream() + ); + } + + private List getVersionFiles( + String startDirectory, + SchemaVersion schemaVersion, + Supplier> inclusionPattern, + Supplier> exclusionPattern + ){ + + List 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> 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> 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 nodesInclusionPattern; + + @Value("${schema.nodes.exclusion.list:}#{T(java.util.Collections).emptyList()}") + private List nodesExclusionPattern; + + @Value("${schema.edges.inclusion.list:}#{T(java.util.Arrays).asList(\"DbEdgeRules_.*.json\")}") + private List edgesInclusionPattern; + + @Value("${schema.edges.exclusion.list:}#{T(java.util.Collections).emptyList()}") + private List 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 getNodesExclusionPattern(){ + return this.nodesExclusionPattern; + } + + public List getNodesInclusionPattern(){ + return this.nodesInclusionPattern; + } + + public List getEdgesExclusionPattern(){ + return this.edgesExclusionPattern; + } + + public List 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 versionContextMap = new TreeMap<>(); + private Map> typesPerVersion = new TreeMap<>(); + private Map 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> filesToIngest = translator.getNodeFiles(); + + try { + for (Entry> verFiles : filesToIngest.entrySet()) { + SchemaVersion v = verFiles.getKey(); + List 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 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 files) throws FileNotFoundException, JAXBException { + List streams = new ArrayList<>(); + + for (String name : files) { + streams.add(new FileInputStream(new File(name))); + } + + Map properties = new HashMap<>(); + properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, streams); + return DynamicJAXBContextFactory.createContextFromOXM(this.getClass().getClassLoader(), properties); + } + + + private Set getAllNodeTypes(List files) throws ParserConfigurationException, SAXException, IOException { + Set types = new HashSet<>(); + final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + docFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + final DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + + ArrayList 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 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 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> 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> map){ + + for (Entry> entry : map.entrySet()) { + + List listOfNodes = (List)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 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 = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + 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 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 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 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 { + + 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 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 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 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 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 files, SchemaVersion v) { + try { + final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + docFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + final DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + + Multimap 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 types, SchemaVersion v) { + StringBuilder errorMsg = new StringBuilder().append("Duplicates found in version ").append(v.toString()).append(". "); + for (String nodeType : types.keySet()) { + Collection 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> nodeConfig = config.getNodeFiles(); + Map> 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 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> 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 @@ package org.onap.aai.schemaservice.web; 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 @@ public class JerseyConfiguration extends ResourceConfig { register(VersionResource.class); register(EchoResource.class); + register(NodeSchemaResource.class); //Request Filters registerFiltersForRequests(); -- cgit 1.2.3-korg