diff options
Diffstat (limited to 'aai-core')
22 files changed, 1402 insertions, 308 deletions
diff --git a/aai-core/pom.xml b/aai-core/pom.xml index 70a03185..a482b972 100644 --- a/aai-core/pom.xml +++ b/aai-core/pom.xml @@ -27,11 +27,11 @@ <parent> <groupId>org.onap.aai.aai-common</groupId> <artifactId>aai-common</artifactId> - <version>1.3.1-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> </parent> <artifactId>aai-core</artifactId> <name>aai-core</name> - <version>1.3.1-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <sonar.language>java</sonar.language> @@ -53,7 +53,7 @@ <!-- Start of Default ONAP Schema Properties --> <aai.wiki.link>https://wiki.onap.org/</aai.wiki.link> - <gendoc.version>v14</gendoc.version> + <gendoc.version>v15</gendoc.version> <aai.release>onap</aai.release> <schema.uri.base.path>/aai</schema.uri.base.path> <schema.configuration.location>N/A</schema.configuration.location> @@ -64,8 +64,8 @@ <schema.version.app.root.start>v11</schema.version.app.root.start> <schema.version.namespace.change.start>v12</schema.version.namespace.change.start> <schema.version.edge.label.start>v12</schema.version.edge.label.start> - <schema.version.api.default>v14</schema.version.api.default> - <schema.version.list>v8,v9,v10,v11,v12,v13,v14</schema.version.list> + <schema.version.api.default>v15</schema.version.api.default> + <schema.version.list>v8,v9,v10,v11,v12,v13,v14,v15</schema.version.list> <!-- End of Default ONAP Schema Properties --> </properties> <profiles> @@ -82,9 +82,9 @@ <schema.version.app.root.start>v11</schema.version.app.root.start> <schema.version.edge.label.start>v12</schema.version.edge.label.start> <schema.version.namespace.change.start>v12</schema.version.namespace.change.start> - <schema.version.api.default>v14</schema.version.api.default> - <schema.version.list>v8,v9,v10,v11,v12,v13,v14</schema.version.list> - <gendoc.version>v14</gendoc.version> + <schema.version.api.default>v15</schema.version.api.default> + <schema.version.list>v8,v9,v10,v11,v12,v13,v14,v15</schema.version.list> + <gendoc.version>v15</gendoc.version> </properties> </profile> <!-- End of ONAP profile --> @@ -987,6 +987,12 @@ <groupId>org.apache.tinkerpop</groupId> <artifactId>gremlin-groovy</artifactId> <version>${gremlin.version}</version> + <exclusions> + <exclusion> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> diff --git a/aai-core/src/main/java/org/onap/aai/config/SwaggerGenerationConfiguration.java b/aai-core/src/main/java/org/onap/aai/config/SwaggerGenerationConfiguration.java index fbbb703a..9aae5a62 100644 --- a/aai-core/src/main/java/org/onap/aai/config/SwaggerGenerationConfiguration.java +++ b/aai-core/src/main/java/org/onap/aai/config/SwaggerGenerationConfiguration.java @@ -37,25 +37,31 @@ import org.springframework.context.annotation.Scope; @Configuration public class SwaggerGenerationConfiguration { - @Value("${schema.uri.base.path}") - private String basePath; + @Value("${schema.uri.base.path}") + private String basePath; - @Bean - @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public NodesYAMLfromOXM nodesYamlFromOXM(SchemaVersions schemaVersions, NodeIngestor nodeIngestor, EdgeIngestor edgeIngestor) { - return new NodesYAMLfromOXM(basePath, schemaVersions, nodeIngestor, edgeIngestor); - } - - @Bean - @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public HTMLfromOXM htmlFromOXM(SchemaVersions schemaVersions, NodeIngestor nodeIngestor, EdgeIngestor edgeIngestor) { - return new HTMLfromOXM(schemaVersions, nodeIngestor, edgeIngestor); - } - - @Bean - @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public YAMLfromOXM yamlFromOXM(SchemaVersions schemaVersions, NodeIngestor nodeIngestor, EdgeIngestor edgeIngestor) { - return new YAMLfromOXM(basePath, schemaVersions, nodeIngestor, edgeIngestor); - } + @Value("${schema.xsd.maxoccurs:5000}") + private String maxOccurs; + + @Bean + @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public NodesYAMLfromOXM nodesYamlFromOXM(SchemaVersions schemaVersions, NodeIngestor nodeIngestor, EdgeIngestor edgeIngestor) { + NodesYAMLfromOXM nodesYamlFromOXM = new NodesYAMLfromOXM(basePath, schemaVersions, nodeIngestor, edgeIngestor); + return nodesYamlFromOXM; + } + + @Bean + @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public HTMLfromOXM htmlFromOXM(SchemaVersions schemaVersions, NodeIngestor nodeIngestor, EdgeIngestor edgeIngestor) { + HTMLfromOXM htmlFromOXM = new HTMLfromOXM(maxOccurs, schemaVersions, nodeIngestor, edgeIngestor); + return htmlFromOXM; + } + + @Bean + @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public YAMLfromOXM yamlFromOXM(SchemaVersions schemaVersions, NodeIngestor nodeIngestor, EdgeIngestor edgeIngestor) { + YAMLfromOXM yamlFromOXM = new YAMLfromOXM(basePath, schemaVersions, nodeIngestor, edgeIngestor); + return yamlFromOXM; + } } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java b/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java index e8c03bdd..7a2c447e 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java @@ -96,6 +96,7 @@ public class DBSerializer { private final Loader loader; private final String baseURL; private double dbTimeMsecs = 0; + private long currentTimeMillis; private SchemaVersions schemaVersions; /** @@ -117,6 +118,7 @@ public class DBSerializer { this.version = version; this.loader = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, version); this.baseURL = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE); + this.currentTimeMillis = System.currentTimeMillis(); initBeans(); } @@ -156,14 +158,14 @@ public class DBSerializer { * @param isNewVertex the is new vertex */ public void touchStandardVertexProperties(Vertex v, boolean isNewVertex) { - - String timeNowInSec = Long.toString(System.currentTimeMillis()); + String timeNowInSec = Long.toString(currentTimeMillis); + if (isNewVertex) { v.property(AAIProperties.SOURCE_OF_TRUTH, this.sourceOfTruth); v.property(AAIProperties.CREATED_TS, timeNowInSec); v.property(AAIProperties.AAI_UUID, UUID.randomUUID().toString()); } - v.property(AAIProperties.RESOURCE_VERSION, timeNowInSec ); + v.property(AAIProperties.RESOURCE_VERSION, timeNowInSec); v.property(AAIProperties.LAST_MOD_TS, timeNowInSec); v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, this.sourceOfTruth); diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Format.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Format.java index abd261ed..7e7356fe 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Format.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/Format.java @@ -31,7 +31,8 @@ public enum Format { resource_and_url, console, raw, - count; + count, + resource_with_sot; public static Format getFormat(String format) throws AAIException { try { diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/FormatFactory.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/FormatFactory.java index 29ae8512..f36941f8 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/FormatFactory.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/FormatFactory.java @@ -83,6 +83,9 @@ public class FormatFactory { case count : formatter = new Formatter(inject(new Count(), params)); break; + case resource_with_sot : + formatter = new Formatter(inject(new ResourceWithSoT.Builder(loader, serializer, urlBuilder), params).build()); + break; default : break; diff --git a/aai-core/src/main/java/org/onap/aai/serialization/queryformats/ResourceWithSoT.java b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/ResourceWithSoT.java new file mode 100644 index 00000000..503f3a58 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/serialization/queryformats/ResourceWithSoT.java @@ -0,0 +1,166 @@ +/** + * ============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.serialization.queryformats; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.onap.aai.db.props.AAIProperties; +import org.onap.aai.introspection.Loader; +import org.onap.aai.serialization.db.DBSerializer; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import org.onap.aai.serialization.queryformats.params.Depth; +import org.onap.aai.serialization.queryformats.params.NodesOnly; +import org.onap.aai.serialization.queryformats.utils.UrlBuilder; +import org.onap.aai.util.AAIConfig; + +import java.util.Optional; + +public class ResourceWithSoT extends MultiFormatMapper { + protected JsonParser parser = new JsonParser(); + protected final DBSerializer serializer; + protected final Loader loader; + protected final UrlBuilder urlBuilder; + protected final int depth; + protected final boolean nodesOnly; + protected ResourceWithSoT(Builder builder) { + this.urlBuilder = builder.getUrlBuilder(); + this.loader = builder.getLoader(); + this.serializer = builder.getSerializer(); + this.depth = builder.getDepth(); + this.nodesOnly = builder.isNodesOnly(); + } + + @Override + public int parallelThreshold() { + return 100; + } + + public static class Builder implements NodesOnly<Builder>, Depth<Builder> { + + protected final Loader loader; + protected final DBSerializer serializer; + protected final UrlBuilder urlBuilder; + protected boolean includeUrl = false; + protected boolean nodesOnly = false; + protected int depth = 1; + protected boolean modelDriven = false; + public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) { + this.loader = loader; + this.serializer = serializer; + this.urlBuilder = urlBuilder; + } + + protected Loader getLoader() { + return this.loader; + } + + protected DBSerializer getSerializer() { + return this.serializer; + } + + protected UrlBuilder getUrlBuilder() { + return this.urlBuilder; + } + + public Builder includeUrl() { + this.includeUrl = true; + return this; + } + + public Builder nodesOnly(Boolean nodesOnly) { + this.nodesOnly = nodesOnly; + return this; + } + public boolean isNodesOnly() { + return this.nodesOnly; + } + + public Builder depth(Integer depth) { + this.depth = depth; + return this; + } + + public int getDepth() { + return this.depth; + } + + public boolean isIncludeUrl() { + return this.includeUrl; + } + + public Builder modelDriven() { + this.modelDriven = true; + return this; + } + + public boolean getModelDriven() { + return this.modelDriven; + } + public ResourceWithSoT build() { + return new ResourceWithSoT(this); + } + } + + /** + * + * Returns an Optional<JsonObject> to convert the contents from the given Vertex object into a JsonObject. + * The fields returned are to record the time stamp of the creation/modification of the object, the user responsible for + * the change, and the last http method performed on the object. + * + * @param v + * @return + * @throws AAIFormatVertexException + */ + @Override + protected Optional<JsonObject> getJsonFromVertex(Vertex v) throws AAIFormatVertexException { + // Null check + if (v == null) + return null; + + JsonObject json = new JsonObject(); + + Object createdTimestampObj = v.property(AAIProperties.CREATED_TS).value(); + Object lastModifiedTimestampObj = v.property(AAIProperties.LAST_MOD_TS).value(); + Object sotObj = v.property(AAIProperties.SOURCE_OF_TRUTH).value(); + Object lastModSotObj = v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value(); + long createdTimestamp = Long.valueOf(createdTimestampObj.toString()); + long lastModifiedTimestamp = Long.valueOf(lastModifiedTimestampObj.toString()); + long threshold = Long.valueOf(AAIConfig.get("aai.resource.format.threshold", "10")); + + // Add to the property field of the JSON payload + json.addProperty("aai-created-ts", createdTimestampObj.toString()); + json.addProperty("aai-last-mod-ts", lastModifiedTimestampObj.toString()); + json.addProperty("source-of-truth", sotObj.toString()); + json.addProperty("last-mod-source-of-truth", lastModSotObj.toString()); + + // Check if the timestamp difference between creation and last modification are greater than a certain threshold, and if the source of truth differs + // If the timestamp difference is marginal and the SoT (creator/modifier) is the same, the last action performed is likely to be a creation. + long timestampDiff = lastModifiedTimestamp - createdTimestamp; + boolean isSameSoT = sotObj.toString().equals(lastModSotObj.toString()); + + if (timestampDiff <= threshold && isSameSoT) + json.addProperty("last-action-performed", "Created"); + else + json.addProperty("last-action-performed", "Modified"); + + return Optional.of(json); + } +} diff --git a/aai-core/src/main/java/org/onap/aai/util/GenerateXsd.java b/aai-core/src/main/java/org/onap/aai/util/GenerateXsd.java index d94457e5..84f06064 100644 --- a/aai-core/src/main/java/org/onap/aai/util/GenerateXsd.java +++ b/aai-core/src/main/java/org/onap/aai/util/GenerateXsd.java @@ -236,6 +236,7 @@ public class GenerateXsd { logger.error( "Exception creating output file " + outfileName); logger.error( e.getMessage()); e.printStackTrace(); + System.exit(-1); } } else if ( versionSupportsSwagger(apiVersion )) { outfileName = yaml_dir + "/aai_swagger_" + apiVersion + "." + generateTypeYAML; @@ -244,8 +245,10 @@ public class GenerateXsd { YAMLfromOXM swagger = (YAMLfromOXM) ctx.getBean(YAMLfromOXM.class); swagger.setVersion(v); fileContent = swagger.process(); + Map combinedJavaTypes = swagger.getCombinedJavaTypes(); NodesYAMLfromOXM nodesSwagger = ctx.getBean(NodesYAMLfromOXM.class); nodesSwagger.setVersion(v); + nodesSwagger.setCombinedJavaTypes(combinedJavaTypes); nodesContent = nodesSwagger.process(); } catch(Exception e) { logger.error( "Exception creating output file " + outfileName); diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/HTMLfromOXM.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/HTMLfromOXM.java index cba65daa..7d3b37d1 100644 --- a/aai-core/src/main/java/org/onap/aai/util/genxsd/HTMLfromOXM.java +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/HTMLfromOXM.java @@ -22,6 +22,9 @@ package org.onap.aai.util.genxsd; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import javax.xml.parsers.ParserConfigurationException; @@ -46,10 +49,11 @@ public class HTMLfromOXM extends OxmFileProcessor { private static final Logger logger = LoggerFactory.getLogger("HTMLfromOXM.class"); + private String maxOccurs; - - public HTMLfromOXM(SchemaVersions schemaVersions, NodeIngestor ni, EdgeIngestor ei ){ + public HTMLfromOXM(String maxOccurs, SchemaVersions schemaVersions, NodeIngestor ni, EdgeIngestor ei ){ super(schemaVersions, ni,ei); + this.maxOccurs = maxOccurs; } public void setOxmVersion(File oxmFile, SchemaVersion v) { super.setOxmVersion(oxmFile, v); @@ -69,7 +73,7 @@ public class HTMLfromOXM extends OxmFileProcessor { public String getDocumentHeader() { StringBuffer sb = new StringBuffer(); logger.trace("processing starts"); - sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"); + sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + LINE_SEPARATOR); String namespace = "org.onap"; if (v.compareTo(getSchemaVersions().getNamespaceChangeVersion()) < 0 ) { namespace = "org.openecomp"; @@ -77,14 +81,14 @@ public class HTMLfromOXM extends OxmFileProcessor { if ( versionUsesAnnotations(v.toString()) ) { sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/" + v.toString() + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + v.toString() + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" - + "\n" - + "xmlns:jaxb=\"http://java.sun.com/xml/ns/jaxb\"\r\n" + - " jaxb:version=\"2.1\"\r\n" + - " xmlns:annox=\"http://annox.dev.java.net\"\r\n" + - " jaxb:extensionBindingPrefixes=\"annox\">\n\n"); + + LINE_SEPARATOR + + "xmlns:jaxb=\"http://java.sun.com/xml/ns/jaxb\"" + LINE_SEPARATOR + + " jaxb:version=\"2.1\"" + LINE_SEPARATOR + + " xmlns:annox=\"http://annox.dev.java.net\"" + LINE_SEPARATOR + + " jaxb:extensionBindingPrefixes=\"annox\">" + DOUBLE_LINE_SEPARATOR); } else { sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/" - + v.toString() + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + v.toString() + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n\n"); + + v.toString() + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + v.toString() + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">" + DOUBLE_LINE_SEPARATOR); } return sb.toString(); } @@ -92,6 +96,7 @@ public class HTMLfromOXM extends OxmFileProcessor { @Override public String process() throws ParserConfigurationException, SAXException, IOException, AAIException, FileNotFoundException, EdgeRuleNotFoundException { StringBuilder sb = new StringBuilder(); + try { init(); } catch(Exception e) { @@ -100,9 +105,21 @@ public class HTMLfromOXM extends OxmFileProcessor { } sb.append(getDocumentHeader()); StringBuilder sbInventory = new StringBuilder(); + Element elem; + String javaTypeName; + combinedJavaTypes = new HashMap(); for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { - XSDElement javaTypeElement = new XSDElement((Element)javaTypeNodes.item(i)); - String javaTypeName = javaTypeElement.name(); + elem = (Element)javaTypeNodes.item(i); + javaTypeName = elem.getAttribute("name"); + if ( !"Inventory".equals(javaTypeName ) ) { + if ( generatedJavaType.containsKey(javaTypeName) ) { + continue; + } + // will combine all matching java-types + elem = getJavaTypeElement(javaTypeName,false ); + } + XSDElement javaTypeElement = new XSDElement(elem, maxOccurs); + //javaTypeName = javaTypeElement.name(); if ( javaTypeName == null ) { String msg = "Invalid OXM file: <java-type> has no name attribute in " + oxmFile; logger.error(msg); @@ -112,26 +129,38 @@ public class HTMLfromOXM extends OxmFileProcessor { logger.debug("skipping Nodes entry (temporary feature)"); continue; } - //Skip any type that has already been processed(recursion could be the reason) logger.debug(getXmlRootElementName(javaTypeName)+" vs "+ javaTypeName+":"+generatedJavaType.containsKey(getXmlRootElementName(javaTypeName))); - if ( generatedJavaType.containsKey(javaTypeName) ) { - continue; - } + if ( !"Inventory".equals(javaTypeName)) { generatedJavaType.put(javaTypeName, null); } sb.append(processJavaTypeElement( javaTypeName, javaTypeElement, sbInventory )); } sb.append(sbInventory); - sb.append(" </xs:sequence>\n"); - sb.append(" </xs:complexType>\n"); - sb.append(" </xs:element>\n"); - sb.append("</xs:schema>\n"); + sb.append(" </xs:sequence>" + LINE_SEPARATOR); + sb.append(" </xs:complexType>" + LINE_SEPARATOR); + sb.append(" </xs:element>" + LINE_SEPARATOR); + sb.append("</xs:schema>" + LINE_SEPARATOR); return sb.toString(); } + + protected boolean isValidName( String name ) { + if ( name == null || name.length() == 0 ) { + return false; + } + String pattern = "^[a-z0-9-]*$"; + return name.matches(pattern); + } + + protected boolean skipCheck( String javaAttribute ) { + if ( javaAttribute.equals("model") + || javaAttribute.equals("eventHeader") ) { + return true; + } + return false; + } public String processJavaTypeElement( String javaTypeName, Element javaType_Element, StringBuilder sbInventory) { - String xmlRootElementName = getXMLRootElementName(javaType_Element); NodeList parentNodes = javaType_Element.getElementsByTagName("java-attributes"); @@ -157,19 +186,20 @@ public class HTMLfromOXM extends OxmFileProcessor { if ( xmlElementNodes.getLength() > 0 ) { if ( !processingInventory || !hasPreviousInventory ) { - sb1.append(" <xs:element name=\"" + xmlRootElementName + "\">\n"); - sb1.append(" <xs:complexType>\n"); + sb1.append(" <xs:element name=\"" + xmlRootElementName + "\">" + LINE_SEPARATOR); + sb1.append(" <xs:complexType>" + LINE_SEPARATOR); - XSDElement javaTypeElement = new XSDElement(javaType_Element); + XSDElement javaTypeElement = new XSDElement(javaType_Element, maxOccurs); logger.debug("XSDElement name: "+javaTypeElement.name()); if(versionUsesAnnotations(v.toString())) { sb1.append(javaTypeElement.getHTMLAnnotation("class", " ")); } - sb1.append(" <xs:sequence>\n"); + sb1.append(" <xs:sequence>" + LINE_SEPARATOR); } + Element javatypeElement; for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) { - XSDElement xmlElementElement = new XSDElement((Element)xmlElementNodes.item(i)); + XSDElement xmlElementElement = new XSDElement((Element)xmlElementNodes.item(i), maxOccurs); // String elementName = xmlElementElement.getAttribute("name"); String elementType = xmlElementElement.getAttribute("type"); @@ -177,7 +207,8 @@ public class HTMLfromOXM extends OxmFileProcessor { String addType = elementType.contains("." + v.toString() + ".") ? elementType.substring(elementType.lastIndexOf('.')+1) : null; if ( elementType.contains("." + v.toString() + ".") && !generatedJavaType.containsKey(addType) ) { generatedJavaType.put(addType, elementType); - sb.append(processJavaTypeElement( addType, getJavaTypeElement(addType), null )); + javatypeElement = getJavaTypeElement(addType, processingInventory); + sb.append(processJavaTypeElement( addType, javatypeElement, null )); } if ("Nodes".equals(addType)) { logger.trace("Skipping nodes, temporary testing"); @@ -187,18 +218,18 @@ public class HTMLfromOXM extends OxmFileProcessor { sb1.append(xmlElementElement.getHTMLElement(v, versionUsesAnnotations(v.toString()), this)); } if ( !processingInventory ) { - sb1.append(" </xs:sequence>\n"); - sb1.append(" </xs:complexType>\n"); - sb1.append(" </xs:element>\n"); + sb1.append(" </xs:sequence>" + LINE_SEPARATOR); + sb1.append(" </xs:complexType>" + LINE_SEPARATOR); + sb1.append(" </xs:element>" + LINE_SEPARATOR); } } if ( xmlElementNodes.getLength() < 1 ) { - sb.append(" <xs:element name=\"" + xmlRootElementName + "\">\n"); - sb.append(" <xs:complexType>\n"); - sb.append(" <xs:sequence/>\n"); - sb.append(" </xs:complexType>\n"); - sb.append(" </xs:element>\n"); + sb.append(" <xs:element name=\"" + xmlRootElementName + "\">" + LINE_SEPARATOR); + sb.append(" <xs:complexType>" + LINE_SEPARATOR); + sb.append(" <xs:sequence/>" + LINE_SEPARATOR); + sb.append(" </xs:complexType>" + LINE_SEPARATOR); + sb.append(" </xs:element>" + LINE_SEPARATOR); generatedJavaType.put(javaTypeName, null); return sb.toString(); } @@ -210,11 +241,13 @@ public class HTMLfromOXM extends OxmFileProcessor { return sb.toString(); } - private Element getJavaTypeElement( String javaTypeName ) + private Element getJavaTypeElement( String javaTypeName, boolean processingInventory ) { String attrName, attrValue; Attr attr; Element javaTypeElement; + + List<Element> combineElementList = new ArrayList<Element>(); for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { javaTypeElement = (Element) javaTypeNodes.item(i); NamedNodeMap attributes = javaTypeElement.getAttributes(); @@ -222,12 +255,24 @@ public class HTMLfromOXM extends OxmFileProcessor { attr = (Attr) attributes.item(j); attrName = attr.getNodeName(); attrValue = attr.getNodeValue(); - if ( attrName.equals("name") && attrValue.equals(javaTypeName)) - return javaTypeElement; + if ( attrName.equals("name") && attrValue.equals(javaTypeName)) { + if ( processingInventory ) { + return javaTypeElement; + } else { + combineElementList.add(javaTypeElement); + } + } } } - logger.error( "oxm file format error, missing java-type " + javaTypeName); - return (Element) null; + if ( combineElementList.size() == 0 ) { + logger.error( "oxm file format error, missing java-type " + javaTypeName); + return (Element) null; + } else if ( combineElementList.size() > 1 ) { + // need to combine java-attributes + return combineElements( javaTypeName, combineElementList); + } + return combineElementList.get(0); + } private boolean versionUsesAnnotations( String version) { @@ -240,4 +285,4 @@ public class HTMLfromOXM extends OxmFileProcessor { } return false; } -}
\ No newline at end of file +} diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/NodesYAMLfromOXM.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/NodesYAMLfromOXM.java index 5c4cd8bd..0b89ce10 100644 --- a/aai-core/src/main/java/org/onap/aai/util/genxsd/NodesYAMLfromOXM.java +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/NodesYAMLfromOXM.java @@ -117,9 +117,21 @@ public class NodesYAMLfromOXM extends OxmFileProcessor { } pathSb.append(getDocumentHeader()); StringBuffer definitionsSb = new StringBuffer(); + Element elem; + String javaTypeName; for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { - XSDElement javaTypeElement = new XSDElement((Element)javaTypeNodes.item(i)); - String javaTypeName = javaTypeElement.name(); + elem = (Element)javaTypeNodes.item(i); + javaTypeName = elem.getAttribute("name"); + if ( !"Inventory".equals(javaTypeName ) ) { + if ( generatedJavaType.containsKey(javaTypeName) ) { + continue; + } + // will combine all matching java-types + elem = getJavaTypeElementSwagger(javaTypeName ); + } + + XSDElement javaTypeElement = new XSDElement(elem); + logger.debug("External: "+javaTypeElement.getAttribute("name")+"/"+getXmlRootElementName(javaTypeName)); if ( javaTypeName == null ) { @@ -128,10 +140,7 @@ public class NodesYAMLfromOXM extends OxmFileProcessor { throw new AAIException(msg); } namespaceFilter.add(getXmlRootElementName(javaTypeName)); - //Skip any type that has already been processed(recursion could be the reason) - if ( generatedJavaType.containsKey(getXmlRootElementName(javaTypeName)) ) { - continue; - } + processJavaTypeElementSwagger( javaTypeName, javaTypeElement, pathSb, definitionsSb, null, null, null, null, null, null); } @@ -491,7 +500,8 @@ public class NodesYAMLfromOXM extends OxmFileProcessor { } Path path = Paths.get(outfileName); Charset charset = Charset.forName("UTF-8"); - try(BufferedWriter bw = Files.newBufferedWriter(path, charset);) { + try { + BufferedWriter bw = Files.newBufferedWriter(path, charset); bw.write(fileContent); if ( bw != null ) { bw.close(); diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/OxmFileProcessor.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/OxmFileProcessor.java index 391142cc..a758be50 100644 --- a/aai-core/src/main/java/org/onap/aai/util/genxsd/OxmFileProcessor.java +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/OxmFileProcessor.java @@ -23,6 +23,8 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -34,6 +36,13 @@ import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException; @@ -46,12 +55,17 @@ import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import org.xml.sax.InputSource; public abstract class OxmFileProcessor { + + public static final String LINE_SEPARATOR = System.getProperty("line.separator"); + public static final String DOUBLE_LINE_SEPARATOR = System.getProperty("line.separator") + System.getProperty("line.separator"); + EdgeIngestor ei; NodeIngestor ni; protected Set<String> namespaceFilter; @@ -62,6 +76,8 @@ public abstract class OxmFileProcessor { protected String apiVersion = null; protected SchemaVersions schemaVersions; + protected Map combinedJavaTypes; + protected static int annotationsStartVersion = 9; // minimum version to support annotations in xsd protected static int annotationsMinVersion = 6; // lower versions support annotations in xsd @@ -248,12 +264,22 @@ public abstract class OxmFileProcessor { return null; } + public Map getCombinedJavaTypes() { + return combinedJavaTypes; + } + + public void setCombinedJavaTypes(Map combinedJavaTypes) { + this.combinedJavaTypes = combinedJavaTypes; + } + public Element getJavaTypeElementSwagger( String javaTypeName ) { String attrName, attrValue; Attr attr; Element javaTypeElement; + + List<Element> combineElementList = new ArrayList<Element>(); for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { javaTypeElement = (Element) javaTypeNodes.item(i); NamedNodeMap attributes = javaTypeElement.getAttributes(); @@ -261,11 +287,18 @@ public abstract class OxmFileProcessor { attr = (Attr) attributes.item(j); attrName = attr.getNodeName(); attrValue = attr.getNodeValue(); - if ( attrName.equals("name") && attrValue.equals(javaTypeName)) - return javaTypeElement; + if ( attrName.equals("name") && attrValue.equals(javaTypeName)) { + combineElementList.add(javaTypeElement); + } } } - return (Element) null; + if ( combineElementList.size() == 0 ) { + return (Element) null; + } else if ( combineElementList.size() > 1 ) { + // need to combine java-attributes + return combineElements( javaTypeName, combineElementList); + } + return combineElementList.get(0); } public boolean versionSupportsSwaggerDiff( String version) { @@ -284,4 +317,211 @@ public abstract class OxmFileProcessor { return false; } + protected void updateParentXmlElements(Element parentElement, NodeList moreXmlElementNodes) { + Element xmlElement; + NodeList childNodes; + Node childNode; + + Node refChild = null; + // find childNode with attributes and no children, insert children before that node + childNodes = parentElement.getChildNodes(); + if ( childNodes == null || childNodes.getLength() == 0 ) { + // should not happen since the base parent was chosen if it had children + return; + } + + for ( int i = 0; i < childNodes.getLength(); ++i ) { + refChild = childNodes.item(i); + if ( refChild.hasAttributes() && !refChild.hasChildNodes()) { + break; + } + + } + + for ( int i = 0; i < moreXmlElementNodes.getLength(); ++i ) { + xmlElement = (Element)moreXmlElementNodes.item(i); + childNode = xmlElement.cloneNode(true); + parentElement.insertBefore(childNode, refChild); + } + } + + protected Node getXmlPropertiesNode(Element javaTypeElement ) { + NodeList nl = javaTypeElement.getChildNodes(); + Node child; + for ( int i = 0; i < nl.getLength(); ++i ) { + child = nl.item(i); + if ( "xml-properties".equals(child.getNodeName())) { + return child; + } + } + return null; + } + + protected Node merge( NodeList nl, Node mergeNode ) { + NamedNodeMap nnm = mergeNode.getAttributes(); + Node childNode; + NamedNodeMap childNnm; + + String mergeName = nnm.getNamedItem("name").getNodeValue(); + String mergeValue = nnm.getNamedItem("value").getNodeValue(); + String childName; + String childValue; + for ( int j = 0; j < nl.getLength(); ++j ) { + childNode = nl.item(j); + if ( "xml-property".equals(childNode.getNodeName())) { + childNnm = childNode.getAttributes(); + childName = childNnm.getNamedItem("name").getNodeValue(); + childValue = childNnm.getNamedItem("value").getNodeValue(); + if ( childName.equals(mergeName)) { + // attribute exists + // keep, replace or update + if ( childValue.contains(mergeValue) ) { + return null; + } + if ( mergeValue.contains(childValue) ) { + childNnm.getNamedItem("value").setTextContent(mergeValue); + return null; + } + childNnm.getNamedItem("value").setTextContent(mergeValue + "," + childValue); + return null; + } + } + } + childNode = mergeNode.cloneNode(true); + return childNode; + } + + protected void mergeXmlProperties(Node useChildProperties, NodeList propertiesToMerge ) { + NodeList nl = useChildProperties.getChildNodes(); + Node childNode; + Node newNode; + for ( int i = 0; i < propertiesToMerge.getLength(); ++i ) { + childNode = propertiesToMerge.item(i); + if ( "xml-property".equals(childNode.getNodeName()) ) { + newNode = merge(nl, childNode); + if ( newNode != null ) { + useChildProperties.appendChild(newNode); + } + } + + } + } + + protected void combineXmlProperties(int useElement, List<Element> combineElementList) { + // add or update xml-properties to the referenced element from the combined list + Element javaTypeElement = combineElementList.get(useElement); + NodeList nl = javaTypeElement.getChildNodes(); + Node useChildProperties = getXmlPropertiesNode( javaTypeElement); + int cloneChild = -1; + Node childProperties; + if ( useChildProperties == null ) { + // find xml-properties to clone + for ( int i = 0; i < combineElementList.size(); ++i ) { + if ( i == useElement ) { + continue; + } + childProperties = getXmlPropertiesNode(combineElementList.get(i)); + if ( childProperties != null ) { + useChildProperties = childProperties.cloneNode(true); + javaTypeElement.appendChild(useChildProperties); + cloneChild = i; + } + } + } + NodeList cnl; + // find other xml-properties + for ( int i = 0; i < combineElementList.size(); ++i ) { + if ( i == useElement|| ( cloneChild >= 0 && i <= cloneChild )) { + continue; + } + childProperties = getXmlPropertiesNode(combineElementList.get(i)); + if ( childProperties == null ) { + continue; + } + cnl = childProperties.getChildNodes(); + mergeXmlProperties( useChildProperties, cnl); + } + + } + + protected Element combineElements( String javaTypeName, List<Element> combineElementList ) { + Element javaTypeElement; + NodeList parentNodes; + Element parentElement = null; + NodeList xmlElementNodes; + + int useElement = -1; + if ( combinedJavaTypes.containsKey( javaTypeName) ) { + return combineElementList.get((int)combinedJavaTypes.get(javaTypeName)); + } + for ( int i = 0; i < combineElementList.size(); ++i ) { + javaTypeElement = combineElementList.get(i); + parentNodes = javaTypeElement.getElementsByTagName("java-attributes"); + if ( parentNodes.getLength() == 0 ) { + continue; + } + parentElement = (Element)parentNodes.item(0); + xmlElementNodes = parentElement.getElementsByTagName("xml-element"); + if ( xmlElementNodes.getLength() <= 0 ) { + continue; + } + useElement = i; + break; + } + boolean doCombineElements = true; + if ( useElement < 0 ) { + useElement = 0; + doCombineElements = false; + } else if ( useElement == combineElementList.size() - 1) { + doCombineElements = false; + } + if ( doCombineElements ) { + // get xml-element from other javaTypeElements + Element otherParentElement = null; + for ( int i = 0; i < combineElementList.size(); ++i ) { + if ( i == useElement ) { + continue; + } + javaTypeElement = combineElementList.get(i); + parentNodes = javaTypeElement.getElementsByTagName("java-attributes"); + if ( parentNodes.getLength() == 0 ) { + continue; + } + otherParentElement = (Element)parentNodes.item(0); + xmlElementNodes = otherParentElement.getElementsByTagName("xml-element"); + if ( xmlElementNodes.getLength() <= 0 ) { + continue; + } + // xml-element that are not present + updateParentXmlElements( parentElement, xmlElementNodes); + + } + } + // need to combine xml-properties + combineXmlProperties(useElement, combineElementList ); + combinedJavaTypes.put( javaTypeName, useElement); + return combineElementList.get(useElement); + } + + + private static void prettyPrint(Node node, String tab) + { + // for debugging + try { + // Set up the output transformer + TransformerFactory transfac = TransformerFactory.newInstance(); + Transformer trans = transfac.newTransformer(); + trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + trans.setOutputProperty(OutputKeys.INDENT, "yes"); + StringWriter sw = new StringWriter(); + StreamResult result = new StreamResult(sw); + DOMSource source = new DOMSource(node); + trans.transform(source, result); + String xmlString = sw.toString(); + System.out.println(xmlString); + } + catch (TransformerException e) { + e.printStackTrace(); + } + } } diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/XSDElement.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/XSDElement.java index f9ce7c11..9de7967e 100644 --- a/aai-core/src/main/java/org/onap/aai/util/genxsd/XSDElement.java +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/XSDElement.java @@ -40,16 +40,25 @@ import com.google.common.base.Joiner; public class XSDElement implements Element { Element xmlElementElement; + String maxOccurs; private static final int VALUE_NONE = 0; private static final int VALUE_DESCRIPTION = 1; private static final int VALUE_INDEXED_PROPS = 2; private static final int VALUE_CONTAINER = 3; private static final int VALUE_REQUIRES = 4; + public XSDElement(Element xmlElementElement, String maxOccurs) { + super(); + this.xmlElementElement = xmlElementElement; + this.maxOccurs = maxOccurs; + } + public XSDElement(Element xmlElementElement) { super(); this.xmlElementElement = xmlElementElement; + this.maxOccurs = null; } + public String name() { return this.getAttribute("name"); } @@ -297,19 +306,19 @@ public class XSDElement implements Element { sbElement.append(" type=\"xs:int\""); if ( elementType.equals("java.lang.Boolean")) sbElement.append(" type=\"xs:boolean\""); - if ( ("java.lang.Boolean".equals(elementType)) || (elementIsRequired == null || !elementIsRequired.equals("true")||addType != null)) { + if ( addType != null || elementType.startsWith("java.lang.") ) { sbElement.append(" minOccurs=\"0\""); } if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) { - sbElement.append(" maxOccurs=\"5000\""); + sbElement.append(" maxOccurs=\"" + maxOccurs + "\""); } if(useAnnotation) { - String annotation = new XSDElement(xmlElementElement).getHTMLAnnotation("field", " "); - sbElement.append(StringUtils.isNotEmpty(annotation) ? ">\n" : ""); + String annotation = new XSDElement(xmlElementElement, maxOccurs).getHTMLAnnotation("field", " "); + sbElement.append(StringUtils.isNotEmpty(annotation) ? ">" + OxmFileProcessor.LINE_SEPARATOR : ""); sbElement.append(annotation); - sbElement.append(StringUtils.isNotEmpty(annotation) ? " </xs:element>\n" : "/>\n" ); + sbElement.append(StringUtils.isNotEmpty(annotation) ? " </xs:element>" + OxmFileProcessor.LINE_SEPARATOR : "/>" + OxmFileProcessor.LINE_SEPARATOR ); } else { - sbElement.append("/>\n"); + sbElement.append("/>" + OxmFileProcessor.LINE_SEPARATOR); } return this.getHTMLElementWrapper(sbElement.toString(), v, useAnnotation); // return sbElement.toString(); @@ -337,18 +346,18 @@ public class XSDElement implements Element { if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) { sbElement.append(" minOccurs=\"0\""); } - sbElement.append(">\n"); - sbElement.append(" <xs:complexType>\n"); + sbElement.append(">" + OxmFileProcessor.LINE_SEPARATOR); + sbElement.append(" <xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); if(useAnnotation) { - XSDElement javaTypeElement = new XSDElement((Element)this.getParentNode()); + XSDElement javaTypeElement = new XSDElement((Element)this.getParentNode(), maxOccurs); sbElement.append(javaTypeElement.getHTMLAnnotation("class", " ")); } - sbElement.append(" <xs:sequence>\n"); + sbElement.append(" <xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); sbElement.append(" "); sbElement.append(unwrappedElement); - sbElement.append(" </xs:sequence>\n"); - sbElement.append(" </xs:complexType>\n"); - sbElement.append(" </xs:element>\n"); + sbElement.append(" </xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sbElement.append(" </xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sbElement.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); return sbElement.toString(); } @@ -385,12 +394,12 @@ public class XSDElement implements Element { if(metadata.size() == 0) { return ""; } - sb.append(indentation +"<xs:annotation>\r\n"); + sb.append(indentation +"<xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); sb.append( - indentation + " <xs:appinfo>\r\n" + - indentation + " <annox:annotate target=\""+target+"\">@org.onap.aai.annotations.Metadata(" + Joiner.on(",").join(metadata) + ")</annox:annotate>\r\n" + - indentation + " </xs:appinfo>\r\n"); - sb.append(indentation +"</xs:annotation>\r\n"); + indentation + " <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR + + indentation + " <annox:annotate target=\""+target+"\">@org.onap.aai.annotations.Metadata(" + Joiner.on(",").join(metadata) + ")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR + + indentation + " </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(indentation +"</xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); return sb.toString(); } @@ -722,5 +731,4 @@ public class XSDElement implements Element { } -} - +}
\ No newline at end of file diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/YAMLfromOXM.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/YAMLfromOXM.java index f90d54e6..a14a6977 100644 --- a/aai-core/src/main/java/org/onap/aai/util/genxsd/YAMLfromOXM.java +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/YAMLfromOXM.java @@ -27,6 +27,7 @@ import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -111,25 +112,33 @@ public class YAMLfromOXM extends OxmFileProcessor { try { init(); } catch(Exception e) { - logger.error( "Error initializing " + this.getClass(),e); + logger.error( "Error initializing " + this.getClass()); throw e; } pathSb.append(getDocumentHeader()); StringBuffer definitionsSb = new StringBuffer(); + Element elem; + String javaTypeName; + combinedJavaTypes = new HashMap(); for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { - XSDElement javaTypeElement = new XSDElement((Element)javaTypeNodes.item(i)); - logger.debug("External: "+javaTypeElement.getAttribute("name")); - String javaTypeName = javaTypeElement.name(); + elem = (Element)javaTypeNodes.item(i); + javaTypeName = elem.getAttribute("name"); + if ( !"Inventory".equals(javaTypeName ) ) { + if ( generatedJavaType.containsKey(getXmlRootElementName(javaTypeName) ) ) { + continue; + } + // will combine all matching java-types + elem = getJavaTypeElementSwagger(javaTypeName ); + } + + XSDElement javaTypeElement = new XSDElement(elem); if ( javaTypeName == null ) { String msg = "Invalid OXM file: <java-type> has no name attribute in " + oxmFile; logger.error(msg); throw new AAIException(msg); } namespaceFilter.add(getXmlRootElementName(javaTypeName)); - //Skip any type that has already been processed(recursion could be the reason) - if ( generatedJavaType.containsKey(getXmlRootElementName(javaTypeName)) ) { - continue; - } + processJavaTypeElementSwagger( javaTypeName, javaTypeElement, pathSb, definitionsSb, null, null, null, null, null, null); } @@ -160,8 +169,8 @@ public class YAMLfromOXM extends OxmFileProcessor { if(namespaceFilter != null && (! namespaceFilter.contains(entry.getKey()))) { continue; } - logger.debug("Key: "+entry.getKey()+"Test: "+ (entry.getKey() == "relationship")); - if(entry.getKey().matches("relationship")) { + logger.debug("Key: "+entry.getKey()+"Test: "+ (entry.getKey() == "relationship-dict")); + if(entry.getKey().matches("relationship-dict")) { String jb=entry.getValue(); logger.debug("Value: "+jb); int ndx=jb.indexOf("related-to-property:"); @@ -209,10 +218,24 @@ public class YAMLfromOXM extends OxmFileProcessor { return sb.toString(); } + private String getDictionary(String resource ) { + StringBuffer dictSb = new StringBuffer(); + dictSb.append(" " + resource + ":\n"); + dictSb.append(" description: |\n"); + dictSb.append(" dictionary of " + resource + "\n" ); + dictSb.append(" type: object\n"); + dictSb.append(" properties:\n"); + dictSb.append(" " + resource + ":\n"); + dictSb.append(" type: array\n"); + dictSb.append(" items:\n"); + dictSb.append(" $ref: \"#/definitions/" + resource + "-dict\"\n"); + return dictSb.toString(); + } + private String processJavaTypeElementSwagger( String javaTypeName, Element javaTypeElement, StringBuffer pathSb, StringBuffer definitionsSb, String path, String tag, String opId, String getItemName, StringBuffer pathParams, String validEdges) { - + String xmlRootElementName = getXMLRootElementName(javaTypeElement); StringBuilder definitionsLocalSb = new StringBuilder(256); @@ -409,6 +432,7 @@ public class YAMLfromOXM extends OxmFileProcessor { } boolean processingInventoryDef = false; + String dict = null; if ( xmlRootElementName.equals("inventory")) { // inventory properties for each oxm to be concatenated processingInventoryDef = true; @@ -418,7 +442,10 @@ public class YAMLfromOXM extends OxmFileProcessor { definitionsLocalSb.append(" " + xmlRootElementName + ":\n"); definitionsLocalSb.append(" properties:\n"); } - + } else if ( xmlRootElementName.equals("relationship")) { + definitionsSb.append(" " + "relationship-dict" + ":\n"); + definitionsLocalSb.append(" " + "relationship-dict" + ":\n"); + dict = getDictionary(xmlRootElementName); } else { definitionsSb.append(" " + xmlRootElementName + ":\n"); definitionsLocalSb.append(" " + xmlRootElementName + ":\n"); @@ -441,7 +468,7 @@ public class YAMLfromOXM extends OxmFileProcessor { results.get(key).stream().filter((i) -> (i.getFrom().equals(xmlRootElementName) && (! i.isPrivateEdge() && i.getPreventDelete().equals("OUT")))).forEach((i) ->{ preventDelete.add(i.getTo().toUpperCase());} ); } } catch(Exception e) { - logger.debug("xmlRootElementName: "+xmlRootElementName+"\n",e); + logger.debug("xmlRootElementName: "+xmlRootElementName+"\n"+e); } try { EdgeRuleQuery q1 = new EdgeRuleQuery.Builder(xmlRootElementName).version(v).toOnly().build(); @@ -454,7 +481,7 @@ public class YAMLfromOXM extends OxmFileProcessor { results.get(key).stream().filter((i) -> (i.getTo().equals(xmlRootElementName) && (! i.isPrivateEdge() && i.getPreventDelete().equals("IN")))).forEach((i) ->{ preventDelete.add(i.getFrom().toUpperCase());} ); } } catch(Exception e) { - logger.debug("xmlRootElementName: "+xmlRootElementName+"\n",e); + logger.debug("xmlRootElementName: "+xmlRootElementName+"\n"+e); } if(preventDelete.size() > 0) { prevent = xmlRootElementName.toUpperCase()+" cannot be deleted if related to "+String.join(",",preventDelete); @@ -501,11 +528,14 @@ public class YAMLfromOXM extends OxmFileProcessor { if ( xmlRootElementName.equals("inventory") ) { //will add to javaTypeDefinitions at end inventoryDefSb.append(definitionsLocalSb.toString()); + } else if ( xmlRootElementName.equals("relationship") ){ + javaTypeDefinitions.put(xmlRootElementName, dict); + javaTypeDefinitions.put(xmlRootElementName+ "-dict", definitionsLocalSb.toString()); } else { javaTypeDefinitions.put(xmlRootElementName, definitionsLocalSb.toString()); } } catch (Exception e) { - logger.error("Exception adding in javaTypeDefinitions",e); + e.printStackTrace(); } if ( xmlRootElementName.equals("inventory") ) { logger.trace("skip xmlRootElementName(2)="+xmlRootElementName); @@ -535,16 +565,21 @@ public class YAMLfromOXM extends OxmFileProcessor { try { outfile.createNewFile(); } catch (IOException e) { - logger.error( "Exception creating output file " + outfileName,e); + logger.error( "Exception creating output file " + outfileName); + e.printStackTrace(); } + BufferedWriter bw = null; + Charset charset = Charset.forName("UTF-8"); + Path path = Paths.get(outfileName); try { - Charset charset = Charset.forName("UTF-8"); - Path path = Paths.get(outfileName); - try(BufferedWriter bw = Files.newBufferedWriter(path, charset)){ - bw.write(fileContent); + bw = Files.newBufferedWriter(path, charset); + bw.write(fileContent); + if ( bw != null ) { + bw.close(); } } catch ( IOException e) { - logger.error( "Exception writing output file " + outfileName,e); + logger.error( "Exception writing output file " + outfileName); + e.printStackTrace(); } } @@ -565,4 +600,4 @@ public class YAMLfromOXM extends OxmFileProcessor { return false; } -} +}
\ No newline at end of file diff --git a/aai-core/src/test/java/org/onap/aai/dbmap/AAIGraphTest.java b/aai-core/src/test/java/org/onap/aai/dbmap/AAIGraphTest.java index 52319709..5915ce68 100644 --- a/aai-core/src/test/java/org/onap/aai/dbmap/AAIGraphTest.java +++ b/aai-core/src/test/java/org/onap/aai/dbmap/AAIGraphTest.java @@ -31,6 +31,8 @@ import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.matchesPattern; import static org.junit.Assert.*; +import java.io.FileNotFoundException; + public class AAIGraphTest extends AAISetup{ @Before public void setup() { @@ -68,5 +70,15 @@ public class AAIGraphTest extends AAISetup{ graphMgt.rollback(); graph.close(); } + + @Test (expected=FileNotFoundException.class) + public void JanusGraphOpenNameWithInvalidFilePathTest() throws Exception{ + JanusGraph graph = JanusGraphFactory.open(new AAIGraphConfig.Builder("invalid").forService(SERVICE_NAME).withGraphType("graphType").buildConfiguration()); + JanusGraphManagement graphMgt = graph.openManagement(); + String connectionInstanceName = graphMgt.getOpenInstances().stream().filter(c -> c.contains("current")).findFirst().get(); + assertThat(connectionInstanceName,matchesPattern("^\\d+_[\\w\\-\\d]+_" + SERVICE_NAME + "_graphType_\\d+\\(current\\)$")); + graphMgt.rollback(); + graph.close(); + } } diff --git a/aai-core/src/test/java/org/onap/aai/rest/RestHandlerTest.java b/aai-core/src/test/java/org/onap/aai/rest/RestHandlerTest.java new file mode 100644 index 00000000..c25e2929 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/rest/RestHandlerTest.java @@ -0,0 +1,40 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright © 2018 IBM. + * ================================================================================ + * 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.rest; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class RestHandlerTest { + + @Test + public void testGetInstance() { + + RestHandlerService firstInstance = RestHandlerService.getInstance(); + RestHandlerService secondInstance = RestHandlerService.getInstance(); + assertNotNull(firstInstance); + assertNotNull(secondInstance); + assertTrue(firstInstance == secondInstance); + + } +} diff --git a/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerTest.java b/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerTest.java index af6afac2..a5b968b3 100644 --- a/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerTest.java +++ b/aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerTest.java @@ -340,25 +340,64 @@ public class DbSerializerTest extends AAISetup { } - @Test + @Test public void touchStandardVertexPropertiesTest() throws AAIException, InterruptedException { engine.startTransaction(); + + //if this test runs through too fast the value may not change, causing the test to fail. sleeping ensures a different value + Thread.sleep(2); DBSerializer dbser2 = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST-2"); Vertex vert = graph.addVertex("aai-node-type", "generic-vnf"); + // Upon first creation of the Vertex and the DBSerializer + // the source of truth and created-ts should be the same as their modified counterparts + dbser2.touchStandardVertexProperties(vert, true); + String createTS = (String)vert.property(AAIProperties.CREATED_TS).value(); + String modTS = (String)vert.property(AAIProperties.LAST_MOD_TS).value(); + String sot = (String)vert.property(AAIProperties.SOURCE_OF_TRUTH).value(); + String lastModSOT = (String)vert.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value(); + assertTrue(createTS.equals(modTS)); + assertTrue(sot.equals(lastModSOT)); + + //if this test runs through too fast the value may not change, causing the test to fail. sleeping ensures a different value + Thread.sleep(2); + + // Not new vertex && new DBSerializer (A new serializer since a new one will be created per transaction) + // Here the vertex will be modified by a different source of truth + DBSerializer dbser3 = new DBSerializer(version, engine, introspectorFactoryType, "AAI-TEST-3"); + dbser3.touchStandardVertexProperties(vert, false); + createTS = (String)vert.property(AAIProperties.CREATED_TS).value(); + modTS = (String)vert.property(AAIProperties.LAST_MOD_TS).value(); + sot = (String)vert.property(AAIProperties.SOURCE_OF_TRUTH).value(); + lastModSOT = (String)vert.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value(); + assertFalse(createTS.equals(modTS)); + assertFalse(sot.equals(lastModSOT)); + + //if this test runs through too fast the value may not change, causing the test to fail. sleeping ensures a different value + Thread.sleep(2); + + // The currentTimeMillis used for the created-ts and modified-ts is created at DBSerializer instantiation + // Every REST transaction should create a new DBSerializer - thus a new currentTimeMillis is used at the time of transaction. + // Using an existing vertex, but treating it as new && using an older DBSerializer dbser.touchStandardVertexProperties(vert, true); String resverStart = (String)vert.property(AAIProperties.RESOURCE_VERSION).value(); - String lastModTimeStart = (String)vert.property(AAIProperties.LAST_MOD_TS).value(); + String lastModTimeStart = (String)vert.property(AAIProperties.LAST_MOD_TS).value(); + createTS = (String)vert.property(AAIProperties.CREATED_TS).value(); + modTS = (String)vert.property(AAIProperties.LAST_MOD_TS).value(); + assertTrue(createTS.equals(modTS)); + assertEquals("AAI-TEST", vert.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value()); - Thread.sleep(10); //bc the resource version is set based on current time in milliseconds, - //if this test runs through too fast the value may not change - //causing the test to fail. sleeping ensures a different value + //if this test runs through too fast the value may not change, causing the test to fail. sleeping ensures a different value + Thread.sleep(2); dbser2.touchStandardVertexProperties(vert, false); - assertFalse(resverStart.equals(vert.property(AAIProperties.RESOURCE_VERSION).value())); - assertFalse(lastModTimeStart.equals(vert.property(AAIProperties.LAST_MOD_TS).value())); - assertEquals("AAI-TEST-2", vert.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value()); + String resourceVer = (String)vert.property(AAIProperties.RESOURCE_VERSION).value(); + String lastModTs = (String)vert.property(AAIProperties.LAST_MOD_TS).value(); + String lastModSoT = (String)vert.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH).value(); + assertFalse(resverStart.equals(resourceVer)); + assertFalse(lastModTimeStart.equals(lastModTs)); + assertEquals("AAI-TEST-2", lastModSoT); } @Test diff --git a/aai-core/src/test/java/org/onap/aai/serialization/db/EdgeRulesTest.java b/aai-core/src/test/java/org/onap/aai/serialization/db/EdgeRulesTest.java new file mode 100644 index 00000000..0bb07895 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/serialization/db/EdgeRulesTest.java @@ -0,0 +1,156 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.serialization.db; + + +import com.google.common.collect.Multimap; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.aai.AAISetup; +import org.onap.aai.edges.EdgeIngestor; +import org.onap.aai.edges.EdgeRule; +import org.onap.aai.edges.EdgeRuleQuery; +import org.onap.aai.edges.enums.EdgeType; +import org.onap.aai.edges.exceptions.AmbiguousRuleChoiceException; +import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException; +import org.onap.aai.setup.SchemaVersion; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.*; +import java.util.stream.Collectors; + +import static junit.framework.TestCase.fail; +import static org.junit.Assert.assertEquals; + +public class EdgeRulesTest extends AAISetup { + + //set thrown.expect to whatever a specific test needs + //this establishes a default of expecting no exceptions to be thrown + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Autowired + private EdgeIngestor edgeIngestor; + + @Test + public void verifyOutDirection() throws EdgeRuleNotFoundException, AmbiguousRuleChoiceException { + + EdgeRuleQuery ruleQuery = new EdgeRuleQuery + .Builder("cloud-region", "flavor") + .edgeType(EdgeType.TREE) + .build(); + + EdgeRule rule = edgeIngestor.getRule(ruleQuery); + + assertEquals("out direction", rule.getDirection(), Direction.IN); + } + + @Test + public void verifyOutFlippedDirection() throws EdgeRuleNotFoundException, AmbiguousRuleChoiceException { + + EdgeRuleQuery ruleQuery = new EdgeRuleQuery + .Builder("flavor", "cloud-region") + .edgeType(EdgeType.TREE) + .build(); + + EdgeRule rule = edgeIngestor.getRule(ruleQuery); + + assertEquals("in direction", rule.getDirection(), Direction.OUT); + } + + @Test + public void verifyMultipleGet() throws EdgeRuleNotFoundException { + + EdgeRuleQuery ruleQuery = new EdgeRuleQuery + .Builder("model-element", "model-ver") + .edgeType(EdgeType.TREE) + .build(); + + Multimap<String, EdgeRule> ruleMap = edgeIngestor.getRules(ruleQuery); + + for (EdgeRule edgeRule : ruleMap.get("model|model-ver")) { + assertEquals("has isA rule", "org.onap.relationships.inventory.IsA", + edgeRule.getLabel()); + } + + } + + @Test + public void verifyAllRules() throws EdgeRuleNotFoundException { + + // This will cause every rule in the real json files to be verified + // so if any required properties are missing, the verification builds + // will catch it and incorrect rules can't get merged in. + for (SchemaVersion v : schemaVersions.getVersions()) { + Multimap<String, EdgeRule> all = edgeIngestor.getAllRules(schemaVersions.getDefaultVersion()); + + //this part verifies the default properties + // 1) can have only at most 1 containment edge between same node type pair + // 2) if there is at least 1 cousin edge, there must be exactly 1 cousin edge with default=true + for (String key : all.keySet()) { + + Collection<EdgeRule> edgeRuleCollection = all.get(key); + + boolean foundContainment = false; //can have at most 1 containment rel btwn same pair of node types + boolean foundCousin = false; + boolean cousinDefault = false; //if there is a cousin edge there must be at least 1 default cousin defined + Set<String> labels = new HashSet<>(); //all edges between the same pair must have different labels + int cousinCount = 0; + + for(EdgeRule rule: edgeRuleCollection){ + EdgeRule match = rule; + //check containment + if (!("NONE".equals(match.getContains()))) { + if (foundContainment) { + fail("more than one containment edge defined for " + v.toString() + " " + key); + } else { + foundContainment = true; + } + } else { //check cousin stuff + foundCousin = true; + cousinCount++; + if (match.isDefault()) { + if (!cousinDefault) { + cousinDefault = true; + } else { + fail("more than one cousin edge defined as default for " + v.toString() + " " + key); + } + } + } + + //check labels + String label = match.getLabel(); + if (labels.contains(label)) { + fail("same label found for multiple edges for " + v.toString() + " " + key); + } else { + labels.add(label); + } + } + if (foundCousin && !cousinDefault && cousinCount > 1) { + fail("there is at least one cousin edge but none are designated the default for " + v.toString() + " " + key); + } + } + } + } +} diff --git a/aai-core/src/test/java/org/onap/aai/serialization/queryformats/ResourceWithSoTTest.java b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/ResourceWithSoTTest.java new file mode 100644 index 00000000..ad28e697 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/serialization/queryformats/ResourceWithSoTTest.java @@ -0,0 +1,181 @@ +/** + * ============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.serialization.queryformats; + +import com.google.gson.JsonObject; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.aai.AAISetup; +import org.onap.aai.dbmap.DBConnectionType; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.serialization.db.DBSerializer; +import org.onap.aai.serialization.engines.JanusGraphDBEngine; +import org.onap.aai.serialization.engines.QueryStyle; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import org.onap.aai.serialization.queryformats.utils.UrlBuilder; +import org.onap.aai.setup.SchemaVersion; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +public class ResourceWithSoTTest extends AAISetup { + @Mock + private UrlBuilder urlBuilder; + + private Graph graph; + private Vertex putVertex; + private Vertex patchVertex1; + private Vertex patchVertex2; + + private JsonObject jsonPutObj = new JsonObject() ; + private JsonObject jsonPatchObj1 = new JsonObject() ; + private JsonObject jsonPatchObj2 = new JsonObject() ; + + private SchemaVersion version; + private ResourceWithSoT resourceWithSoT; + + private TransactionalGraphEngine dbEngine; + private Loader loader; + private DBSerializer serializer; + private final ModelType factoryType = ModelType.MOXY; + + @Before + public void setUp() throws Exception { + + version = schemaVersions.getDefaultVersion(); + MockitoAnnotations.initMocks(this); + + graph = TinkerGraph.open(); + + Long currentTimeMs = System.currentTimeMillis(); + String timeNowInMs = Long.toString(currentTimeMs); + + // PUT / CREATE + jsonPutObj.addProperty("aai-created-ts", timeNowInMs); + jsonPutObj.addProperty("aai-last-mod-ts", timeNowInMs); + jsonPutObj.addProperty("source-of-truth", "user_a"); + jsonPutObj.addProperty("last-mod-source-of-truth", "user_a"); + jsonPutObj.addProperty("last-action-performed", "Created"); + + putVertex = graph.addVertex( + "aai-created-ts", timeNowInMs, + "aai-last-mod-ts", timeNowInMs, + "source-of-truth", "user_a", + "last-mod-source-of-truth", "user_a" + ); + + // PATCH / MODIFY with differing source of truths + jsonPatchObj1.addProperty("aai-created-ts", timeNowInMs); + jsonPatchObj1.addProperty("aai-last-mod-ts", timeNowInMs); + jsonPatchObj1.addProperty("source-of-truth", "user_a"); + jsonPatchObj1.addProperty("last-mod-source-of-truth", "user_b"); + jsonPatchObj1.addProperty("last-action-performed", "Modified"); + + patchVertex1 = graph.addVertex( + "aai-created-ts", timeNowInMs, + "aai-last-mod-ts", timeNowInMs, + "source-of-truth", "user_a", + "last-mod-source-of-truth", "user_b" + ); + + // PATCH / MODIFY with differing time stamps + jsonPatchObj2.addProperty("aai-created-ts", timeNowInMs); + jsonPatchObj2.addProperty("aai-last-mod-ts", Long.toString(currentTimeMs + 1000)); + jsonPatchObj2.addProperty("source-of-truth", "user_a"); + jsonPatchObj2.addProperty("last-mod-source-of-truth", "user_a"); + jsonPatchObj2.addProperty("last-action-performed", "Modified"); + + patchVertex2 = graph.addVertex( + "aai-created-ts", timeNowInMs, + "aai-last-mod-ts", Long.toString(currentTimeMs + 1000), + "source-of-truth", "user_a", + "last-mod-source-of-truth", "user_a" + ); + + graph = TinkerGraph.open(); + createLoaderEngineSetup(); + } + + // This test is to simulate a PUT request + @Test + public void testGetJsonFromVertexWithCreateVertex() throws AAIFormatVertexException, AAIException { + if (putVertex == null) + assertTrue("The vertex used for this test is null. Fail immediately.", false); + + JsonObject json = resourceWithSoT.getJsonFromVertex(putVertex).get(); + assertEquals(jsonPutObj, json); + } + + // This test is to simulate PATCH requests + @Test + public void testGetJsonFromVertexWithModifyVertex() throws AAIFormatVertexException, AAIException { + if (patchVertex1 == null) + assertTrue("The vertex 1 used for this test is null. Fail immediately.", false); + if (patchVertex2 == null) + assertTrue("The vertex 2 used for this test is null. Fail immediately.", false); + + // Differing Source of Truths will indicate that the action performed modified the vertex + JsonObject json1 = resourceWithSoT.getJsonFromVertex(patchVertex1).get(); + assertEquals(jsonPatchObj1, json1); + + // Timestamps that have a large span in time difference will (likely) indicate that the transaction was not a create (thus, modify) + JsonObject json2 = resourceWithSoT.getJsonFromVertex(patchVertex2).get(); + assertEquals(jsonPatchObj2, json2); + } + + @Test + public void testGetJsonFromVertexWithNullVertex() throws AAIFormatVertexException, AAIException { + // Null check, will return null. + assertNull(resourceWithSoT.getJsonFromVertex(null)); + } + + public void createLoaderEngineSetup() throws AAIException { + + if (loader == null) { + loader = loaderFactory.createLoaderForVersion(factoryType, version); + //loader = LoaderFactory.createLoaderForVersion(factoryType, version); + dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, DBConnectionType.CACHED, loader)); + serializer = new DBSerializer(version, dbEngine, factoryType, "Junit"); + resourceWithSoT = new ResourceWithSoT.Builder(loader, serializer, urlBuilder).build(); + + TransactionalGraphEngine.Admin spyAdmin = spy(dbEngine.asAdmin()); + + when(dbEngine.tx()).thenReturn(graph); + when(dbEngine.asAdmin()).thenReturn(spyAdmin); + + when(spyAdmin.getReadOnlyTraversalSource()) + .thenReturn(graph.traversal(GraphTraversalSource.build().with(ReadOnlyStrategy.instance()))); + when(spyAdmin.getTraversalSource()).thenReturn(graph.traversal()); + } + } +} diff --git a/aai-core/src/test/java/org/onap/aai/util/JettyObfuscationConversionCommandLineUtilTest.java b/aai-core/src/test/java/org/onap/aai/util/JettyObfuscationConversionCommandLineUtilTest.java index 97349ecc..071b630b 100644 --- a/aai-core/src/test/java/org/onap/aai/util/JettyObfuscationConversionCommandLineUtilTest.java +++ b/aai-core/src/test/java/org/onap/aai/util/JettyObfuscationConversionCommandLineUtilTest.java @@ -4,6 +4,8 @@ * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ + * Modifications Copyright © 2018 IBM. + * ================================================================================ * 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 @@ -30,42 +32,65 @@ import org.junit.Test; public class JettyObfuscationConversionCommandLineUtilTest { - private final ByteArrayOutputStream testOut = new ByteArrayOutputStream(); + private final ByteArrayOutputStream testOut = new ByteArrayOutputStream(); + + /** + * Test. + */ + @Test + public void test() { + //setup, this will catch main's print statements for evaluation + PrintStream oldOutputStream = System.out; + System.setOut(new PrintStream(testOut)); + + /* ------ TEST OBFUSCATION ----*/ + JettyObfuscationConversionCommandLineUtil.main(new String[]{"-e", "hello world"}); + /* + * testOut was also catching any logging statements which interfered with result checking. + * This regex business was the workaround - it tries to find the expected value in + * the results and asserts against that. + */ + String obfResult = testOut.toString(); + String obfExpected = "OBF:1thf1ugo1x151wfw1ylz11tr1ymf1wg21x1h1uh21th7"; + Pattern obfExpectPat = Pattern.compile(obfExpected); + Matcher obfMatch = obfExpectPat.matcher(obfResult); + assertTrue(obfMatch.find()); + + testOut.reset(); //clear out previous result + + /* ------ TEST DEOBFUSCATION ----- */ + JettyObfuscationConversionCommandLineUtil.main(new String[]{"-d", obfExpected}); + String deobfResult = testOut.toString(); + String deobfExpected = "hello world"; + Pattern deobfExpectPat = Pattern.compile(deobfExpected); + Matcher deobfMatch = deobfExpectPat.matcher(deobfResult); + assertTrue(deobfMatch.find()); - /** - * Test. - */ - @Test - public void test() { - //setup, this will catch main's print statements for evaluation - PrintStream oldOutputStream = System.out; - System.setOut(new PrintStream(testOut)); + //clean up, resets to stdout + System.setOut(oldOutputStream); + } - /* ------ TEST OBFUSCATION ----*/ - JettyObfuscationConversionCommandLineUtil.main(new String[]{"-e", "hello world"}); - /* - * testOut was also catching any logging statements which interfered with result checking. - * This regex business was the workaround - it tries to find the expected value in - * the results and asserts against that. - */ - String obfResult = testOut.toString(); - String obfExpected = "OBF:1thf1ugo1x151wfw1ylz11tr1ymf1wg21x1h1uh21th7"; - Pattern obfExpectPat = Pattern.compile(obfExpected); - Matcher obfMatch = obfExpectPat.matcher(obfResult); - assertTrue(obfMatch.find()); + + /** + * Test. + */ + @Test + public void testUsage() { + System.setOut(new PrintStream(testOut)); - testOut.reset(); //clear out previous result + /* ------ TEST OBFUSCATION ----*/ + JettyObfuscationConversionCommandLineUtil.main(new String[]{"-f", "hello world"}); + /* + * testOut was also catching any logging statements which interfered with result checking. + * This regex business was the workaround - it tries to find the expected value in + * the results and asserts against that. + */ + String obfResult = testOut.toString(); + assertTrue(obfResult.startsWith("failed to parse input")); + + testOut.reset(); //clear out previous result - /* ------ TEST DEOBFUSCATION ----- */ - JettyObfuscationConversionCommandLineUtil.main(new String[]{"-d", obfExpected}); - String deobfResult = testOut.toString(); - String deobfExpected = "hello world"; - Pattern deobfExpectPat = Pattern.compile(deobfExpected); - Matcher deobfMatch = deobfExpectPat.matcher(deobfResult); - assertTrue(deobfMatch.find()); - //clean up, resets to stdout - System.setOut(oldOutputStream); - } + } } diff --git a/aai-core/src/test/java/org/onap/aai/util/genxsd/HTMLfromOXMTest.java b/aai-core/src/test/java/org/onap/aai/util/genxsd/HTMLfromOXMTest.java index d35cc4f0..57835b50 100644 --- a/aai-core/src/test/java/org/onap/aai/util/genxsd/HTMLfromOXMTest.java +++ b/aai-core/src/test/java/org/onap/aai/util/genxsd/HTMLfromOXMTest.java @@ -33,6 +33,7 @@ import java.nio.file.Paths; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; import org.onap.aai.config.SwaggerGenerationConfiguration; import org.onap.aai.setup.SchemaVersion; @@ -65,7 +66,8 @@ import org.w3c.dom.Element; }) @TestPropertySource(properties = { - "schema.uri.base.path = /aai" + "schema.uri.base.path = /aai", + "schema.xsd.maxoccurs = 5000" }) public class HTMLfromOXMTest { private static final Logger logger = LoggerFactory.getLogger("HTMLfromOXMTest.class"); @@ -95,14 +97,18 @@ public class HTMLfromOXMTest { @Before public void setUp() throws Exception { + setUp(0); + } + + public void setUp(int sbopt) throws Exception + { XSDElementTest x = new XSDElementTest(); - x.setUp(); + x.setUp(sbopt); testXML = x.testXML; logger.debug(testXML); BufferedWriter bw = new BufferedWriter(new FileWriter(OXMFILENAME)); bw.write(testXML); bw.close(); - } @Test @@ -133,7 +139,23 @@ public class HTMLfromOXMTest { } logger.debug("FileContent-I:"); logger.debug(fileContent); - assertThat(fileContent, is(HTMLresult())); + assertThat(fileContent, is(HTMLresult(0))); + } + + @Test + public void testProcessWithCombiningJavaTypes() { + SchemaVersion v = schemaVersions.getAppRootVersion(); + String fileContent = null; + try { + setUp(1); + htmlFromOxm.setXmlVersion(testXML, v); + fileContent = htmlFromOxm.process(); + } catch(Exception e) { + e.printStackTrace(); + } + logger.debug("FileContent-I:"); + logger.debug(fileContent); + assertThat(fileContent, is(HTMLresult(1))); } @Test @@ -158,7 +180,7 @@ public class HTMLfromOXMTest { XMLfile.delete(); logger.debug("FileContent-I:"); logger.debug(fileContent); - assertThat(fileContent, is(HTMLresult())); + assertThat(fileContent, is(HTMLresult(0))); } @Test @@ -173,7 +195,7 @@ public class HTMLfromOXMTest { } logger.debug("FileContent-II:"); logger.debug(fileContent); - assertThat(fileContent, is(HTMLresult())); + assertThat(fileContent, is(HTMLresult(0))); } @Test @@ -193,139 +215,170 @@ public class HTMLfromOXMTest { assertThat("Element="+customer.getNodeName()+"/"+customer.getAttribute("name"), is(target)); } public String HTMLresult() { + return HTMLresult(0); + } + + public String HTMLresult(int sbopt) { StringBuilder sb = new StringBuilder(32368); sb.append(HTMLheader()); - sb.append(HTMLdefs()); + sb.append(HTMLdefs(sbopt)); return sb.toString(); } public String HTMLheader() { StringBuilder sb = new StringBuilder(1500); - sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"); - sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://org.onap.aai.inventory/v11\" xmlns:tns=\"http://org.onap.aai.inventory/v11\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\nxmlns:jaxb=\"http://java.sun.com/xml/ns/jaxb\"\r\n"); - sb.append(" jaxb:version=\"2.1\"\r\n"); - sb.append(" xmlns:annox=\"http://annox.dev.java.net\"\r\n"); - sb.append(" jaxb:extensionBindingPrefixes=\"annox\">\n\n"); + sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://org.onap.aai.inventory/v11\" xmlns:tns=\"http://org.onap.aai.inventory/v11\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" + OxmFileProcessor.LINE_SEPARATOR + "xmlns:jaxb=\"http://java.sun.com/xml/ns/jaxb\"" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" jaxb:version=\"2.1\"" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" xmlns:annox=\"http://annox.dev.java.net\"" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" jaxb:extensionBindingPrefixes=\"annox\">" + OxmFileProcessor.DOUBLE_LINE_SEPARATOR); return sb.toString(); } + public String HTMLdefs() { + return HTMLdefs(0); + } + public String HTMLdefs(int sbopt) { StringBuilder sb = new StringBuilder(1500); - sb.append(" <xs:element name=\"service-subscription\">\n"); - sb.append(" <xs:complexType>\n"); - sb.append(" <xs:annotation>\r\n"); - sb.append(" <xs:appinfo>\r\n"); - sb.append(" <annox:annotate target=\"class\">@org.onap.aai.annotations.Metadata(description=\"Object that group service instances.\",indexedProps=\"service-type\",dependentOn=\"customer\",container=\"service-subscriptions\",crossEntityReference=\"service-instance,service-type\")</annox:annotate>\r\n"); - sb.append(" </xs:appinfo>\r\n"); - sb.append(" </xs:annotation>\r\n"); - sb.append(" <xs:sequence>\n"); - sb.append(" <xs:element name=\"service-type\" type=\"xs:string\">\n"); - sb.append(" <xs:annotation>\r\n"); - sb.append(" <xs:appinfo>\r\n"); - sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(isKey=true,description=\"Value defined by orchestration to identify this service.\")</annox:annotate>\r\n"); - sb.append(" </xs:appinfo>\r\n"); - sb.append(" </xs:annotation>\r\n"); - sb.append(" </xs:element>\n"); - sb.append(" <xs:element name=\"temp-ub-sub-account-id\" type=\"xs:string\" minOccurs=\"0\">\n"); - sb.append(" <xs:annotation>\r\n"); - sb.append(" <xs:appinfo>\r\n"); - sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(description=\"This property will be deleted from A&AI in the near future. Only stop gap solution.\")</annox:annotate>\r\n"); - sb.append(" </xs:appinfo>\r\n"); - sb.append(" </xs:annotation>\r\n"); - sb.append(" </xs:element>\n"); - sb.append(" <xs:element name=\"resource-version\" type=\"xs:string\" minOccurs=\"0\">\n"); - sb.append(" <xs:annotation>\r\n"); - sb.append(" <xs:appinfo>\r\n"); - sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(description=\"Used for optimistic concurrency. Must be empty on create, valid on update and delete.\")</annox:annotate>\r\n"); - sb.append(" </xs:appinfo>\r\n"); - sb.append(" </xs:annotation>\r\n"); - sb.append(" </xs:element>\n"); - sb.append(" </xs:sequence>\n"); - sb.append(" </xs:complexType>\n"); - sb.append(" </xs:element>\n"); - sb.append(" <xs:element name=\"service-subscriptions\">\n"); - sb.append(" <xs:complexType>\n"); - sb.append(" <xs:annotation>\r\n"); - sb.append(" <xs:appinfo>\r\n"); - sb.append(" <annox:annotate target=\"class\">@org.onap.aai.annotations.Metadata(description=\"Collection of objects that group service instances.\")</annox:annotate>\r\n"); - sb.append(" </xs:appinfo>\r\n"); - sb.append(" </xs:annotation>\r\n"); - sb.append(" <xs:sequence>\n"); - sb.append(" <xs:element ref=\"tns:service-subscription\" minOccurs=\"0\" maxOccurs=\"5000\"/>\n"); - sb.append(" </xs:sequence>\n"); - sb.append(" </xs:complexType>\n"); - sb.append(" </xs:element>\n"); - sb.append(" <xs:element name=\"customer\">\n"); - sb.append(" <xs:complexType>\n"); - sb.append(" <xs:annotation>\r\n"); - sb.append(" <xs:appinfo>\r\n"); - sb.append(" <annox:annotate target=\"class\">@org.onap.aai.annotations.Metadata(description=\"customer identifiers to provide linkage back to BSS information.\",nameProps=\"subscriber-name\",indexedProps=\"subscriber-name,global-customer-id,subscriber-type\",searchable=\"global-customer-id,subscriber-name\",uniqueProps=\"global-customer-id\",container=\"customers\",namespace=\"business\")</annox:annotate>\r\n"); - sb.append(" </xs:appinfo>\r\n"); - sb.append(" </xs:annotation>\r\n"); - sb.append(" <xs:sequence>\n"); - sb.append(" <xs:element name=\"global-customer-id\" type=\"xs:string\">\n"); - sb.append(" <xs:annotation>\r\n"); - sb.append(" <xs:appinfo>\r\n"); - sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(isKey=true,description=\"Global customer id used across to uniquely identify customer.\")</annox:annotate>\r\n"); - sb.append(" </xs:appinfo>\r\n"); - sb.append(" </xs:annotation>\r\n"); - sb.append(" </xs:element>\n"); - sb.append(" <xs:element name=\"subscriber-name\" type=\"xs:string\">\n"); - sb.append(" <xs:annotation>\r\n"); - sb.append(" <xs:appinfo>\r\n"); - sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(description=\"Subscriber name, an alternate way to retrieve a customer.\")</annox:annotate>\r\n"); - sb.append(" </xs:appinfo>\r\n"); - sb.append(" </xs:annotation>\r\n"); - sb.append(" </xs:element>\n"); - sb.append(" <xs:element name=\"subscriber-type\" type=\"xs:string\">\n"); - sb.append(" <xs:annotation>\r\n"); - sb.append(" <xs:appinfo>\r\n"); - sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(description=\"Subscriber type, a way to provide VID with only the INFRA customers.\",defaultValue=\"CUST\")</annox:annotate>\r\n"); - sb.append(" </xs:appinfo>\r\n"); - sb.append(" </xs:annotation>\r\n"); - sb.append(" </xs:element>\n"); - sb.append(" <xs:element name=\"resource-version\" type=\"xs:string\" minOccurs=\"0\">\n"); - sb.append(" <xs:annotation>\r\n"); - sb.append(" <xs:appinfo>\r\n"); - sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(description=\"Used for optimistic concurrency. Must be empty on create, valid on update and delete.\")</annox:annotate>\r\n"); - sb.append(" </xs:appinfo>\r\n"); - sb.append(" </xs:annotation>\r\n"); - sb.append(" </xs:element>\n"); - sb.append(" <xs:element ref=\"tns:service-subscriptions\" minOccurs=\"0\"/>\n"); - sb.append(" </xs:sequence>\n"); - sb.append(" </xs:complexType>\n"); - sb.append(" </xs:element>\n"); - sb.append(" <xs:element name=\"customers\">\n"); - sb.append(" <xs:complexType>\n"); - sb.append(" <xs:annotation>\r\n"); - sb.append(" <xs:appinfo>\r\n"); - sb.append(" <annox:annotate target=\"class\">@org.onap.aai.annotations.Metadata(description=\"Collection of customer identifiers to provide linkage back to BSS information.\")</annox:annotate>\r\n"); - sb.append(" </xs:appinfo>\r\n"); - sb.append(" </xs:annotation>\r\n"); - sb.append(" <xs:sequence>\n"); - sb.append(" <xs:element ref=\"tns:customer\" minOccurs=\"0\" maxOccurs=\"5000\"/>\n"); - sb.append(" </xs:sequence>\n"); - sb.append(" </xs:complexType>\n"); - sb.append(" </xs:element>\n"); - sb.append(" <xs:element name=\"business\">\n"); - sb.append(" <xs:complexType>\n"); - sb.append(" <xs:annotation>\r\n"); - sb.append(" <xs:appinfo>\r\n"); - sb.append(" <annox:annotate target=\"class\">@org.onap.aai.annotations.Metadata(description=\"Namespace for business related constructs\")</annox:annotate>\r\n"); - sb.append(" </xs:appinfo>\r\n"); - sb.append(" </xs:annotation>\r\n"); - sb.append(" <xs:sequence>\n"); - sb.append(" <xs:element ref=\"tns:customers\" minOccurs=\"0\"/>\n"); - sb.append(" </xs:sequence>\n"); - sb.append(" </xs:complexType>\n"); - sb.append(" </xs:element>\n"); - sb.append(" <xs:element name=\"inventory\">\n"); - sb.append(" <xs:complexType>\n"); - sb.append(" <xs:sequence>\n"); - sb.append(" <xs:element ref=\"tns:business\" minOccurs=\"0\"/>\n"); - sb.append(" </xs:sequence>\n"); - sb.append(" </xs:complexType>\n"); - sb.append(" </xs:element>\n"); - sb.append("</xs:schema>\n"); + sb.append(" <xs:element name=\"service-subscription\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"class\">@org.onap.aai.annotations.Metadata(description=\"Object that group service instances.\",indexedProps=\"service-type\",dependentOn=\"customer\",container=\"service-subscriptions\",crossEntityReference=\"service-instance,service-type\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element name=\"service-type\" type=\"xs:string\" minOccurs=\"0\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(isKey=true,description=\"Value defined by orchestration to identify this service.\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element name=\"temp-ub-sub-account-id\" type=\"xs:string\" minOccurs=\"0\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(description=\"This property will be deleted from A&AI in the near future. Only stop gap solution.\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element name=\"resource-version\" type=\"xs:string\" minOccurs=\"0\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(description=\"Used for optimistic concurrency. Must be empty on create, valid on update and delete.\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element name=\"service-subscriptions\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"class\">@org.onap.aai.annotations.Metadata(description=\"Collection of objects that group service instances.\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element ref=\"tns:service-subscription\" minOccurs=\"0\" maxOccurs=\"5000\"/>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element name=\"customer\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + if ( sbopt == 0 ) { + sb.append(" <annox:annotate target=\"class\">@org.onap.aai.annotations.Metadata(description=\"customer identifiers to provide linkage back to BSS information.\",nameProps=\"subscriber-name\",indexedProps=\"subscriber-name,global-customer-id,subscriber-type\",searchable=\"global-customer-id,subscriber-name\",uniqueProps=\"global-customer-id\",container=\"customers\",namespace=\"business\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + } else { + sb.append(" <annox:annotate target=\"class\">@org.onap.aai.annotations.Metadata(description=\"customer identifiers to provide linkage back to BSS information.\",nameProps=\"subscriber-name\",indexedProps=\"subscriber-type,subscriber-name,global-customer-id\",searchable=\"global-customer-id,subscriber-name\",uniqueProps=\"global-customer-id\",container=\"customers\",namespace=\"business\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + } + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element name=\"global-customer-id\" type=\"xs:string\" minOccurs=\"0\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(isKey=true,description=\"Global customer id used across to uniquely identify customer.\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element name=\"subscriber-name\" type=\"xs:string\" minOccurs=\"0\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(description=\"Subscriber name, an alternate way to retrieve a customer.\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + if ( sbopt == 0 ) { + sb.append(" <xs:element name=\"subscriber-type\" type=\"xs:string\" minOccurs=\"0\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(description=\"Subscriber type, a way to provide VID with only the INFRA customers.\",defaultValue=\"CUST\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element name=\"resource-version\" type=\"xs:string\" minOccurs=\"0\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(description=\"Used for optimistic concurrency. Must be empty on create, valid on update and delete.\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + } else { + sb.append(" <xs:element name=\"resource-version\" type=\"xs:string\" minOccurs=\"0\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(description=\"Used for optimistic concurrency. Must be empty on create, valid on update and delete.\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element name=\"subscriber-type\" type=\"xs:string\" minOccurs=\"0\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"field\">@org.onap.aai.annotations.Metadata(description=\"Subscriber type, a way to provide VID with only the INFRA customers.\",defaultValue=\"CUST\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + + } + sb.append(" <xs:element ref=\"tns:service-subscriptions\" minOccurs=\"0\"/>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element name=\"customers\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"class\">@org.onap.aai.annotations.Metadata(description=\"Collection of customer identifiers to provide linkage back to BSS information.\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element ref=\"tns:customer\" minOccurs=\"0\" maxOccurs=\"5000\"/>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element name=\"business\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <annox:annotate target=\"class\">@org.onap.aai.annotations.Metadata(description=\"Namespace for business related constructs\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element ref=\"tns:customers\" minOccurs=\"0\"/>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element name=\"inventory\">" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" <xs:element ref=\"tns:business\" minOccurs=\"0\"/>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:sequence>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:complexType>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append(" </xs:element>" + OxmFileProcessor.LINE_SEPARATOR); + sb.append("</xs:schema>" + OxmFileProcessor.LINE_SEPARATOR); return sb.toString(); } } + diff --git a/aai-core/src/test/java/org/onap/aai/util/genxsd/NodesYAMLfromOXMTest.java b/aai-core/src/test/java/org/onap/aai/util/genxsd/NodesYAMLfromOXMTest.java index 2dfcd4ed..b19a524b 100644 --- a/aai-core/src/test/java/org/onap/aai/util/genxsd/NodesYAMLfromOXMTest.java +++ b/aai-core/src/test/java/org/onap/aai/util/genxsd/NodesYAMLfromOXMTest.java @@ -64,7 +64,8 @@ import org.w3c.dom.Element; }) @TestPropertySource(properties = { - "schema.uri.base.path = /aai" + "schema.uri.base.path = /aai", + "schema.xsd.maxoccurs = 5000" }) public class NodesYAMLfromOXMTest { //public class NodesYAMLfromOXMTest extends AAISetup { diff --git a/aai-core/src/test/java/org/onap/aai/util/genxsd/XSDElementTest.java b/aai-core/src/test/java/org/onap/aai/util/genxsd/XSDElementTest.java index 94047c37..cfab4cc2 100644 --- a/aai-core/src/test/java/org/onap/aai/util/genxsd/XSDElementTest.java +++ b/aai-core/src/test/java/org/onap/aai/util/genxsd/XSDElementTest.java @@ -70,16 +70,25 @@ public class XSDElementTest { @Before public void setUp() throws Exception { - StringBuilder sb = new StringBuilder(maxSizeForXml); - addNamespace(sb); - addBusiness(sb); - addCustomers(sb); - addCustomer(sb); - addServiceSubscriptions(sb); - addServiceSubscription(sb); - addEndOfXML(sb); - testXML = sb.toString(); - init(); + setUp(0); + } + + public void setUp(int sbopt) throws Exception { + StringBuilder sb = new StringBuilder(maxSizeForXml); + addNamespace(sb); + addBusiness(sb); + addCustomers(sb); + if ( sbopt == 0 ) { + addCustomer(sb); + } else { + addCustomerNoSubscriberType(sb); + addCustomerSubscriberType(sb); + } + addServiceSubscriptions(sb); + addServiceSubscription(sb); + addEndOfXML(sb); + testXML = sb.toString(); + init(); } private void addNamespace(StringBuilder sb){ @@ -163,6 +172,58 @@ public class XSDElementTest { sb.append("</java-type>\n"); } + private void addCustomerNoSubscriberType(StringBuilder sb){ + sb.append("<java-type name=\"Customer\">\n"); + sb.append("<xml-root-element name=\"customer\" />\n"); + sb.append("<java-attributes>\n"); + sb.append("<xml-element java-attribute=\"globalCustomerId\" name=\"global-customer-id\" required=\"true\" type=\"java.lang.String\" xml-key=\"true\">\n"); + sb.append("<xml-properties>\n"); + sb.append("<xml-property name=\"description\" value=\"Global customer id used across to uniquely identify customer.\" />\n"); + sb.append("</xml-properties>\n"); + sb.append("</xml-element>\n"); + sb.append("<xml-element java-attribute=\"subscriberName\" name=\"subscriber-name\" required=\"true\" type=\"java.lang.String\">\n"); + sb.append("<xml-properties>\n"); + sb.append("<xml-property name=\"description\" value=\"Subscriber name, an alternate way to retrieve a customer.\" />\n"); + sb.append("</xml-properties>\n"); + sb.append("</xml-element>\n"); + sb.append("<xml-element java-attribute=\"resourceVersion\" name=\"resource-version\" type=\"java.lang.String\">\n"); + sb.append("<xml-properties>\n"); + sb.append("<xml-property name=\"description\" value=\"Used for optimistic concurrency. Must be empty on create, valid on update and delete.\" />\n"); + sb.append("</xml-properties>\n"); + sb.append("</xml-element>\n"); + sb.append("<xml-element java-attribute=\"serviceSubscriptions\" name=\"service-subscriptions\" type=\"inventory.aai.onap.org.v11.ServiceSubscriptions\" />\n"); +// sb.append("<xml-element java-attribute=\"relationshipList\" name=\"relationship-list\" type=\"inventory.aai.onap.org.v11.RelationshipList\" />\n"); + sb.append("</java-attributes>\n"); + sb.append("<xml-properties>\n"); + sb.append("<xml-property name=\"description\" value=\"customer identifiers to provide linkage back to BSS information.\" />\n"); + sb.append("<xml-property name=\"nameProps\" value=\"subscriber-name\" />\n"); + sb.append("<xml-property name=\"indexedProps\" value=\"subscriber-name,global-customer-id\" />\n"); + sb.append("<xml-property name=\"searchable\" value=\"global-customer-id,subscriber-name\" />\n"); + sb.append("<xml-property name=\"uniqueProps\" value=\"global-customer-id\" />\n"); + sb.append("<xml-property name=\"container\" value=\"customers\" />\n"); + sb.append("<xml-property name=\"namespace\" value=\"business\" />\n"); + sb.append("</xml-properties>\n"); + sb.append("</java-type>\n"); + } + + private void addCustomerSubscriberType(StringBuilder sb){ + sb.append("<java-type name=\"Customer\">\n"); + sb.append("<xml-root-element name=\"customer\" />\n"); + sb.append("<java-attributes>\n"); + sb.append("<xml-element java-attribute=\"subscriberType\" name=\"subscriber-type\" required=\"true\" type=\"java.lang.String\">\n"); + sb.append("<xml-properties>\n"); + sb.append("<xml-property name=\"description\" value=\"Subscriber type, a way to provide VID with only the INFRA customers.\" />\n"); + sb.append("<xml-property name=\"defaultValue\" value=\"CUST\" />\n"); + sb.append("</xml-properties>\n"); + sb.append("</xml-element>\n"); + sb.append("</java-attributes>\n"); + sb.append("<xml-properties>\n"); + sb.append("<xml-property name=\"indexedProps\" value=\"subscriber-type\" />\n"); + sb.append("<xml-property name=\"container\" value=\"customers\" />\n"); + sb.append("</xml-properties>\n"); + sb.append("</java-type>\n"); + } + private void addServiceSubscriptions(StringBuilder sb){ sb.append("<java-type name=\"ServiceSubscriptions\">\n"); sb.append("<xml-properties>\n"); @@ -503,11 +564,11 @@ public class XSDElementTest { @Test public void testGetHTMLAnnotation() { ArrayList<String> target = new ArrayList<String>(); - target.add(" <xs:annotation>\r\n <xs:appinfo>\r\n <annox:annotate target=\"Business\">@org.onap.aai.annotations.Metadata(description=\"Namespace for business related constructs\")</annox:annotate>\r\n </xs:appinfo>\r\n </xs:annotation>\r\n"); - target.add(" <xs:annotation>\r\n <xs:appinfo>\r\n <annox:annotate target=\"Customers\">@org.onap.aai.annotations.Metadata(description=\"Collection of customer identifiers to provide linkage back to BSS information.\")</annox:annotate>\r\n </xs:appinfo>\r\n </xs:annotation>\r\n"); - target.add(" <xs:annotation>\r\n <xs:appinfo>\r\n <annox:annotate target=\"Customer\">@org.onap.aai.annotations.Metadata(description=\"customer identifiers to provide linkage back to BSS information.\",nameProps=\"subscriber-name\",indexedProps=\"subscriber-name,global-customer-id,subscriber-type\",searchable=\"global-customer-id,subscriber-name\",uniqueProps=\"global-customer-id\",container=\"customers\",namespace=\"business\")</annox:annotate>\r\n </xs:appinfo>\r\n </xs:annotation>\r\n"); - target.add(" <xs:annotation>\r\n <xs:appinfo>\r\n <annox:annotate target=\"ServiceSubscriptions\">@org.onap.aai.annotations.Metadata(description=\"Collection of objects that group service instances.\")</annox:annotate>\r\n </xs:appinfo>\r\n </xs:annotation>\r\n"); - target.add(" <xs:annotation>\r\n <xs:appinfo>\r\n <annox:annotate target=\"ServiceSubscription\">@org.onap.aai.annotations.Metadata(description=\"Object that group service instances.\",indexedProps=\"service-type\",dependentOn=\"customer\",container=\"service-subscriptions\",crossEntityReference=\"service-instance,service-type\")</annox:annotate>\r\n </xs:appinfo>\r\n </xs:annotation>\r\n"); + target.add(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR + " <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR + " <annox:annotate target=\"Business\">@org.onap.aai.annotations.Metadata(description=\"Namespace for business related constructs\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR + " </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR + " </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + target.add(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR + " <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR + " <annox:annotate target=\"Customers\">@org.onap.aai.annotations.Metadata(description=\"Collection of customer identifiers to provide linkage back to BSS information.\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR + " </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR + " </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + target.add(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR + " <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR + " <annox:annotate target=\"Customer\">@org.onap.aai.annotations.Metadata(description=\"customer identifiers to provide linkage back to BSS information.\",nameProps=\"subscriber-name\",indexedProps=\"subscriber-name,global-customer-id,subscriber-type\",searchable=\"global-customer-id,subscriber-name\",uniqueProps=\"global-customer-id\",container=\"customers\",namespace=\"business\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR + " </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR + " </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + target.add(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR + " <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR + " <annox:annotate target=\"ServiceSubscriptions\">@org.onap.aai.annotations.Metadata(description=\"Collection of objects that group service instances.\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR + " </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR + " </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); + target.add(" <xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR + " <xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR + " <annox:annotate target=\"ServiceSubscription\">@org.onap.aai.annotations.Metadata(description=\"Object that group service instances.\",indexedProps=\"service-type\",dependentOn=\"customer\",container=\"service-subscriptions\",crossEntityReference=\"service-instance,service-type\")</annox:annotate>" + OxmFileProcessor.LINE_SEPARATOR + " </xs:appinfo>" + OxmFileProcessor.LINE_SEPARATOR + " </xs:annotation>" + OxmFileProcessor.LINE_SEPARATOR); List<String> annotes = new ArrayList<String>(); for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { XSDElement javaTypeElement = new XSDElement((Element) javaTypeNodes.item(i)); diff --git a/aai-core/src/test/java/org/onap/aai/util/genxsd/YAMLfromOXMTest.java b/aai-core/src/test/java/org/onap/aai/util/genxsd/YAMLfromOXMTest.java index e1288978..813ad837 100644 --- a/aai-core/src/test/java/org/onap/aai/util/genxsd/YAMLfromOXMTest.java +++ b/aai-core/src/test/java/org/onap/aai/util/genxsd/YAMLfromOXMTest.java @@ -76,7 +76,8 @@ import com.google.common.collect.Multimap; }) @TestPropertySource(properties = { - "schema.uri.base.path = /aai" + "schema.uri.base.path = /aai", + "schema.xsd.maxoccurs = 5000" }) public class YAMLfromOXMTest { @Autowired |