summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--aai-core/pom.xml.versionsBackup1063
-rw-r--r--aai-core/src/main/java/org/onap/aai/config/IntrospectionConfig.java4
-rw-r--r--aai-core/src/main/java/org/onap/aai/introspection/Introspector.java182
-rw-r--r--aai-core/src/main/java/org/onap/aai/introspection/JSONStrategy.java82
-rw-r--r--aai-core/src/main/java/org/onap/aai/introspection/Loader.java25
-rw-r--r--aai-core/src/main/java/org/onap/aai/introspection/MoxyLoader.java36
-rw-r--r--aai-core/src/main/java/org/onap/aai/introspection/MoxyStrategy.java103
-rw-r--r--aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java299
-rw-r--r--aai-core/src/main/java/org/onap/aai/serialization/db/DBSerializer.java3736
-rw-r--r--aai-core/src/main/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngine.java51
-rw-r--r--aai-core/src/main/java/org/onap/aai/serialization/engines/query/QueryEngine.java57
-rw-r--r--aai-core/src/test/java/org/onap/aai/HttpTestUtil.java52
-rw-r--r--aai-core/src/test/java/org/onap/aai/parsers/uri/URIToObjectTest.java51
-rw-r--r--aai-core/src/test/java/org/onap/aai/rest/EdgeNotValidAnymoreTest.java120
-rw-r--r--aai-core/src/test/java/org/onap/aai/rest/EntitlementTest.java96
-rw-r--r--aai-core/src/test/java/org/onap/aai/rest/ModelElementTest.java98
-rw-r--r--aai-core/src/test/java/org/onap/aai/rest/PserverDuplicateTest.java135
-rw-r--r--aai-core/src/test/java/org/onap/aai/rest/VipAddressListTest.java99
-rw-r--r--aai-core/src/test/java/org/onap/aai/serialization/db/DbSerializerTest.java17
-rw-r--r--aai-core/src/test/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngineTest.java157
-rw-r--r--aai-core/src/test/resources/payloads/resource/cloud-region-with-vlan.json50
-rw-r--r--aai-core/src/test/resources/payloads/resource/cloud-region.json4
-rw-r--r--aai-core/src/test/resources/payloads/resource/entitlement.json4
-rw-r--r--aai-core/src/test/resources/payloads/resource/model-element.json230
-rw-r--r--aai-core/src/test/resources/payloads/resource/model.json975
-rw-r--r--aai-core/src/test/resources/payloads/resource/vip-ipv4-address-list.json6
-rw-r--r--aai-core/src/test/resources/payloads/resource/vnf.json4
-rw-r--r--aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeIngestor.java371
-rw-r--r--aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeRule.java51
-rw-r--r--aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeRuleQuery.java33
-rw-r--r--aai-schema-ingest/src/main/java/org/onap/aai/edges/SchemaFilter.java69
-rw-r--r--aai-schema-ingest/src/main/java/org/onap/aai/edges/exceptions/AmbiguousRuleChoiceException.java6
-rw-r--r--aai-schema-ingest/src/main/java/org/onap/aai/edges/exceptions/EdgeRuleNotFoundException.java6
-rw-r--r--aai-schema/src/main/resources/onap/oxm/v15/aai_oxm_v15.xml4
34 files changed, 5911 insertions, 2365 deletions
diff --git a/aai-core/pom.xml.versionsBackup b/aai-core/pom.xml.versionsBackup
new file mode 100644
index 00000000..55c5d712
--- /dev/null
+++ b/aai-core/pom.xml.versionsBackup
@@ -0,0 +1,1063 @@
+<?xml version="1.0"?>
+<!--
+
+ ============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=========================================================
+
+-->
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.aai.aai-common</groupId>
+ <artifactId>aai-common</artifactId>
+ <version>1.3.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>aai-core</artifactId>
+ <name>aai-core</name>
+ <version>1.3.1-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <properties>
+ <sonar.language>java</sonar.language>
+ <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
+ <sonar.surefire.reportsPath>${project.build.directory}/surefire-reports</sonar.surefire.reportsPath>
+ <sonar.jacoco.reportPath>${project.build.directory}/coverage-reports/jacoco.exec</sonar.jacoco.reportPath>
+ <sonar.jacoco.reportMissing.force.zero>false</sonar.jacoco.reportMissing.force.zero>
+ <sonar.projectVersion>${project.version}</sonar.projectVersion>
+ <httpclient.version>4.5.5</httpclient.version>
+ <jackson.version>2.2.3</jackson.version>
+ <eelf.core.version>1.0.0</eelf.core.version>
+ <logback.version>1.2.3</logback.version>
+ <freemarker.version>2.3.21</freemarker.version>
+ <activemq.version>5.15.6</activemq.version>
+ <jacoco.line.coverage.limit>0.50</jacoco.line.coverage.limit>
+ <gremlin.version>3.2.2</gremlin.version>
+ <groovy.version>2.4.15</groovy.version>
+ <jetty.version>9.4.11.v20180605</jetty.version>
+
+ <!-- Start of Default ONAP Schema Properties -->
+ <aai.wiki.link>https://wiki.onap.org/</aai.wiki.link>
+ <gendoc.version>v14</gendoc.version>
+ <aai.release>onap</aai.release>
+ <schema.uri.base.path>/aai</schema.uri.base.path>
+ <schema.configuration.location>N/A</schema.configuration.location>
+ <schema.nodes.location>aai-schema/src/main/resources/${aai.release}/oxm</schema.nodes.location>
+ <schema.edges.location>aai-schema/src/main/resources/${aai.release}/dbedgerules</schema.edges.location>
+ <schema.version.depth.start>v9</schema.version.depth.start>
+ <schema.version.related.link.start>v10</schema.version.related.link.start>
+ <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>
+ <!-- End of Default ONAP Schema Properties -->
+ </properties>
+ <profiles>
+ <!-- Start of ONAP profile -->
+ <profile>
+ <id>onap</id>
+ <properties>
+ <aai.release>onap</aai.release>
+ <schema.configuration.location>N/A</schema.configuration.location>
+ <schema.nodes.location>aai-schema/src/main/resources/${aai.release}/oxm</schema.nodes.location>
+ <schema.edges.location>aai-schema/src/main/resources/${aai.release}/dbedgerules</schema.edges.location>
+ <schema.version.depth.start>v9</schema.version.depth.start>
+ <schema.version.related.link.start>v10</schema.version.related.link.start>
+ <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>
+ </properties>
+ </profile>
+ <!-- End of ONAP profile -->
+ <profile>
+ <id>generateXsd</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.1.1</version>
+ <executions>
+ <execution>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ <configuration>
+ <mainClass>org.onap.aai.util.GenerateXsd</mainClass>
+ <systemProperties>
+ <systemProperty>
+ <key>gen_version</key>
+ <value>${gendoc.version}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>gen_type</key>
+ <value>XSD</value>
+ </systemProperty>
+ <systemProperty>
+ <key>yamlresponses_url</key>
+ <value></value>
+ </systemProperty>
+ <systemProperty>
+ <key>yamlresponses_label</key>
+ <value></value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.configuration.location</key>
+ <value>${schema.configuration.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.nodes.location</key>
+ <value>${schema.nodes.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.edges.location</key>
+ <value>${schema.edges.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.list</key>
+ <value>${schema.version.list}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.depth.start</key>
+ <value>${schema.version.depth.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.depth.start</key>
+ <value>${schema.version.depth.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.related.link.start</key>
+ <value>${schema.version.related.link.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.app.root.start</key>
+ <value>${schema.version.app.root.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.edge.label.start</key>
+ <value>${schema.version.app.root.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.namespace.change.start</key>
+ <value>${schema.version.namespace.change.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.api.default</key>
+ <value>${schema.version.api.default}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.uri.base.path</key>
+ <value>${schema.uri.base.path}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>aai.release</key>
+ <value>${aai.release}</value>
+ </systemProperty>
+ </systemProperties>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>generateYaml</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.1.1</version>
+ <executions>
+ <execution>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ <configuration>
+ <mainClass>org.onap.aai.util.GenerateXsd</mainClass>
+ <systemProperties>
+ <systemProperty>
+ <key>gen_version</key>
+ <value>${gendoc.version}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>gen_type</key>
+ <value>YAML</value>
+ </systemProperty>
+ <systemProperty>
+ <key>yamlresponses_url</key>
+ <value>https://wiki.web.att.com/pages/viewpage.action?pageId=607391054
+ </value>
+ </systemProperty>
+ <systemProperty>
+ <key>yamlresponses_label</key>
+ <value>Response codes found in [response codes]</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.configuration.location</key>
+ <value>${schema.configuration.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.nodes.location</key>
+ <value>${schema.nodes.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.edges.location</key>
+ <value>${schema.edges.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.list</key>
+ <value>${schema.version.list}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.depth.start</key>
+ <value>${schema.version.depth.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.depth.start</key>
+ <value>${schema.version.depth.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.related.link.start</key>
+ <value>${schema.version.related.link.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.app.root.start</key>
+ <value>${schema.version.app.root.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.edge.label.start</key>
+ <value>${schema.version.app.root.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.namespace.change.start</key>
+ <value>${schema.version.namespace.change.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.api.default</key>
+ <value>${schema.version.api.default}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.uri.base.path</key>
+ <value>${schema.uri.base.path}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>aai.release</key>
+ <value>${aai.release}</value>
+ </systemProperty>
+ </systemProperties>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>generateHtml</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.1.1</version>
+ <executions>
+ <execution>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ <configuration>
+ <mainClass>org.onap.aai.util.swagger.GenerateSwagger</mainClass>
+ <systemProperties>
+ <property>
+ <key>aai.generate.version</key>
+ <value>${gendoc.version}</value>
+ </property>
+ <property>
+ <key>aai.wiki.link</key>
+ <value>${aai.wiki.link}</value>
+ </property>
+ <systemProperty>
+ <key>schema.configuration.location</key>
+ <value>${schema.configuration.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.nodes.location</key>
+ <value>${schema.nodes.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.edges.location</key>
+ <value>${schema.edges.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.list</key>
+ <value>${schema.version.list}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.depth.start</key>
+ <value>${schema.version.depth.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.depth.start</key>
+ <value>${schema.version.depth.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.related.link.start</key>
+ <value>${schema.version.related.link.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.app.root.start</key>
+ <value>${schema.version.app.root.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.edge.label.start</key>
+ <value>${schema.version.app.root.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.namespace.change.start</key>
+ <value>${schema.version.namespace.change.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.api.default</key>
+ <value>${schema.version.api.default}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.uri.base.path</key>
+ <value>${schema.uri.base.path}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>aai.release</key>
+ <value>${aai.release}</value>
+ </systemProperty>
+ </systemProperties>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>autoGenerate</id>
+ <activation>
+ <property>
+ <name>aai.generate.schema</name>
+ <value>!false</value>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.1.1</version>
+ <executions>
+ <execution>
+ <id>autoGenerateXsd</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ <configuration>
+ <mainClass>org.onap.aai.util.GenerateXsd</mainClass>
+ <systemProperties>
+ <systemProperty>
+ <key>gen_version</key>
+ <value>ALL</value>
+ </systemProperty>
+ <systemProperty>
+ <key>gen_type</key>
+ <value>XSD</value>
+ </systemProperty>
+ <systemProperty>
+ <key>yamlresponses_url</key>
+ <value></value>
+ </systemProperty>
+ <systemProperty>
+ <key>yamlresponses_label</key>
+ <value></value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.configuration.location</key>
+ <value>${schema.configuration.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.nodes.location</key>
+ <value>${schema.nodes.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.edges.location</key>
+ <value>${schema.edges.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.list</key>
+ <value>${schema.version.list}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.depth.start</key>
+ <value>${schema.version.depth.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.depth.start</key>
+ <value>${schema.version.depth.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.related.link.start</key>
+ <value>${schema.version.related.link.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.app.root.start</key>
+ <value>${schema.version.app.root.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.edge.label.start</key>
+ <value>${schema.version.app.root.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.namespace.change.start</key>
+ <value>${schema.version.namespace.change.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.api.default</key>
+ <value>${schema.version.api.default}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.uri.base.path</key>
+ <value>${schema.uri.base.path}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>aai.release</key>
+ <value>${aai.release}</value>
+ </systemProperty>
+ </systemProperties>
+ </configuration>
+ </execution>
+ <execution>
+ <id>autoGenerateYaml</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ <configuration>
+ <mainClass>org.onap.aai.util.GenerateXsd</mainClass>
+ <systemProperties>
+ <systemProperty>
+ <key>gen_version</key>
+ <value>ALL</value>
+ </systemProperty>
+ <systemProperty>
+ <key>gen_type</key>
+ <value>YAML</value>
+ </systemProperty>
+ <systemProperty>
+ <key>yamlresponses_url</key>
+ <value>https://wiki.web.att.com/pages/viewpage.action?pageId=607391054
+ </value>
+ </systemProperty>
+ <systemProperty>
+ <key>yamlresponses_label</key>
+ <value>Response codes found in [response codes]</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.configuration.location</key>
+ <value>${schema.configuration.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.nodes.location</key>
+ <value>${schema.nodes.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.edges.location</key>
+ <value>${schema.edges.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.list</key>
+ <value>${schema.version.list}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.depth.start</key>
+ <value>${schema.version.depth.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.depth.start</key>
+ <value>${schema.version.depth.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.related.link.start</key>
+ <value>${schema.version.related.link.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.app.root.start</key>
+ <value>${schema.version.app.root.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.edge.label.start</key>
+ <value>${schema.version.app.root.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.namespace.change.start</key>
+ <value>${schema.version.namespace.change.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.api.default</key>
+ <value>${schema.version.api.default}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>aai.release</key>
+ <value>${aai.release}</value>
+ </systemProperty>
+ </systemProperties>
+ </configuration>
+ </execution>
+ <execution>
+ <id>autoGenerateHtml</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ <configuration>
+ <mainClass>org.onap.aai.util.AutoGenerateHtml</mainClass>
+ <systemProperties>
+ <property>
+ <key>aai.generate.version</key>
+ <value>${gendoc.version}</value>
+ </property>
+ <property>
+ <key>aai.wiki.link</key>
+ <value>${aai.wiki.link}</value>
+ </property>
+ <systemProperty>
+ <key>schema.configuration.location</key>
+ <value>${schema.configuration.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.nodes.location</key>
+ <value>${schema.nodes.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.edges.location</key>
+ <value>${schema.edges.location}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.list</key>
+ <value>${schema.version.list}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.depth.start</key>
+ <value>${schema.version.depth.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.depth.start</key>
+ <value>${schema.version.depth.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.related.link.start</key>
+ <value>${schema.version.related.link.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.app.root.start</key>
+ <value>${schema.version.app.root.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.edge.label.start</key>
+ <value>${schema.version.app.root.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.namespace.change.start</key>
+ <value>${schema.version.namespace.change.start}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>schema.version.api.default</key>
+ <value>${schema.version.api.default}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>aai.release</key>
+ <value>${aai.release}</value>
+ </systemProperty>
+ </systemProperties>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.12.4</version>
+ <configuration>
+ <argLine>-noverify ${argLine}</argLine>
+ <systemPropertyVariables>
+ <AJSC_HOME>.</AJSC_HOME>
+ <BUNDLECONFIG_DIR>bundleconfig-local</BUNDLECONFIG_DIR>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>sonar-maven-plugin</artifactId>
+ <version>3.2</version>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>0.7.7.201606060606</version>
+ <configuration>
+ <dumpOnExit>true</dumpOnExit>
+ </configuration>
+ <executions>
+ <execution>
+ <id>jacoco-initialize-unit-tests</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ <configuration>
+ <destFile>${project.build.directory}/coverage-reports/jacoco.exec</destFile>
+ <!-- <append>true</append> -->
+ </configuration>
+ </execution>
+ <execution>
+ <id>post-unit-test</id>
+ <phase>test</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ <configuration>
+ <!-- Sets the path to the file which contains the execution data. -->
+ <dataFile>${project.build.directory}/coverage-reports/jacoco.exec</dataFile>
+ <!-- Sets the output directory for the code coverage report. -->
+ <outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>default-check</id>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ <configuration>
+ <dataFile>${project.build.directory}/coverage-reports/jacoco.exec</dataFile>
+ <rules>
+ <rule implementation="org.jacoco.maven.RuleConfiguration">
+ <element>BUNDLE</element>
+ <limits>
+ <limit implementation="org.jacoco.report.check.Limit">
+ <counter>LINE</counter>
+ <value>COVEREDRATIO</value>
+ <minimum>${jacoco.line.coverage.limit}</minimum>
+ </limit>
+ </limits>
+ </rule>
+ </rules>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <!-- explicitly define maven-deploy-plugin after other to force exec order -->
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>nexus-staging-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.aai.aai-common</groupId>
+ <artifactId>aai-schema-ingest</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.aai.aai-common</groupId>
+ <artifactId>aai-annotations</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-text</artifactId>
+ <version>1.1</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.att.eelf</groupId>
+ <artifactId>eelf-core</artifactId>
+ <version>${eelf.core.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-core-asl</artifactId>
+ <version>1.9.13</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-mapper-asl</artifactId>
+ <version>1.9.13</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-junit</artifactId>
+ <version>2.0.0.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ <version>1.3</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>1.10.19</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>19.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.janusgraph</groupId>
+ <artifactId>janusgraph-core</artifactId>
+ <version>0.2.0</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>4.3.18.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>4.3.18.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ <version>2.2.11</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.persistence</groupId>
+ <artifactId>eclipselink</artifactId>
+ <version>2.6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.7</version>
+ </dependency>
+ <dependency>
+ <groupId>com.jayway.jsonpath</groupId>
+ <artifactId>json-path</artifactId>
+ <version>2.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>${jetty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.module</groupId>
+ <artifactId>jackson-module-jaxb-annotations</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-core</artifactId>
+ <version>1.18</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>1.18</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-json</artifactId>
+ <version>1.18</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <version>2.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tinkerpop</groupId>
+ <artifactId>gremlin-core</artifactId>
+ <version>${gremlin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tinkerpop</groupId>
+ <artifactId>tinkergraph-gremlin</artifactId>
+ <version>${gremlin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.5</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.dataformat</groupId>
+ <artifactId>jackson-dataformat-yaml</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ <version>1.0.b2</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-cli</groupId>
+ <artifactId>commons-cli</artifactId>
+ <version>1.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.beust</groupId>
+ <artifactId>jcommander</artifactId>
+ <version>1.48</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20160810</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.bazaarvoice.jolt</groupId>
+ <artifactId>jolt-complete</artifactId>
+ <version>0.0.24</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <version>${logback.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>${logback.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-access</artifactId>
+ <version>${logback.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.activemq</groupId>
+ <artifactId>activemq-broker</artifactId>
+ <version>${activemq.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.opencsv</groupId>
+ <artifactId>opencsv</artifactId>
+ <version>3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.freemarker</groupId>
+ <artifactId>freemarker</artifactId>
+ <version>${freemarker.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.github.fge</groupId>
+ <artifactId>json-patch</artifactId>
+ <version>1.9</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy</artifactId>
+ <version>${groovy.version}</version>
+ <classifier>indy</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>4.3.18.RELEASE</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-test</artifactId>
+ <version>1.5.1.RELEASE</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-javaagent</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.skyscreamer</groupId>
+ <artifactId>jsonassert</artifactId>
+ <version>1.4.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>${httpclient.version}</version>
+ </dependency>
+ <dependency>
+ <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>
+ <artifactId>spring-jms</artifactId>
+ <version>4.3.18.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.8.11</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.8.11</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>2.8.11</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.17</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot</artifactId>
+ <version>1.5.15.RELEASE</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <!-- Plugins and repositories -->
+ <pluginRepositories>
+ <pluginRepository>
+ <id>central</id>
+ <url>http://repo1.maven.org/maven2</url>
+ </pluginRepository>
+ <pluginRepository>
+ <id>EvoSuite</id>
+ <name>EvoSuite Repository</name>
+ <url>http://www.evosuite.org/m2</url>
+ </pluginRepository>
+ </pluginRepositories>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.10.4</version>
+ <configuration>
+ <failOnError>false</failOnError>
+ <doclet>org.umlgraph.doclet.UmlGraphDoc</doclet>
+ <docletArtifact>
+ <groupId>org.umlgraph</groupId>
+ <artifactId>umlgraph</artifactId>
+ <version>5.6</version>
+ </docletArtifact>
+ <additionalparam>-views</additionalparam>
+ <useStandardDocletOptions>true</useStandardDocletOptions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+</project>
diff --git a/aai-core/src/main/java/org/onap/aai/config/IntrospectionConfig.java b/aai-core/src/main/java/org/onap/aai/config/IntrospectionConfig.java
index aa4ec1a1..e737f08d 100644
--- a/aai-core/src/main/java/org/onap/aai/config/IntrospectionConfig.java
+++ b/aai-core/src/main/java/org/onap/aai/config/IntrospectionConfig.java
@@ -21,14 +21,16 @@
*/
package org.onap.aai.config;
+import org.onap.aai.schema.enums.ObjectMetadata;
import org.onap.aai.setup.SchemaVersion;
import org.onap.aai.setup.SchemaVersions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
import org.onap.aai.introspection.LoaderFactory;
import org.onap.aai.introspection.MoxyLoader;
diff --git a/aai-core/src/main/java/org/onap/aai/introspection/Introspector.java b/aai-core/src/main/java/org/onap/aai/introspection/Introspector.java
index c7520dd4..269d6330 100644
--- a/aai-core/src/main/java/org/onap/aai/introspection/Introspector.java
+++ b/aai-core/src/main/java/org/onap/aai/introspection/Introspector.java
@@ -36,6 +36,7 @@ import org.onap.aai.workarounds.NamingExceptions;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
+import java.util.stream.Collectors;
public abstract class Introspector implements Cloneable {
@@ -57,25 +58,25 @@ public abstract class Introspector implements Cloneable {
protected String convertPropertyName (String name) {
return CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, name);
}
-
+
protected abstract Object get(String name);
protected abstract void set(String name, Object value);
/**
- *
+ *
* @param name the property name you'd like to retrieve the value for
* @return the value of the property
*/
public <T> T getValue(String name) {
String convertedName = convertPropertyName(name);
Object result = null;
-
+
if (this.hasProperty(name)) {
result = this.get(convertedName);
} else {
/* property not found - slightly ambiguous */
return null;
}
-
+
Class<?> clazz = this.getClass(name);
if (this.isListType(name) && result == null) {
try {
@@ -88,18 +89,18 @@ public abstract class Introspector implements Cloneable {
return (T)result;
}
-
+
public Introspector getWrappedValue(String name) {
String convertedName = convertPropertyName(name);
Object value = null;
-
+
if (this.hasProperty(name)) {
value = this.get(convertedName);
} else {
/* property not found - slightly ambiguous */
return null;
}
-
+
Class<?> clazz = this.getClass(name);
if (this.isListType(name) && value == null) {
try {
@@ -115,9 +116,9 @@ public abstract class Introspector implements Cloneable {
//no value
return null;
}
-
+
}
-
+
public List<Introspector> getWrappedListValue(String name) {
String convertedName = convertPropertyName(name);
Object value = null;
@@ -141,17 +142,17 @@ public abstract class Introspector implements Cloneable {
LOGGER.warn(e.getMessage(),e);
}
}
-
+
List<Object> valueList = (List<Object>)value;
-
+
for (Object item : valueList) {
resultList.add(IntrospectorFactory.newInstance(this.getModelType(), item));
}
-
+
return resultList;
-
+
}
-
+
public Object castValueAccordingToSchema(String name, Object obj) {
Object result = obj;
Class<?> nameClass = this.getClass(name);
@@ -159,11 +160,11 @@ public abstract class Introspector implements Cloneable {
throw new IllegalArgumentException("property: " + name + " does not exist on " + this.getDbName());
}
if (obj != null) {
-
+
try {
if (!obj.getClass().getName().equals(nameClass.getName())) {
if (nameClass.isPrimitive()) {
- nameClass = ClassUtils.primitiveToWrapper(nameClass);
+ nameClass = ClassUtils.primitiveToWrapper(nameClass);
result = nameClass.getConstructor(String.class).newInstance(obj.toString());
}
if (obj instanceof String) {
@@ -180,35 +181,35 @@ public abstract class Introspector implements Cloneable {
}
return result;
}
-
+
public List<Object> castValueAccordingToSchema(String name, List<?> objs) {
List<Object> result = new ArrayList<>();
-
+
for (Object item : objs) {
result.add(this.castValueAccordingToSchema(name, item));
}
-
+
return result;
-
+
}
/**
- *
+ *
* @param name the property name you'd like to set the value of
* @param obj the value to be set
* @return
*/
public void setValue(String name, Object obj) throws IllegalArgumentException {
Object box = this.castValueAccordingToSchema(name, obj);
-
+
name = convertPropertyName(name);
this.set(name, box);
}
/**
- *
+ *
* @return a list of all the properties available on the object
*/
public abstract Set<String> getProperties();
-
+
public Set<String> getProperties(PropertyPredicate<Introspector, String> p) {
final Set<String> temp = new LinkedHashSet<>();
this.getProperties().stream().filter(item -> {
@@ -217,22 +218,30 @@ public abstract class Introspector implements Cloneable {
temp.add(item);
});
final Set<String> result = Collections.unmodifiableSet(temp);
-
+
return result;
-
+
}
+
+ public Set<String> getSimpleProperties(PropertyPredicate<Introspector, String> p){
+ return this.getProperties()
+ .stream()
+ .filter(item -> p.test(this, item))
+ .filter(this::isSimpleType)
+ .collect(Collectors.toSet());
+ }
/**
- *
+ *
* @return a list of the required properties on the object
*/
public abstract Set<String> getRequiredProperties();
/**
- *
+ *
* @return a list of the properties that can be used to query the object in the db
*/
public abstract Set<String> getKeys();
/**
- *
+ *
* @return a list of the all key properties for this object
*/
public Set<String> getAllKeys() {
@@ -274,7 +283,7 @@ public abstract class Introspector implements Cloneable {
result = this.indexedProperties;
return result;
}
-
+
public Set<String> getUniqueProperties() {
Set<String> result = null;
if (this.uniqueProperties == null) {
@@ -292,7 +301,7 @@ public abstract class Introspector implements Cloneable {
result = this.uniqueProperties;
return result;
}
-
+
public Set<String> getDependentOn() {
String dependentOn = this.getMetadata(ObjectMetadata.DEPENDENT_ON);
if (dependentOn == null) {
@@ -301,21 +310,21 @@ public abstract class Introspector implements Cloneable {
return new LinkedHashSet<>(Arrays.asList(dependentOn.split(",")));
}
/**
- *
+ *
* @param name
* @return the string name of the java class of the named property
*/
public String getType(String name) {
Class<?> resultClass = this.getClass(name);
String result = "";
-
+
if (resultClass != null) {
result = resultClass.getName();
if (result.equals("java.util.ArrayList")) {
result = "java.util.List";
}
}
-
+
return result;
}
/**
@@ -327,33 +336,33 @@ public abstract class Introspector implements Cloneable {
public String getGenericType(String name) {
Class<?> resultClass = this.getGenericTypeClass(name);
String result = "";
-
+
if (resultClass != null) {
result = resultClass.getName();
}
-
+
return result;
}
/**
- *
+ *
* @return the string name of the java class of the underlying object
*/
public abstract String getJavaClassName();
-
+
/**
- *
+ *
* @param name the property name
* @return the Class object
*/
public abstract Class<?> getClass(String name);
-
+
public abstract Class<?> getGenericTypeClass(String name);
/**
- *
+ *
* @param name the property name
* @return a new instance of the underlying type of this property
- * @throws AAIUnknownObjectException
+ * @throws AAIUnknownObjectException
*/
public Object newInstanceOfProperty(String name) throws AAIUnknownObjectException {
String type = this.getType(name);
@@ -364,22 +373,22 @@ public abstract class Introspector implements Cloneable {
String type = this.getGenericType(name);
return loader.objectFromName(type);
}
-
-
+
+
public Introspector newIntrospectorInstanceOfProperty(String name) throws AAIUnknownObjectException {
-
+
Introspector result = IntrospectorFactory.newInstance(this.getModelType(), this.newInstanceOfProperty(name));
-
+
return result;
-
+
}
-
+
public Introspector newIntrospectorInstanceOfNestedProperty(String name) throws AAIUnknownObjectException {
-
+
Introspector result = IntrospectorFactory.newInstance(this.getModelType(), this.newInstanceOfNestedProperty(name));
-
+
return result;
-
+
}
/**
* Is this type not a Java String or primitive
@@ -388,56 +397,56 @@ public abstract class Introspector implements Cloneable {
*/
public boolean isComplexType(String name) {
String result = this.getType(name);
-
+
if (result.contains("aai") || result.equals("java.lang.Object")) {
return true;
} else {
return false;
}
}
-
+
public boolean isComplexGenericType(String name) {
String result = this.getGenericType(name);
-
+
if (result.contains("aai")) {
return true;
} else {
return false;
}
}
-
+
public boolean isSimpleType(String name) {
return !(this.isComplexType(name) || this.isListType(name));
}
-
+
public boolean isSimpleGenericType(String name) {
return !this.isComplexGenericType(name);
}
public boolean isListType(String name) {
String result = this.getType(name);
-
+
if (result.contains("java.util.List")) {
return true;
} else {
return false;
}
}
-
+
public boolean isContainer() {
Set<String> props = this.getProperties();
boolean result = false;
if (props.size() == 1 && this.isListType(props.iterator().next())) {
result = true;
}
-
+
return result;
}
-
+
public abstract String getChildName();
public String getChildDBName() {
String result = this.getChildName();
-
+
result = namingException.getDBName(result);
return result;
}
@@ -447,10 +456,10 @@ public abstract class Introspector implements Cloneable {
String lowerHyphen = this.getName();
lowerHyphen = namingException.getDBName(lowerHyphen);
-
+
return lowerHyphen;
}
-
+
public abstract ModelType getModelType();
public boolean hasChild(Introspector child) {
@@ -474,7 +483,7 @@ public abstract class Introspector implements Cloneable {
}
return result;
}
-
+
public void setURIChain(String uri) {
this.uriChain = uri;
}
@@ -488,21 +497,21 @@ public abstract class Introspector implements Cloneable {
if (this.isContainer()) {
result += "/" + this.getName();
} else {
-
+
if (container != null) {
result += "/" + container;
}
result += "/" + this.getDbName() + "/" + this.findKey();
-
+
if (namespace != null && !namespace.equals("")) {
result = "/" + namespace + result;
}
}
-
+
return result;
}
-
+
public String getGenericURI() {
String result = "";
if (this.isContainer()) {
@@ -513,10 +522,10 @@ public abstract class Introspector implements Cloneable {
result += "/{" + this.getDbName() + "-" + key + "}";
}
}
-
+
return result;
}
-
+
public String getFullGenericURI() {
String result = "";
String namespace = this.getMetadata(ObjectMetadata.NAMESPACE);
@@ -537,33 +546,33 @@ public abstract class Introspector implements Cloneable {
if (namespace != null && !namespace.equals("")) {
result = "/" + namespace + result;
}
-
+
}
-
+
return result;
}
public abstract String preProcessKey(String key);
-
+
protected abstract String findKey() throws UnsupportedEncodingException;
-
+
public abstract String marshal(MarshallerProperties properties);
-
+
public abstract Object clone();
public abstract Object getUnderlyingObject();
-
+
public String marshal(boolean formatted) {
MarshallerProperties properties =
new MarshallerProperties.Builder(MediaType.APPLICATION_JSON_TYPE).formatted(formatted).build();
-
+
return marshal(properties);
}
public String makeSingular(String word) {
-
+
String result = word;
result = result.replaceAll("(?:([ho])es|s)$", "");
-
+
if (result.equals("ClassesOfService")) {
result = "ClassOfService";
} else if (result.equals("CvlanTag")) {
@@ -573,10 +582,10 @@ public abstract class Introspector implements Cloneable {
}
return result;
}
-
+
protected String makePlural(String word) {
String result = word;
-
+
if (result.equals("cvlan-tag-entry")) {
return "cvlan-tags";
} else if (result.equals("class-of-service")) {
@@ -590,7 +599,7 @@ public abstract class Introspector implements Cloneable {
if (result.equals("classes-of-services")) {
result = "classes-of-service";
}*/
-
+
return result;
}
@@ -599,21 +608,22 @@ public abstract class Introspector implements Cloneable {
public Optional<String> getPropertyMetadata(String propName, PropertyMetadata metadataName) {
final String resultValue = this.getPropertyMetadata(propName).getOrDefault(metadataName, "");
Optional<String> result = Optional.empty();
-
+
if (!resultValue.isEmpty()) {
result = Optional.of(resultValue);
}
return result;
-
+
}
public abstract SchemaVersion getVersion();
public Loader getLoader() {
return this.loader;
}
-
+
public boolean isTopLevel() {
-
+
return this.getMetadata(ObjectMetadata.NAMESPACE) != null;
}
+
}
diff --git a/aai-core/src/main/java/org/onap/aai/introspection/JSONStrategy.java b/aai-core/src/main/java/org/onap/aai/introspection/JSONStrategy.java
index b1447d8f..d54a9833 100644
--- a/aai-core/src/main/java/org/onap/aai/introspection/JSONStrategy.java
+++ b/aai-core/src/main/java/org/onap/aai/introspection/JSONStrategy.java
@@ -46,47 +46,47 @@ public class JSONStrategy extends Introspector {
throw new IllegalArgumentException("This object has no named type.");
}
}
-
+
protected JSONStrategy(Object o, String namedType) {
super(o);
json = (JSONObject)o;
this.namedType = namedType;
-
+
}
-
+
@Override
public boolean hasProperty(String name) {
- //TODO
+ //TODO
return true;
}
@Override
public Object getValue(String name) {
Object result = "";
result = json.get(name);
-
+
return result;
}
@Override
public void setValue(String name, Object obj) {
json.put(name, obj);
-
+
}
@Override
public Object getUnderlyingObject() {
return this.json;
}
-
+
@Override
public Set<String> getProperties() {
Set<String> result = json.keySet();
return result;
}
-
+
@Override
public Set<String> getRequiredProperties() {
//unknowable
-
+
return this.getProperties();
}
@@ -109,11 +109,11 @@ public class JSONStrategy extends Introspector {
if (resultClass != null) {
result = resultClass.getName();
}
-
+
if (result.equals("org.json.simple.JSONArray")) {
result = "java.util.List";
}
-
+
return result;
}
@@ -136,7 +136,7 @@ public class JSONStrategy extends Introspector {
public Class<?> getClass(String name) {
Class<?> result = null;
result = json.get(name).getClass();
-
+
return result;
}
@@ -148,7 +148,7 @@ public class JSONStrategy extends Introspector {
if (resultObject.getClass().getName().equals("org.json.simple.JSONArray")) {
resultClass = ((List)resultObject).get(0).getClass();
}
-
+
return resultClass;
}
@@ -169,43 +169,43 @@ public class JSONStrategy extends Introspector {
return null;
}
}
-
+
@Override
public boolean isComplexType(String name) {
String result = this.getType(name);
-
+
if (result.contains("JSONObject")) {
return true;
} else {
return false;
}
-
+
}
-
+
@Override
public boolean isComplexGenericType(String name) {
String result = this.getGenericType(name);
-
+
if (result.contains("JSONObject")) {
return true;
} else {
return false;
}
-
+
}
-
+
@Override
public boolean isListType(String name) {
String result = this.getType(name);
-
+
if (result.contains("java.util.List")) {
return true;
} else {
return false;
}
-
+
}
-
+
@Override
public boolean isContainer() {
Set<String> props = this.getProperties();
@@ -213,66 +213,66 @@ public class JSONStrategy extends Introspector {
if (props.size() == 1 && this.isListType(props.iterator().next())) {
result = true;
}
-
+
return result;
}
@Override
protected String findKey() {
return "";
}
-
+
@Override
public String getName() {
return this.namedType;
}
-
+
@Override
public String getDbName() {
return this.getName();
}
-
+
@Override
public String getURI() {
-
- // use a UUID for now
+
+ // use a UUID for now
return UUID.randomUUID().toString();
}
-
+
@Override
public String getGenericURI() {
-
+
//there is none defined for this
return "";
}
-
+
@Override
public String preProcessKey (String key) {
-
+
// don't do anything with it
return key;
-
+
}
-
+
@Override
public String marshal(MarshallerProperties properties) {
//TODO
return null;
}
-
+
@Override
public Object clone() {
//TODO
return null;
}
-
+
/*@Override
public String findEdgeName(String parent, String child) {
-
+
// Always has for now
return "has";
-
+
}*/
-
+
@Override
public ModelType getModelType() {
return ModelType.JSON;
@@ -341,7 +341,7 @@ public class JSONStrategy extends Introspector {
@Override
protected void set(String name, Object value) {
// TODO Auto-generated method stub
-
+
}
@Override
diff --git a/aai-core/src/main/java/org/onap/aai/introspection/Loader.java b/aai-core/src/main/java/org/onap/aai/introspection/Loader.java
index 3a69e56e..cae4cbb7 100644
--- a/aai-core/src/main/java/org/onap/aai/introspection/Loader.java
+++ b/aai-core/src/main/java/org/onap/aai/introspection/Loader.java
@@ -25,12 +25,13 @@ import org.onap.aai.restcore.MediaType;
import org.onap.aai.setup.SchemaVersion;
import java.util.Map;
+import java.util.Set;
public abstract class Loader {
private final SchemaVersion version;
private final ModelType modelType;
-
+
/**
* Instantiates a new loader.
*
@@ -41,32 +42,32 @@ public abstract class Loader {
this.version = version;
this.modelType = modelType;
}
-
+
/**
* Process.
*
* @param version the version
*/
protected abstract void process(SchemaVersion version);
-
+
/**
* Object from name.
*
* @param name the name
* @return the object
- * @throws AAIUnknownObjectException
+ * @throws AAIUnknownObjectException
*/
public abstract Object objectFromName(String name) throws AAIUnknownObjectException;
-
+
/**
* Introspector from name.
*
* @param name the name
* @return the introspector
- * @throws AAIUnknownObjectException
+ * @throws AAIUnknownObjectException
*/
public abstract Introspector introspectorFromName(String name) throws AAIUnknownObjectException;
-
+
/**
* Unmarshal.
*
@@ -76,7 +77,7 @@ public abstract class Loader {
* @return the introspector
*/
public abstract Introspector unmarshal(String type, String json, MediaType mediaType) throws AAIUnmarshallingException;
-
+
/**
* Unmarshal.
*
@@ -88,7 +89,7 @@ public abstract class Loader {
return unmarshal(type, json, MediaType.APPLICATION_JSON_TYPE);
}
-
+
/**
* Gets the model type.
*
@@ -97,7 +98,7 @@ public abstract class Loader {
public ModelType getModelType() {
return this.modelType;
}
-
+
/**
* Gets the version.
*
@@ -106,6 +107,8 @@ public abstract class Loader {
public SchemaVersion getVersion() {
return this.version;
}
-
+
public abstract Map<String, Introspector> getAllObjects();
+
+ public abstract Set<String> getNamedPropNodes();
}
diff --git a/aai-core/src/main/java/org/onap/aai/introspection/MoxyLoader.java b/aai-core/src/main/java/org/onap/aai/introspection/MoxyLoader.java
index 82504550..fa52d62f 100644
--- a/aai-core/src/main/java/org/onap/aai/introspection/MoxyLoader.java
+++ b/aai-core/src/main/java/org/onap/aai/introspection/MoxyLoader.java
@@ -34,6 +34,7 @@ import org.onap.aai.logging.ErrorLogHelper;
import org.onap.aai.logging.LogFormatTools;
import org.onap.aai.nodes.NodeIngestor;
import org.onap.aai.restcore.MediaType;
+import org.onap.aai.schema.enums.ObjectMetadata;
import org.onap.aai.setup.SchemaVersion;
import org.onap.aai.workarounds.NamingExceptions;
import org.springframework.stereotype.Component;
@@ -44,6 +45,7 @@ import java.io.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
public class MoxyLoader extends Loader {
@@ -52,9 +54,11 @@ public class MoxyLoader extends Loader {
private Map<String, Introspector> allObjs = null;
private Map<SchemaVersion, MoxyLoader> moxyLoaderFactory;
-
+
private NodeIngestor nodeIngestor;
+ private Set<String> namedProps;
+
public MoxyLoader(SchemaVersion version, NodeIngestor nodeIngestor) {
super(version, ModelType.MOXY);
this.nodeIngestor = nodeIngestor;
@@ -67,14 +71,14 @@ public class MoxyLoader extends Loader {
}
/**
* {@inheritDoc}
- * @throws AAIUnknownObjectException
+ * @throws AAIUnknownObjectException
*/
@Override
public Introspector introspectorFromName(String name) throws AAIUnknownObjectException {
return IntrospectorFactory.newInstance(ModelType.MOXY, objectFromName(name));
}
-
+
/**
* {@inheritDoc}
*/
@@ -93,7 +97,7 @@ public class MoxyLoader extends Loader {
} else {
upperCamel = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, sanitizedName);
}
-
+
try {
final DynamicEntity result = jaxbContext.newDynamicEntity(upperCamel);
@@ -115,14 +119,14 @@ public class MoxyLoader extends Loader {
* We need to have just same JaxbContext for each version
*/
jaxbContext = nodeIngestor.getContextForVersion(version);
-
+
}
/**
* {@inheritDoc}
*/
@Override
- public Introspector unmarshal(String type, String json, MediaType mediaType) throws AAIUnmarshallingException {
+ public Introspector unmarshal(String type, String json, MediaType mediaType) throws AAIUnmarshallingException {
try {
final Object clazz = objectFromName(type);
final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
@@ -143,7 +147,7 @@ public class MoxyLoader extends Loader {
throw new AAIUnmarshallingException("Could not unmarshall: " + e.getMessage(), e);
}
}
-
+
@Override
public Map<String, Introspector> getAllObjects() {
if (this.allObjs != null) {
@@ -163,7 +167,7 @@ public class MoxyLoader extends Loader {
return allObjs;
}
}
-
+
private Set<String> objectsInVersion() {
Set<String> result = new HashSet<>();
@@ -177,7 +181,21 @@ public class MoxyLoader extends Loader {
//result.remove("EdgePropNames");
return result;
}
-
+
+ @Override
+ public Set<String> getNamedPropNodes(){
+
+ if(namedProps == null){
+ namedProps = getAllObjects()
+ .entrySet()
+ .stream()
+ .filter(
+ (entry) -> entry.getValue().getMetadata(ObjectMetadata.NAME_PROPS) != null
+ ).map(entry -> entry.getKey()).collect(Collectors.toSet());
+ }
+
+ return namedProps;
+ }
public DynamicJAXBContext getJAXBContext() {
return this.jaxbContext;
}
diff --git a/aai-core/src/main/java/org/onap/aai/introspection/MoxyStrategy.java b/aai-core/src/main/java/org/onap/aai/introspection/MoxyStrategy.java
index ecf31253..f0d487e8 100644
--- a/aai-core/src/main/java/org/onap/aai/introspection/MoxyStrategy.java
+++ b/aai-core/src/main/java/org/onap/aai/introspection/MoxyStrategy.java
@@ -51,9 +51,10 @@ import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.Map.Entry;
+import java.util.stream.Collectors;
public class MoxyStrategy extends Introspector {
-
+
private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(MoxyStrategy.class);
private DynamicEntity internalObject = null;
private DynamicType internalType = null;
@@ -67,9 +68,9 @@ public class MoxyStrategy extends Introspector {
private Set<String> requiredProperties = null;
private boolean isInitialized = false;
-
+
private NodeIngestor nodeIngestor;
-
+
protected MoxyStrategy(Object obj) {
super(obj);
/* must look up the correct jaxbcontext for this object */
@@ -81,19 +82,19 @@ public class MoxyStrategy extends Introspector {
jaxbContext = nodeIngestor.getContextForVersion(version);
String simpleName = internalObject.getClass().getName();
internalType = jaxbContext.getDynamicType(simpleName);
-
+
cd = internalType.getDescriptor();
try {
marshaller = jaxbContext.createMarshaller();
-
+
unmarshaller = jaxbContext.createUnmarshaller();
-
+
} catch (JAXBException e) {
}
}
-
+
private void init() {
isInitialized = true;
@@ -104,13 +105,13 @@ public class MoxyStrategy extends Introspector {
}
props = Collections.unmodifiableSet(props);
this.properties = props;
-
+
Set<String> requiredProps = new LinkedHashSet<>();
requiredProps = new LinkedHashSet<>();
for (DatabaseMapping dm : cd.getMappings()) {
- if (dm.getField() instanceof XMLField) {
+ if (dm.getField() instanceof XMLField) {
XMLField x = (XMLField)dm.getField();
- if (x != null) {
+ if (x != null) {
if (x.isRequired()) {
requiredProps.add(this.removeXPathDescriptor(x.getName()));
}
@@ -119,25 +120,25 @@ public class MoxyStrategy extends Introspector {
}
requiredProps = Collections.unmodifiableSet(requiredProps);
this.requiredProperties = requiredProps;
-
+
Set<String> keys = new LinkedHashSet<>();
-
+
for (String name : internalType.getDescriptor().getPrimaryKeyFieldNames()) {
keys.add(this.removeXPathDescriptor(name));
}
keys = Collections.unmodifiableSet(keys);
this.keys = keys;
-
-
+
+
}
-
+
@Override
public boolean hasProperty(String name) {
String convertedName = convertPropertyName(name);
- return internalType.containsProperty(convertedName);
+ return internalType.containsProperty(convertedName);
}
-
+
@Override
public Object get(String name) {
return internalObject.get(name);
@@ -145,7 +146,7 @@ public class MoxyStrategy extends Introspector {
@Override
public void set(String name, Object obj) throws IllegalArgumentException {
-
+
internalObject.set(name, obj);
}
@@ -157,7 +158,7 @@ public class MoxyStrategy extends Introspector {
}
return this.properties;
-
+
}
@Override
@@ -179,7 +180,7 @@ public class MoxyStrategy extends Introspector {
return this.keys;
}
-
+
@Override
public Map<PropertyMetadata, String> getPropertyMetadata(String prop) {
String propName = this.convertPropertyName(prop);
@@ -192,7 +193,7 @@ public class MoxyStrategy extends Introspector {
PropertyMetadata.valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, (String)entry.getKey())), (String)entry.getValue());
}
}
-
+
return result;
}
@@ -200,8 +201,8 @@ public class MoxyStrategy extends Introspector {
public String getJavaClassName() {
return internalObject.getClass().getName();
}
-
-
+
+
@Override
public Class<?> getClass(String name) {
@@ -211,7 +212,7 @@ public class MoxyStrategy extends Introspector {
if (internalType.getPropertyType(name) == null) {
if (cd.getMappingForAttributeName(name) instanceof XMLCompositeDirectCollectionMapping) {
resultClass = cd.getMappingForAttributeName(name).getContainerPolicy().getContainerClass();
-
+
} else if (cd.getMappingForAttributeName(name) instanceof XMLCompositeCollectionMapping) {
resultClass = cd.getMappingForAttributeName(name).getContainerPolicy().getContainerClass();
} else {
@@ -243,7 +244,7 @@ public class MoxyStrategy extends Introspector {
resultClass = cd.getMappingForAttributeName(name).getReferenceDescriptor().getJavaClass();
}
}
-
+
return resultClass;
}
@@ -251,20 +252,20 @@ public class MoxyStrategy extends Introspector {
public Object getUnderlyingObject() {
return this.internalObject;
}
-
+
@Override
public String getChildName() {
-
+
String className = internalObject.getClass().getSimpleName();
String lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
-
+
if (this.isContainer()) {
lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,this.getGenericTypeClass(this.getProperties().iterator().next()).getSimpleName());
}
-
+
return lowerHyphen;
}
-
+
@Override
public String getName() {
String className = internalObject.getClass().getSimpleName();
@@ -273,11 +274,11 @@ public class MoxyStrategy extends Introspector {
if (this.isContainer()) {
lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,this.getGenericTypeClass(this.getProperties().get(0)).getSimpleName());
}*/
-
+
return lowerHyphen;
}
-
+
@Override
public String getObjectId() throws UnsupportedEncodingException {
String result = "";
@@ -285,17 +286,17 @@ public class MoxyStrategy extends Introspector {
if (this.isContainer()) {
result += "/" + this.getName();
} else {
-
+
if (container != null) {
result += "/" + container;
}
result += "/" + this.getDbName() + "/" + this.findKey();
-
+
}
-
+
return result;
}
-
+
@Override
protected String findKey() throws UnsupportedEncodingException {
Set<String> keys = null;
@@ -305,10 +306,10 @@ public class MoxyStrategy extends Introspector {
String value = UriUtils.encode(this.getValue(key).toString(), "UTF-8");
results.add(value);
}
-
+
return Joiner.on("/").join(results);
}
-
+
@Override
public String preProcessKey (String key) {
String result = "";
@@ -316,19 +317,19 @@ public class MoxyStrategy extends Introspector {
String[] split = key.split("/");
int i = 0;
for (i = split.length-1; i >= 0; i--) {
-
+
if (jaxbContext.getDynamicType(split[i]) != null) {
break;
-
+
}
-
+
}
result = Joiner.on("/").join(Arrays.copyOfRange(split, 0, i));
-
+
return result;
-
+
}
-
+
@Override
public String marshal(MarshallerProperties properties) {
StringWriter result = new StringWriter();
@@ -339,7 +340,7 @@ public class MoxyStrategy extends Introspector {
marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, properties.getWrapperAsArrayName());
marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, false);
}
-
+
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, properties.getFormatted());
marshaller.marshal(this.internalObject, result);
} catch (JAXBException e) {
@@ -348,7 +349,7 @@ public class MoxyStrategy extends Introspector {
return result.toString();
}
-
+
@Override
public Object clone() {
Object result = null;
@@ -358,7 +359,7 @@ public class MoxyStrategy extends Introspector {
unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
-
+
result = unmarshaller.unmarshal(new StreamSource(new StringReader(this.marshal(true))), this.internalObject.getClass()).getValue();
} catch (JAXBException e) {
// TODO Auto-generated catch block
@@ -371,21 +372,21 @@ public class MoxyStrategy extends Introspector {
public ModelType getModelType() {
return ModelType.MOXY;
}
-
+
private String removeXPathDescriptor(String name) {
-
+
return name.replaceAll("/text\\(\\)", "");
}
@Override
public String getMetadata(ObjectMetadata name) {
-
+
return (String)cd.getProperty(name.toString());
}
@Override
public SchemaVersion getVersion() {
-
+
return this.version;
}
}
diff --git a/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java b/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java
index dd5d42c6..bd7f1b91 100644
--- a/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java
+++ b/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java
@@ -8,7 +8,7 @@
* 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
+ * 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,
@@ -50,6 +50,7 @@ import com.github.fge.jsonpatch.mergepatch.JsonMergePatch;
import org.apache.commons.lang.StringUtils;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.janusgraph.core.JanusGraphException;
import org.javatuples.Pair;
import org.onap.aai.db.props.AAIProperties;
@@ -67,6 +68,7 @@ import org.onap.aai.nodes.NodeIngestor;
import org.onap.aai.parsers.query.QueryParser;
import org.onap.aai.parsers.uri.URIToExtensionInformation;
+import org.onap.aai.parsers.uri.URIToObject;
import org.onap.aai.rest.ueb.UEBNotification;
import org.onap.aai.restcore.HttpMethod;
import org.onap.aai.schema.enums.ObjectMetadata;
@@ -93,15 +95,15 @@ public class HttpEntry {
private static final String TARGET_ENTITY = "DB";
private ModelType introspectorFactoryType;
-
+
private QueryStyle queryStyle;
-
+
private SchemaVersion version;
-
+
private Loader loader;
-
+
private TransactionalGraphEngine dbEngine;
-
+
private boolean processSingle = true;
private int paginationBucket = -1;
@@ -148,7 +150,7 @@ public class HttpEntry {
}
- public HttpEntry setHttpEntryProperties(SchemaVersion version, DBConnectionType connectionType, UEBNotification notification){
+ public HttpEntry setHttpEntryProperties(SchemaVersion version, DBConnectionType connectionType, UEBNotification notification){
this.version = version;
this.loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version);
this.dbEngine = new JanusGraphDBEngine(
@@ -161,7 +163,7 @@ public class HttpEntry {
getDbEngine().startTransaction();
return this;
}
-
+
/**
* Gets the introspector factory type.
@@ -316,7 +318,7 @@ public class HttpEntry {
QueryEngine queryEngine = dbEngine.getQueryEngine();
int maxRetries = 10;
int retry = 0;
-
+
LoggingContext.save();
for (DBRequest request : requests) {
response = null;
@@ -358,7 +360,7 @@ public class HttpEntry {
if (requestContextList != null) {
requestContext = requestContextList.get(0);
}
-
+
if (cleanUp == null) {
cleanUp = "false";
}
@@ -426,7 +428,7 @@ public class HttpEntry {
result = formatter.output(vertices.stream().map(vertex -> (Object) vertex).collect(Collectors.toList())).toString();
status = Status.OK;
}
-
+
break;
case PUT:
response = this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, true);
@@ -441,9 +443,9 @@ public class HttpEntry {
}
obj = serializer.getLatestVersionView(v);
if (query.isDependent()) {
- relatedObjects = this.getRelatedObjects(serializer, queryEngine, v);
+ relatedObjects = this.getRelatedObjects(serializer, queryEngine, v, obj, this.loader);
}
- LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs() +
+ LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs() +
(long)queryEngine.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
LOGGER.info ("Completed ");
LoggingContext.restoreIfPossible();
@@ -454,7 +456,7 @@ public class HttpEntry {
serializer.touchStandardVertexProperties(v, false);
this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, true);
serializer.createEdge(obj, v);
-
+
LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs(),TimeUnit.MILLISECONDS);
LOGGER.info ("Completed");
LoggingContext.restoreIfPossible();
@@ -466,7 +468,7 @@ public class HttpEntry {
existingObj = this.getObjectFromDb(vertices, serializer, query, existingObj, request.getUri(), 0, false, cleanUp);
String existingJson = existingObj.marshal(false);
String newJson;
-
+
if (request.getRawRequestContent().isPresent()) {
newJson = request.getRawRequestContent().get();
} else {
@@ -489,15 +491,15 @@ public class HttpEntry {
status = Status.OK;
patchedObj = serializer.getLatestVersionView(v);
if (query.isDependent()) {
- relatedObjects = this.getRelatedObjects(serializer, queryEngine, v);
+ relatedObjects = this.getRelatedObjects(serializer, queryEngine, v, patchedObj, this.loader);
}
- LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs() +
+ LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs() +
(long)queryEngine.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
LOGGER.info ("Completed");
LoggingContext.restoreIfPossible();
notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, patchedObj, relatedObjects, basePath);
} catch (IOException | JsonPatchException e) {
-
+
LOGGER.info ("Caught exception: " + e.getMessage());
LoggingContext.restoreIfPossible();
throw new AAIException("AAI_3000", "could not perform patch operation");
@@ -507,18 +509,18 @@ public class HttpEntry {
String resourceVersion = params.getFirst("resource-version");
obj = serializer.getLatestVersionView(v);
if (query.isDependent()) {
- relatedObjects = this.getRelatedObjects(serializer, queryEngine, v);
+ relatedObjects = this.getRelatedObjects(serializer, queryEngine, v, obj, this.loader);
}
/*
* Find all Delete-other-vertex vertices and create structure for notify
- * findDeleatble also returns the startVertex v and we dont want to create
+ * findDeleatble also returns the startVertex v and we dont want to create
* duplicate notification events for the same
* So remove the startvertex first
*/
-
+
List<Vertex> deletableVertices = dbEngine.getQueryEngine().findDeletable(v);
Long vId = (Long) v.id();
-
+
/*
* I am assuming vertexId cant be null
*/
@@ -527,39 +529,39 @@ public class HttpEntry {
Map<Vertex, Introspector> deleteObjects = new HashMap<>();
Map<String, URI> uriMap = new HashMap<>();
Map<String, HashMap<String, Introspector>> deleteRelatedObjects = new HashMap<>();
-
+
if(isDelVerticesPresent){
deleteObjects = this.buildIntrospectorObjects(serializer, deletableVertices);
-
+
uriMap = this.buildURIMap(serializer, deleteObjects);
deleteRelatedObjects = this.buildRelatedObjects(serializer, queryEngine, deleteObjects);
}
-
+
this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, true);
serializer.delete(v, deletableVertices, resourceVersion, enableResourceVersion);
this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, false);
-
- LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs() +
+
+ LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs() +
(long)queryEngine.getDBTimeMsecs(), TimeUnit.MILLISECONDS);
LOGGER.info ("Completed");
LoggingContext.restoreIfPossible();
status = Status.NO_CONTENT;
notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, obj, relatedObjects, basePath);
-
+
/*
* Notify delete-other-v candidates
*/
-
+
if(isDelVerticesPresent){
this.buildNotificationEvent(sourceOfTruth, status, transactionId, notification, deleteObjects,
uriMap, deleteRelatedObjects, basePath);
}
-
+
break;
case DELETE_EDGE:
serializer.touchStandardVertexProperties(v, false);
serializer.deleteEdge(obj, v);
-
+
LoggingContext.elapsedTime((long)serializer.getDBTimeMsecs(),TimeUnit.MILLISECONDS);
LOGGER.info ("Completed");
LoggingContext.restoreIfPossible();
@@ -569,8 +571,8 @@ public class HttpEntry {
default:
break;
}
-
-
+
+
/* temporarily adding vertex id to the headers
* to be able to use for testing the vertex id endpoint functionality
* since we presently have no other way of generating those id urls
@@ -606,7 +608,7 @@ public class HttpEntry {
break;
} catch (JanusGraphException e) {
this.dbEngine.rollback();
-
+
LOGGER.info ("Caught exception: " + e.getMessage());
LoggingContext.restoreIfPossible();
AAIException ex = new AAIException("AAI_6142", e);
@@ -655,7 +657,7 @@ public class HttpEntry {
return Pair.with(success, responses);
}
-
+
/**
* Gets the media type.
*
@@ -663,15 +665,15 @@ public class HttpEntry {
* @return the media type
*/
private String getMediaType(List <MediaType> mediaTypeList) {
- String mediaType = MediaType.APPLICATION_JSON; // json is the default
+ String mediaType = MediaType.APPLICATION_JSON; // json is the default
for (MediaType mt : mediaTypeList) {
if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt)) {
mediaType = MediaType.APPLICATION_XML;
- }
+ }
}
return mediaType;
}
-
+
/**
* Gets the object from db.
*
@@ -691,19 +693,19 @@ public class HttpEntry {
* @throws NoSuchMethodException the no such method exception
* @throws UnsupportedEncodingException the unsupported encoding exception
* @throws MalformedURLException the malformed URL exception
- * @throws AAIUnknownObjectException
- * @throws URISyntaxException
+ * @throws AAIUnknownObjectException
+ * @throws URISyntaxException
*/
private Introspector getObjectFromDb(List<Vertex> results, DBSerializer serializer, QueryParser query, Introspector obj, URI uri, int depth, boolean nodeOnly, String cleanUp) throws AAIException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, AAIUnknownObjectException, URISyntaxException {
-
- //nothing found
- if (results.isEmpty()) {
- String msg = createNotFoundMessage(query.getResultType(), uri);
+
+ //nothing found
+ if (results.isEmpty()) {
+ String msg = createNotFoundMessage(query.getResultType(), uri);
throw new AAIException("AAI_6114", msg);
- }
+ }
+
+ return serializer.dbToObject(results, obj, depth, nodeOnly, cleanUp);
- return serializer.dbToObject(results, obj, depth, nodeOnly, cleanUp);
-
}
/**
@@ -800,7 +802,7 @@ public class HttpEntry {
return response;
}
-
+
/**
* Creates the not found message.
*
@@ -809,12 +811,12 @@ public class HttpEntry {
* @return the string
*/
private String createNotFoundMessage(String resultType, URI uri) {
-
- String msg = "No Node of type " + resultType + " found at: " + uri.getPath();
- return msg;
+ String msg = "No Node of type " + resultType + " found at: " + uri.getPath();
+
+ return msg;
}
-
+
/**
* Sets the depth.
*
@@ -831,11 +833,11 @@ public class HttpEntry {
return depth;
}
- if(depthParam == null){
+ if(depthParam == null){
if(this.version.compareTo(schemaVersions.getDepthVersion()) >= 0){
depth = 0;
} else {
- depth = AAIProperties.MAXIMUM_DEPTH;
+ depth = AAIProperties.MAXIMUM_DEPTH;
}
} else {
if (!depthParam.isEmpty() && !"all".equals(depthParam)){
@@ -847,16 +849,16 @@ public class HttpEntry {
}
}
- String maxDepth = obj.getMetadata(ObjectMetadata.MAXIMUM_DEPTH);
-
+ String maxDepth = obj.getMetadata(ObjectMetadata.MAXIMUM_DEPTH);
+
int maximumDepth = AAIProperties.MAXIMUM_DEPTH;
if(maxDepth != null){
- try {
- maximumDepth = Integer.parseInt(maxDepth);
- } catch(Exception ex){
- throw new AAIException("AAI_4018");
- }
+ try {
+ maximumDepth = Integer.parseInt(maxDepth);
+ } catch(Exception ex){
+ throw new AAIException("AAI_4018");
+ }
}
if(depth > maximumDepth){
@@ -865,7 +867,7 @@ public class HttpEntry {
return depth;
}
-
+
/**
* Checks if is modification method.
*
@@ -874,31 +876,155 @@ public class HttpEntry {
*/
private boolean isModificationMethod(HttpMethod method) {
boolean result = false;
-
+
if (method.equals(HttpMethod.PUT) || method.equals(HttpMethod.PUT_EDGE) || method.equals(HttpMethod.DELETE_EDGE) || method.equals(HttpMethod.MERGE_PATCH)) {
result = true;
}
-
+
return result;
-
+
}
-
- private HashMap<String, Introspector> getRelatedObjects(DBSerializer serializer, QueryEngine queryEngine, Vertex v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, AAIException, URISyntaxException {
+
+ /**
+ * Given an uri, introspector object and loader object
+ * it will check if the obj is top level object if it is,
+ * it will return immediately returning the uri passed in
+ * If it isn't, it will go through, get the uriTemplate
+ * from the introspector object and get the count of "/"s
+ * and remove that part of the uri using substring
+ * and keep doing that until the current object is top level
+ * Also added the max depth just so worst case scenario
+ * Then keep adding aai-uri to the list include the aai-uri passed in
+ * Convert that list into an array and return it
+ * <p>
+ *
+ * Example:
+ *
+ * <blockquote>
+ * aai-uri -> /cloud-infrastructure/cloud-regions/cloud-region/cloud-owner/cloud-region-id/tenants/tenant/tenant1/vservers/vserver/v1
+ *
+ * Given the uriTemplate vserver -> /vservers/vserver/{vserver-id}
+ * it converts to /vservers/vserver
+ *
+ * lastIndexOf /vservers/vserver in /cloud-infrastructure/cloud-regions/cloud-region/cloud-owner/cloud-region-id/tenants/tenant/tenant1/vservers/vserver/v1
+ * ^
+ * |
+ * |
+ * lastIndexOf
+ * Use substring to get the string from 0 to that lastIndexOf
+ * aai-uri -> /cloud-infrastructure/cloud-regions/cloud-region/cloud-owner/cloud-region-id/tenants/tenant/tenant1
+ *
+ * From this new aai-uri, generate a introspector from the URITOObject class
+ * and keep doing this until you
+ *
+ * </blockquote>
+ *
+ * @param aaiUri - aai-uri of the vertex representating the unique id of a given vertex
+ * @param obj - introspector object of the given starting vertex
+ * @param loader - Type of loader which will always be MoxyLoader to support model driven
+ * @return an array of strings which can be used to get the vertexes of parent and grand parents from a given vertex
+ * @throws UnsupportedEncodingException
+ * @throws AAIException
+ */
+ String[] convertIntrospectorToUriList(String aaiUri, Introspector obj, Loader loader) throws UnsupportedEncodingException, AAIException {
+
+ List<String> uriList = new ArrayList<>();
+ String template = StringUtils.EMPTY;
+ String truncatedUri = aaiUri;
+ int depth = AAIProperties.MAXIMUM_DEPTH;
+ uriList.add(truncatedUri);
+
+ while (depth >= 0 && !obj.isTopLevel()) {
+ template = obj.getMetadata(ObjectMetadata.URI_TEMPLATE);
+
+ if(template == null){
+ LOGGER.warn("Unable to find the uriTemplate for the object {}", obj.getDbName());
+ return null;
+ }
+
+ int templateCount = StringUtils.countMatches(template, "/");
+ int truncatedUriCount = StringUtils.countMatches(truncatedUri, "/");
+
+ if(templateCount > truncatedUriCount){
+ LOGGER.warn("Template uri {} contains more slashes than truncatedUri {}", template, truncatedUri);
+ return null;
+ }
+
+ int cutIndex = StringUtils.ordinalIndexOf(truncatedUri, "/", truncatedUriCount-templateCount+1);
+ truncatedUri = StringUtils.substring(truncatedUri, 0, cutIndex);
+ uriList.add(truncatedUri);
+ obj = new URIToObject(loader, UriBuilder.fromPath(truncatedUri).build()).getEntity();
+ depth--;
+ }
+
+ return uriList.toArray(new String[uriList.size()]);
+ }
+
+ /**
+ *
+ * @param serializer
+ * @param queryEngine
+ * @param v
+ * @param obj
+ * @param loader
+ * @return
+ * @throws IllegalAccessException
+ * @throws IllegalArgumentException
+ * @throws InvocationTargetException
+ * @throws SecurityException
+ * @throws InstantiationException
+ * @throws NoSuchMethodException
+ * @throws UnsupportedEncodingException
+ * @throws AAIException
+ * @throws URISyntaxException
+ */
+ private HashMap<String, Introspector> getRelatedObjects(DBSerializer serializer, QueryEngine queryEngine, Vertex v, Introspector obj, Loader loader) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, AAIException, URISyntaxException {
+
HashMap<String, Introspector> relatedVertices = new HashMap<>();
- List<Vertex> vertexChain = queryEngine.findParents(v);
- for (Vertex vertex : vertexChain) {
+ VertexProperty aaiUriProperty = v.property(AAIProperties.AAI_URI);
+
+ if(!aaiUriProperty.isPresent()){
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("For the given vertex {}, it seems aai-uri is not present so not getting related objects", v.id().toString());
+ } else {
+ LOGGER.info("It seems aai-uri is not present in vertex, so not getting related objects, for more info enable debug log");
+ }
+ return relatedVertices;
+ }
+
+ String aaiUri = aaiUriProperty.value().toString();
+
+ if(!obj.isTopLevel()){
+ String[] uriList = convertIntrospectorToUriList(aaiUri, obj, loader);
+ List<Vertex> vertexChain = null;
+ // If the uriList is null then there is something wrong with converting the uri
+ // into a list of aai-uris so falling back to the old mechanism for finding parents
+ if(uriList == null){
+ LOGGER.info("Falling back to the old mechanism due to unable to convert aai-uri to list of uris but this is not optimal");
+ vertexChain = queryEngine.findParents(v);
+ } else {
+ vertexChain = queryEngine.findParents(uriList);
+ }
+ for(Vertex vertex : vertexChain){
+ try {
+ final Introspector vertexObj = serializer.getVertexProperties(vertex);
+ relatedVertices.put(vertexObj.getObjectId(), vertexObj);
+ } catch (AAIUnknownObjectException e) {
+ LOGGER.warn("Unable to get vertex properties, partial list of related vertices returned");
+ }
+ }
+ } else {
try {
- final Introspector vertexObj = serializer.getVertexProperties(vertex);
+ final Introspector vertexObj = serializer.getVertexProperties(v);
relatedVertices.put(vertexObj.getObjectId(), vertexObj);
} catch (AAIUnknownObjectException e) {
LOGGER.warn("Unable to get vertex properties, partial list of related vertices returned");
}
-
}
-
+
return relatedVertices;
}
-
+
private Map<Vertex, Introspector> buildIntrospectorObjects(DBSerializer serializer, Iterable<Vertex> vertices) {
Map<Vertex, Introspector> deleteObjectMap = new HashMap<>();
for (Vertex vertex : vertices) {
@@ -944,7 +1070,7 @@ public class HttpEntry {
for (Map.Entry<Vertex, Introspector> entry : introSpector.entrySet()) {
try {
HashMap<String, Introspector> relatedObjects = this.getRelatedObjects(serializer, queryEngine,
- entry.getKey());
+ entry.getKey(), entry.getValue(), this.loader);
if (null != entry.getValue())
relatedObjectsMap.put(entry.getValue().getObjectId(), relatedObjects);
} catch (IllegalAccessException | IllegalArgumentException
@@ -959,7 +1085,7 @@ public class HttpEntry {
return relatedObjectsMap;
}
-
+
private void buildNotificationEvent(String sourceOfTruth, Status status, String transactionId,
UEBNotification notification, Map<Vertex, Introspector> deleteObjects, Map<String, URI> uriMap,
Map<String, HashMap<String, Introspector>> deleteRelatedObjects, String basePath) {
@@ -980,4 +1106,27 @@ public class HttpEntry {
}
}
}
+
+ public void setPaginationParameters(String resultIndex, String resultSize) {
+ if (resultIndex != null && resultIndex != "-1" && resultSize != null && resultSize != "-1") {
+ this.setPaginationIndex(Integer.parseInt(resultIndex));
+ this.setPaginationBucket(Integer.parseInt(resultSize));
+ }
+ }
+
+ public List<Object> getPaginatedVertexList(List<Object> vertexList) throws AAIException{
+ List<Object> vertices;
+ if(this.isPaginated()) {
+ this.setTotalsForPaging(vertexList.size(), this.getPaginationBucket());
+ int startIndex = (this.getPaginationIndex() - 1) * this.getPaginationBucket();
+ int endIndex = Math.min((this.getPaginationBucket() * this.getPaginationIndex()), vertexList.size());
+ if(startIndex > endIndex){
+ throw new AAIException("AAI_6150"," ResultIndex is not appropriate for the result set, Needs to be <= "+ endIndex);
+ }
+ vertices = vertexList.subList(startIndex, endIndex);
+ }else{
+ vertices = vertexList;
+ }
+ return vertices;
+ }
}
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 7a2c447e..9d107b1f 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
@@ -23,18 +23,21 @@ package org.onap.aai.serialization.db;
import com.att.eelf.configuration.EELFLogger;
import com.att.eelf.configuration.EELFManager;
import com.google.common.base.CaseFormat;
-import org.janusgraph.core.SchemaViolationException;
+import com.google.common.collect.Multimap;
import org.apache.commons.collections.IteratorUtils;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
import org.apache.tinkerpop.gremlin.structure.*;
-import org.javatuples.Pair;
+import org.janusgraph.core.SchemaViolationException;
import org.javatuples.Triplet;
+import org.onap.aai.concurrent.AaiCallable;
+import org.onap.aai.config.SpringContextAware;
import org.onap.aai.db.props.AAIProperties;
import org.onap.aai.edges.EdgeIngestor;
import org.onap.aai.edges.EdgeRule;
import org.onap.aai.edges.EdgeRuleQuery;
+import org.onap.aai.edges.TypeAlphabetizer;
import org.onap.aai.edges.enums.AAIDirection;
import org.onap.aai.edges.enums.EdgeField;
import org.onap.aai.edges.enums.EdgeProperty;
@@ -57,6 +60,7 @@ import org.onap.aai.schema.enums.PropertyMetadata;
import org.onap.aai.serialization.db.exceptions.MultipleEdgeRuleFoundException;
import org.onap.aai.serialization.db.exceptions.NoEdgeRuleFoundException;
import org.onap.aai.serialization.engines.TransactionalGraphEngine;
+import org.onap.aai.serialization.engines.query.QueryEngine;
import org.onap.aai.serialization.tinkerpop.TreeBackedVertex;
import org.onap.aai.setup.SchemaVersion;
import org.onap.aai.setup.SchemaVersions;
@@ -64,8 +68,6 @@ import org.onap.aai.util.AAIConfig;
import org.onap.aai.util.AAIConstants;
import org.onap.aai.workarounds.NamingExceptions;
import org.springframework.context.ApplicationContext;
-import org.onap.aai.concurrent.AaiCallable;
-import org.onap.aai.config.SpringContextAware;
import javax.ws.rs.core.UriBuilder;
import java.io.UnsupportedEncodingException;
@@ -78,1790 +80,1956 @@ import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
+import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.onap.aai.serialization.engines.query.QueryEngine;
+import java.util.stream.Collectors;
public class DBSerializer {
-
- private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(DBSerializer.class);
-
- private final TransactionalGraphEngine engine;
- private final String sourceOfTruth;
- private final ModelType introspectionType;
- private final SchemaVersion version;
- private final Loader latestLoader;
- private EdgeSerializer edgeSer;
- private EdgeIngestor edgeRules;
- private final Loader loader;
- private final String baseURL;
- private double dbTimeMsecs = 0;
- private long currentTimeMillis;
-
- private SchemaVersions schemaVersions;
- /**
- * Instantiates a new DB serializer.
- *
- * @param version the version
- * @param engine the engine
- * @param introspectionType the introspection type
- * @param sourceOfTruth the source of truth
- * @throws AAIException
- */
- public DBSerializer(SchemaVersion version, TransactionalGraphEngine engine, ModelType introspectionType, String sourceOfTruth) throws AAIException {
- this.engine = engine;
- this.sourceOfTruth = sourceOfTruth;
- this.introspectionType = introspectionType;
- this.schemaVersions = SpringContextAware.getBean(SchemaVersions.class);
- SchemaVersion LATEST = schemaVersions.getDefaultVersion();
- this.latestLoader = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, LATEST);
- 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();
- }
-
- private void initBeans() {
- //TODO proper spring wiring, but that requires a lot of refactoring so for now we have this
- ApplicationContext ctx = SpringContextAware.getApplicationContext();
- EdgeIngestor ei = ctx.getBean(EdgeIngestor.class);
- setEdgeIngestor(ei);
- EdgeSerializer es = ctx.getBean(EdgeSerializer.class);
- setEdgeSerializer(es);
- }
-
- private void backupESInit() {
- setEdgeSerializer(new EdgeSerializer(this.edgeRules));
- }
-
- public void setEdgeSerializer(EdgeSerializer edgeSer) {
- this.edgeSer = edgeSer;
- }
-
- public EdgeSerializer getEdgeSeriailizer() {
- return this.edgeSer;
- }
-
- public void setEdgeIngestor(EdgeIngestor ei) {
- this.edgeRules = ei;
- }
-
- public EdgeIngestor getEdgeIngestor(){
- return this.edgeRules;
- }
-
- /**
- * Touch standard vertex properties.
- *
- * @param v the v
- * @param isNewVertex the is new vertex
- */
- public void touchStandardVertexProperties(Vertex v, boolean isNewVertex) {
- 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.LAST_MOD_TS, timeNowInSec);
- v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, this.sourceOfTruth);
-
- }
-
- private void touchStandardVertexProperties(String nodeType, Vertex v, boolean isNewVertex) {
-
- v.property(AAIProperties.NODE_TYPE, nodeType);
- touchStandardVertexProperties(v, isNewVertex);
-
- }
-
-
-
- /**
- * Creates the new vertex.
- *
- * @param wrappedObject the wrapped object
- * @return the vertex
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIException the AAI exception
- */
- public Vertex createNewVertex(Introspector wrappedObject) {
- Vertex v;
- try {
- StopWatch.conditionalStart();
- v = this.engine.tx().addVertex();
- touchStandardVertexProperties(wrappedObject.getDbName(), v, true);
- }
- finally {
- dbTimeMsecs += StopWatch.stopIfStarted();
- }
- return v;
- }
-
- /**
- * Trim class name.
- *
- * @param className the class name
- * @return the string
- */
- /*
- * Removes the classpath from a class name
- */
- public String trimClassName (String className) {
- String returnValue = "";
-
- if (className.lastIndexOf('.') == -1) {
- return className;
- }
- returnValue = className.substring(className.lastIndexOf('.') + 1, className.length());
-
- return returnValue;
- }
-
- /**
- * Serialize to db.
- *
- * @param obj the obj
- * @param v the v
- * @param uriQuery the uri query
- * @param identifier the identifier
- * @throws SecurityException the security exception
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws InstantiationException the instantiation exception
- * @throws InterruptedException the interrupted exception
- * @throws NoSuchMethodException the no such method exception
- * @throws AAIException the AAI exception
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIUnknownObjectException
- */
- public void serializeToDb(Introspector obj, Vertex v, QueryParser uriQuery, String identifier, String requestContext) throws AAIException, UnsupportedEncodingException {
- StopWatch.conditionalStart();
- try {
- if (uriQuery.isDependent()) {
- //try to find the parent
- List<Vertex> vertices = uriQuery.getQueryBuilder().getParentQuery().toList();
- if (!vertices.isEmpty()) {
- Vertex parent = vertices.get(0);
- this.reflectDependentVertex(parent, v, obj, requestContext);
- } else {
- dbTimeMsecs += StopWatch.stopIfStarted();
- throw new AAIException("AAI_6114", "No parent Node of type " + uriQuery.getParentResultType() + " for " + identifier);
- }
- } else {
- serializeSingleVertex(v, obj, requestContext);
- }
-
- } catch (SchemaViolationException e) {
- dbTimeMsecs += StopWatch.stopIfStarted();
- throw new AAIException("AAI_6117", e);
- }
- dbTimeMsecs += StopWatch.stopIfStarted();
- }
-
- public void serializeSingleVertex(Vertex v, Introspector obj, String requestContext) throws UnsupportedEncodingException, AAIException {
- StopWatch.conditionalStart();
- try {
- boolean isTopLevel = obj.isTopLevel();
- if (isTopLevel) {
- addUriIfNeeded(v, obj.getURI());
- }
-
- processObject(obj, v, requestContext);
- if (!isTopLevel) {
- URI uri = this.getURIForVertex(v);
- URIParser parser = new URIParser(this.loader, uri);
- if (parser.validate()) {
- addUriIfNeeded(v, uri.toString());
- }
- }
- } catch (SchemaViolationException e) {
- throw new AAIException("AAI_6117", e);
- }
- finally {
- dbTimeMsecs += StopWatch.stopIfStarted();
- }
- }
-
- private void addUriIfNeeded(Vertex v, String uri) {
- VertexProperty<String> uriProp = v.property(AAIProperties.AAI_URI);
- if (!uriProp.isPresent() || (uriProp.isPresent() && !uriProp.value().equals(uri))) {
- v.property(AAIProperties.AAI_URI, uri);
- }
- }
-
- /**
- * Process object.
- *
- * @param <T> the generic type
- * @param obj the obj
- * @param v the v
- * @return the list
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws InstantiationException the instantiation exception
- * @throws NoSuchMethodException the no such method exception
- * @throws SecurityException the security exception
- * @throws AAIException the AAI exception
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIUnknownObjectException
- */
- /*
- * Helper method for reflectToDb
- * Handles all the property setting
- */
- private <T> List<Vertex> processObject (Introspector obj, Vertex v, String requestContext) throws UnsupportedEncodingException, AAIException {
- Set<String> properties = new LinkedHashSet<>(obj.getProperties());
- properties.remove(AAIProperties.RESOURCE_VERSION);
- List<Vertex> dependentVertexes = new ArrayList<>();
- List<Vertex> processedVertexes = new ArrayList<>();
- boolean isComplexType = false;
- boolean isListType = false;
- if (!obj.isContainer()) {
- this.touchStandardVertexProperties(obj.getDbName(), v, false);
- }
- this.executePreSideEffects(obj, v);
- for (String property : properties) {
- Object value = null;
- final String propertyType;
- propertyType = obj.getType(property);
- isComplexType = obj.isComplexType(property);
- isListType = obj.isListType(property);
- value = obj.getValue(property);
-
- if (!(isComplexType || isListType)) {
- boolean canModify = this.canModify(obj, property, requestContext);
-
- if (canModify) {
- final Map<PropertyMetadata, String> metadata = obj.getPropertyMetadata(property);
- String dbProperty = property;
- if (metadata.containsKey(PropertyMetadata.DB_ALIAS)) {
- dbProperty = metadata.get(PropertyMetadata.DB_ALIAS);
- }
- if (metadata.containsKey(PropertyMetadata.DATA_LINK)) {
- //data linked properties are ephemeral
- //they are populated dynamically on GETs
- continue;
- }
- if (value != null) {
- if (!value.equals(v.property(dbProperty).orElse(null))) {
- if (propertyType.toLowerCase().contains(".long")) {
- v.property(dbProperty, new Integer(((Long)value).toString()));
- } else {
- v.property(dbProperty, value);
- }
- }
- } else {
- v.property(dbProperty).remove();
- }
- }
- } else if (isListType) {
- List<Object> list = (List<Object>)value;
- if (obj.isComplexGenericType(property)) {
- if (list != null) {
- for (Object o : list) {
- Introspector child = IntrospectorFactory.newInstance(this.introspectionType, o);
- child.setURIChain(obj.getURI());
- processedVertexes.add(reflectDependentVertex(v, child, requestContext));
- }
- }
- } else {
- //simple list case
- engine.setListProperty(v, property, list);
- }
- } else {
- //method.getReturnType() is not 'simple' then create a vertex and edge recursively returning an edge back to this method
- if (value != null) { //effectively ignore complex properties not included in the object we're processing
- if (value.getClass().isArray()) {
-
- int length = Array.getLength(value);
- for (int i = 0; i < length; i ++) {
- Object arrayElement = Array.get(value, i);
- Introspector child = IntrospectorFactory.newInstance(this.introspectionType, arrayElement);
- child.setURIChain(obj.getURI());
- processedVertexes.add(reflectDependentVertex(v, child, requestContext));
-
- }
- } else if (!property.equals("relationship-list")) {
- // container case
- Introspector introspector = IntrospectorFactory.newInstance(this.introspectionType, value);
- if (introspector.isContainer()) {
- dependentVertexes.addAll(this.engine.getQueryEngine().findChildrenOfType(v, introspector.getChildDBName()));
- introspector.setURIChain(obj.getURI());
-
- processedVertexes.addAll(processObject(introspector, v, requestContext));
-
- } else {
- dependentVertexes.addAll(this.engine.getQueryEngine().findChildrenOfType(v, introspector.getDbName()));
- processedVertexes.add(reflectDependentVertex(v, introspector, requestContext));
-
- }
- } else if (property.equals("relationship-list")) {
- handleRelationships(obj, v);
- }
- }
- }
- }
- this.writeThroughDefaults(v, obj);
- /* handle those vertexes not touched */
- for (Vertex toBeRemoved : processedVertexes) {
- dependentVertexes.remove(toBeRemoved);
- }
- this.deleteItemsWithTraversal(dependentVertexes);
-
- this.executePostSideEffects(obj, v);
- return processedVertexes;
- }
-
- /**
- * Handle relationships.
- *
- * @param obj the obj
- * @param vertex the vertex
- * @throws SecurityException the security exception
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIException the AAI exception
- */
- /*
- * Handles the explicit relationships defined for an obj
- */
- private void handleRelationships(Introspector obj, Vertex vertex) throws UnsupportedEncodingException, AAIException {
-
-
-
- Introspector wrappedRl = obj.getWrappedValue("relationship-list");
- processRelationshipList(wrappedRl, vertex);
-
-
- }
-
-
- /**
- * Process relationship list.
- *
- * @param wrapped the wrapped
- * @param v the v
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIException the AAI exception
- */
- private void processRelationshipList(Introspector wrapped, Vertex v) throws UnsupportedEncodingException, AAIException {
-
- List<Object> relationships = (List<Object>)wrapped.getValue("relationship");
-
- List<Triplet<Vertex, Vertex, String>> addEdges = new ArrayList<>();
- List<Edge> existingEdges = this.engine.getQueryEngine().findEdgesForVersion(v, wrapped.getLoader());
-
- for (Object relationship : relationships) {
- Edge e = null;
- Vertex cousinVertex = null;
- String label = null;
- Introspector wrappedRel = IntrospectorFactory.newInstance(this.introspectionType, relationship);
- QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(wrappedRel);
-
- if (wrappedRel.hasProperty("relationship-label")) {
- label = wrappedRel.getValue("relationship-label");
- }
-
- List<Vertex> results = parser.getQueryBuilder().toList();
- if (results.isEmpty()) {
- final AAIException ex = new AAIException("AAI_6129", "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri());
- ex.getTemplateVars().add(parser.getResultType());
- ex.getTemplateVars().add(parser.getUri().toString());
- throw ex;
- } else {
- //still an issue if there's more than one
- cousinVertex = results.get(0);
- }
-
- if (cousinVertex != null) {
- String vType = (String)v.property(AAIProperties.NODE_TYPE).value();
- String cousinType = (String)cousinVertex.property(AAIProperties.NODE_TYPE).value();
- EdgeRuleQuery.Builder baseQ = new EdgeRuleQuery.Builder(vType, cousinType).label(label);
-
-
- if (!edgeRules.hasRule(baseQ.build())) {
- throw new AAIException("AAI_6120", "No EdgeRule found for passed nodeTypes: " + v.property(AAIProperties.NODE_TYPE).value().toString() + ", "
- + cousinVertex.property(AAIProperties.NODE_TYPE).value().toString() + (label != null ? (" with label " + label):"") +".");
- } else if (edgeRules.hasRule(baseQ.edgeType(EdgeType.TREE).build()) && !edgeRules.hasRule(baseQ.edgeType(EdgeType.COUSIN).build())) {
- throw new AAIException("AAI_6145");
- }
-
- e = this.getEdgeBetween(EdgeType.COUSIN, v, cousinVertex, label);
-
- if (e == null) {
- addEdges.add(new Triplet<>(v, cousinVertex, label));
- } else {
- existingEdges.remove(e);
- }
- }
- }
-
- for (Edge edge : existingEdges) {
- edge.remove();
- }
- for (Triplet<Vertex, Vertex, String> triplet : addEdges) {
- try {
- edgeSer.addEdge(this.engine.asAdmin().getTraversalSource(), triplet.getValue0(), triplet.getValue1(), triplet.getValue2());
- } catch (NoEdgeRuleFoundException e) {
- throw new AAIException("AAI_6129", e);
- }
- }
-
- }
-
- /**
- * Write through defaults.
- *
- * @param v the v
- * @param obj the obj
- * @throws AAIUnknownObjectException
- */
- private void writeThroughDefaults(Vertex v, Introspector obj) throws AAIUnknownObjectException {
- Introspector latest = this.latestLoader.introspectorFromName(obj.getName());
- if (latest != null) {
- Set<String> required = latest.getRequiredProperties();
-
- for (String field : required) {
- String defaultValue = null;
- Object vertexProp = null;
- defaultValue = latest.getPropertyMetadata(field).get(PropertyMetadata.DEFAULT_VALUE);
- if (defaultValue != null) {
- vertexProp = v.<Object>property(field).orElse(null);
- if (vertexProp == null) {
- v.property(field, defaultValue);
- }
- }
- }
- }
-
- }
-
-
- /**
- * Reflect dependent vertex.
- *
- * @param v the v
- * @param dependentObj the dependent obj
- * @return the vertex
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws InstantiationException the instantiation exception
- * @throws NoSuchMethodException the no such method exception
- * @throws SecurityException the security exception
- * @throws AAIException the AAI exception
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIUnknownObjectException
- */
- private Vertex reflectDependentVertex(Vertex v, Introspector dependentObj, String requestContext) throws AAIException, UnsupportedEncodingException {
-
- //QueryParser p = this.engine.getQueryBuilder().createQueryFromURI(obj.getURI());
- //List<Vertex> items = p.getQuery().toList();
- QueryBuilder<Vertex> query = this.engine.getQueryBuilder(v);
- query.createEdgeTraversal(EdgeType.TREE, v, dependentObj);
- query.createKeyQuery(dependentObj);
-
- List<Vertex> items = query.toList();
-
- Vertex dependentVertex = null;
- if (items.size() == 1) {
- dependentVertex = items.get(0);
- this.verifyResourceVersion("update", dependentObj.getDbName(), dependentVertex.<String>property(AAIProperties.RESOURCE_VERSION).orElse(null), (String)dependentObj.getValue(AAIProperties.RESOURCE_VERSION), (String)dependentObj.getURI());
- } else {
- this.verifyResourceVersion("create", dependentObj.getDbName(), "", (String)dependentObj.getValue(AAIProperties.RESOURCE_VERSION), (String)dependentObj.getURI());
- dependentVertex = createNewVertex(dependentObj);
- }
-
- return reflectDependentVertex(v, dependentVertex, dependentObj, requestContext);
-
- }
-
- /**
- * Reflect dependent vertex.
- *
- * @param parent the parent
- * @param child the child
- * @param obj the obj
- * @return the vertex
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws InstantiationException the instantiation exception
- * @throws NoSuchMethodException the no such method exception
- * @throws SecurityException the security exception
- * @throws AAIException the AAI exception
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIUnknownObjectException
- */
- private Vertex reflectDependentVertex(Vertex parent, Vertex child, Introspector obj, String requestContext) throws AAIException, UnsupportedEncodingException {
-
- String parentUri = parent.<String>property(AAIProperties.AAI_URI).orElse(null);
- if (parentUri != null) {
- String uri;
- uri = obj.getURI();
- addUriIfNeeded(child, parentUri + uri);
- }
- processObject(obj, child, requestContext);
-
- Edge e;
- e = this.getEdgeBetween(EdgeType.TREE, parent, child, null);
- if (e == null) {
- String canBeLinked = obj.getMetadata(ObjectMetadata.CAN_BE_LINKED);
- if (canBeLinked != null && canBeLinked.equals("true")) {
- Loader ldrForCntxt = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, getVerForContext(requestContext));
- boolean isFirst = !this.engine.getQueryBuilder(ldrForCntxt, parent).createEdgeTraversal(EdgeType.TREE, parent, obj).hasNext();
- if (isFirst) {
- child.property(AAIProperties.LINKED, true);
- }
- }
- edgeSer.addTreeEdge(this.engine.asAdmin().getTraversalSource(), parent, child);
- }
- return child;
-
- }
-
- private SchemaVersion getVerForContext(String requestContext) {
- Pattern pattern = Pattern.compile("v[0-9]+");
- Matcher m = pattern.matcher(requestContext);
- if (!m.find()) {
- return this.version;
- } else {
- return new SchemaVersion(requestContext);
- }
- }
-
- /**
- * Db to object.
- *
- * @param vertices the vertices
- * @param obj the obj
- * @param depth the depth
- * @param cleanUp the clean up
- * @return the introspector
- * @throws AAIException the AAI exception
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws SecurityException the security exception
- * @throws InstantiationException the instantiation exception
- * @throws NoSuchMethodException the no such method exception
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws MalformedURLException the malformed URL exception
- * @throws AAIUnknownObjectException
- * @throws URISyntaxException
- */
- public Introspector dbToObject(List<Vertex> vertices, final Introspector obj, int depth, boolean nodeOnly, String cleanUp) throws UnsupportedEncodingException, AAIException {
- final int internalDepth;
- if (depth == Integer.MAX_VALUE) {
- internalDepth = depth--;
- } else {
- internalDepth = depth;
- }
- StopWatch.conditionalStart();
- if (vertices.size() > 1 && !obj.isContainer()) {
- dbTimeMsecs += StopWatch.stopIfStarted();
- throw new AAIException("AAI_6136", "query object mismatch: this object cannot hold multiple items." + obj.getDbName());
- } else if (obj.isContainer()) {
- final List getList;
- String listProperty = null;
- for (String property : obj.getProperties()) {
- if (obj.isListType(property) && obj.isComplexGenericType(property)) {
- listProperty = property;
- break;
- }
- }
- final String propertyName = listProperty;
- getList = (List)obj.getValue(listProperty);
-
- /* This is an experimental multithreading experiment
- * on get alls.
- */
- ExecutorService pool = GetAllPool.getInstance().getPool();
-
- List<Future<Object>> futures = new ArrayList<>();
-
- QueryEngine tgEngine = this.engine.getQueryEngine();
- for (Vertex v : vertices) {
-
- AaiCallable<Object> task = new AaiCallable<Object>() {
- @Override
- public Object process() throws UnsupportedEncodingException, AAIException {
- Set<Vertex> seen = new HashSet<>();
- Introspector childObject;
- try {
- childObject = obj.newIntrospectorInstanceOfNestedProperty(propertyName);
- } catch (AAIUnknownObjectException e) {
- throw e;
- }
- Tree<Element> tree = tgEngine.findSubGraph(v, internalDepth, nodeOnly);
- TreeBackedVertex treeVertex = new TreeBackedVertex(v, tree);
- try {
- dbToObject(childObject, treeVertex, seen, internalDepth, nodeOnly, cleanUp);
- } catch (UnsupportedEncodingException e) {
- throw e;
- } catch (AAIException e) {
- throw e;
- }
- return childObject.getUnderlyingObject();
- //getList.add(childObject.getUnderlyingObject());
- }
- };
- futures.add(pool.submit(task));
- }
-
- for (Future<Object> future : futures) {
- try {
- getList.add(future.get());
- } catch (ExecutionException e) {
- dbTimeMsecs += StopWatch.stopIfStarted();
- throw new AAIException("AAI_4000", e);
- } catch (InterruptedException e) {
- dbTimeMsecs += StopWatch.stopIfStarted();
- throw new AAIException("AAI_4000", e);
- }
- }
- } else if (vertices.size() == 1) {
- Set<Vertex> seen = new HashSet<>();
- Tree<Element> tree = this.engine.getQueryEngine().findSubGraph(vertices.get(0), depth, nodeOnly);
- TreeBackedVertex treeVertex = new TreeBackedVertex(vertices.get(0), tree);
- dbToObject(obj, treeVertex, seen, depth, nodeOnly, cleanUp);
- } else {
- //obj = null;
- }
-
- dbTimeMsecs += StopWatch.stopIfStarted();
- return obj;
- }
-
- /**
- * Db to object.
- *
- * @param obj the obj
- * @param v the v
- * @param seen the seen
- * @param depth the depth
- * @param cleanUp the clean up
- * @return the introspector
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws SecurityException the security exception
- * @throws InstantiationException the instantiation exception
- * @throws NoSuchMethodException the no such method exception
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIException the AAI exception
- * @throws MalformedURLException the malformed URL exception
- * @throws AAIUnknownObjectException
- * @throws URISyntaxException
- */
- private Introspector dbToObject(Introspector obj, Vertex v, Set<Vertex> seen, int depth, boolean nodeOnly, String cleanUp) throws AAIException, UnsupportedEncodingException {
-
- if (depth < 0) {
- return null;
- }
- depth--;
- seen.add(v);
-
- boolean modified = false;
- for (String property : obj.getProperties(PropertyPredicates.isVisible())) {
- List<Object> getList = null;
- Vertex[] vertices = null;
-
- if (!(obj.isComplexType(property) || obj.isListType(property))) {
- this.copySimpleProperty(property, obj, v);
- modified = true;
- } else {
- if (obj.isComplexType(property)) {
- /* container case */
-
- if (!property.equals("relationship-list") && depth >= 0) {
- Introspector argumentObject = obj.newIntrospectorInstanceOfProperty(property);
- Object result = dbToObject(argumentObject, v, seen, depth+1, nodeOnly, cleanUp);
- if (result != null) {
- obj.setValue(property, argumentObject.getUnderlyingObject());
- modified = true;
- }
- } else if (property.equals("relationship-list") && !nodeOnly){
- /* relationships need to be handled correctly */
- Introspector relationshipList = obj.newIntrospectorInstanceOfProperty(property);
- relationshipList = createRelationshipList(v, relationshipList, cleanUp);
- if (relationshipList != null) {
- modified = true;
- obj.setValue(property, relationshipList.getUnderlyingObject());
- modified = true;
- }
-
- }
- } else if (obj.isListType(property)) {
-
- if (property.equals("any")) {
- continue;
- }
- String genericType = obj.getGenericTypeClass(property).getSimpleName();
- if (obj.isComplexGenericType(property) && depth >= 0) {
- final String childDbName = convertFromCamelCase(genericType);
- String vType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
- EdgeRule rule;
-
- try {
- rule = edgeRules.getRule(new EdgeRuleQuery.Builder(vType, childDbName).edgeType(EdgeType.TREE).build());
- } catch (EdgeRuleNotFoundException e) {
- throw new NoEdgeRuleFoundException(e);
- } catch (AmbiguousRuleChoiceException e) {
- throw new MultipleEdgeRuleFoundException(e);
- }
- if (!rule.getContains().equals(AAIDirection.NONE.toString())) {
- //vertices = this.queryEngine.findRelatedVertices(v, Direction.OUT, rule.getLabel(), childDbName);
- Direction ruleDirection = rule.getDirection();
- Iterator<Vertex> itr = v.vertices(ruleDirection, rule.getLabel());
- List<Vertex> verticesList = (List<Vertex>)IteratorUtils.toList(itr);
- itr = verticesList.stream().filter(item -> {
- return item.property(AAIProperties.NODE_TYPE).orElse("").equals(childDbName);
- }).iterator();
- if (itr.hasNext()) {
- getList = (List<Object>)obj.getValue(property);
- }
- int processed = 0;
- int removed = 0;
- while (itr.hasNext()) {
- Vertex childVertex = itr.next();
- if (!seen.contains(childVertex)) {
- Introspector argumentObject = obj.newIntrospectorInstanceOfNestedProperty(property);
-
- Object result = dbToObject(argumentObject, childVertex, seen, depth, nodeOnly, cleanUp);
- if (result != null) {
- getList.add(argumentObject.getUnderlyingObject());
- }
-
- processed++;
- } else {
- removed++;
- LOGGER.warn("Cycle found while serializing vertex id={}", childVertex.id().toString());
- }
- }
- if (processed == 0) {
- //vertices were all seen, reset the list
- getList = null;
- }
- if (processed > 0) {
- modified = true;
- }
- }
- } else if (obj.isSimpleGenericType(property)) {
- List<Object> temp = this.engine.getListProperty(v, property);
- if (temp != null) {
- getList = (List<Object>)obj.getValue(property);
- getList.addAll(temp);
- modified = true;
- }
-
- }
-
- }
-
- }
- }
-
- //no changes were made to this obj, discard the instance
- if (!modified) {
- return null;
- }
- this.enrichData(obj, v);
- return obj;
-
- }
-
-
- public Introspector getVertexProperties(Vertex v) throws AAIException, UnsupportedEncodingException {
- String nodeType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
- if (nodeType == null) {
- throw new AAIException("AAI_6143");
- }
-
- Introspector obj = this.latestLoader.introspectorFromName(nodeType);
- Set<Vertex> seen = new HashSet<>();
- int depth = 0;
- String cleanUp = "false";
- boolean nodeOnly = true;
- StopWatch.conditionalStart();
- this.dbToObject(obj, v, seen, depth, nodeOnly, cleanUp);
- dbTimeMsecs += StopWatch.stopIfStarted();
- return obj;
-
- }
- public Introspector getLatestVersionView(Vertex v) throws AAIException, UnsupportedEncodingException {
- String nodeType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
- if (nodeType == null) {
- throw new AAIException("AAI_6143");
- }
- Introspector obj = this.latestLoader.introspectorFromName(nodeType);
- Set<Vertex> seen = new HashSet<>();
- int depth = AAIProperties.MAXIMUM_DEPTH;
- String cleanUp = "false";
- boolean nodeOnly = false;
- StopWatch.conditionalStart();
- Tree<Element> tree = this.engine.getQueryEngine().findSubGraph(v, depth, nodeOnly);
- TreeBackedVertex treeVertex = new TreeBackedVertex(v, tree);
- this.dbToObject(obj, treeVertex, seen, depth, nodeOnly, cleanUp);
- dbTimeMsecs += StopWatch.stopIfStarted();
- return obj;
- }
- /**
- * Copy simple property.
- *
- * @param property the property
- * @param obj the obj
- * @param v the v
- * @throws InstantiationException the instantiation exception
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws NoSuchMethodException the no such method exception
- * @throws SecurityException the security exception
- */
- private void copySimpleProperty(String property, Introspector obj, Vertex v) {
-
- final Map<PropertyMetadata, String> metadata = obj.getPropertyMetadata(property);
- String dbPropertyName = property;
-
- if (metadata.containsKey(PropertyMetadata.DB_ALIAS)) {
- dbPropertyName = metadata.get(PropertyMetadata.DB_ALIAS);
- }
-
-
-
- final Object temp = v.<Object>property(dbPropertyName).orElse(null);
- if (temp != null) {
- obj.setValue(property, temp);
- }
- }
-
- /**
- * Simple db to object.
- *
- * @param obj the obj
- * @param v the v
- * @throws InstantiationException the instantiation exception
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws NoSuchMethodException the no such method exception
- * @throws SecurityException the security exception
- */
- private void simpleDbToObject (Introspector obj, Vertex v) {
- for (String property : obj.getProperties()) {
-
-
- if (!(obj.isComplexType(property) || obj.isListType(property))) {
- this.copySimpleProperty(property, obj, v);
- }
- }
- }
-
- /**
- * Creates the relationship list.
- *
- * @param v the v
- * @param obj the obj
- * @param cleanUp the clean up
- * @return the object
- * @throws InstantiationException the instantiation exception
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws NoSuchMethodException the no such method exception
- * @throws SecurityException the security exception
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIException the AAI exception
- * @throws MalformedURLException the malformed URL exception
- * @throws URISyntaxException
- */
- private Introspector createRelationshipList(Vertex v, Introspector obj, String cleanUp) throws UnsupportedEncodingException, AAIException {
-
- List<Vertex> cousins = this.engine.getQueryEngine().findCousinVertices(v);
-
- List<Object> relationshipObjList = obj.getValue("relationship");
-
- for (Vertex cousin : cousins) {
- if (obj.getVersion().compareTo(schemaVersions.getEdgeLabelVersion()) >= 0) {
- List<Edge> edges = this.getEdgesBetween(EdgeType.COUSIN, v, cousin);
- for (Edge e : edges) {
- Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
- Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, e);
- if (result != null) {
- relationshipObjList.add(result);
- }
- }
- } else {
- Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
- Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, null);
- if (result != null) {
- relationshipObjList.add(result);
- }
- }
-
- }
-
- if (relationshipObjList.isEmpty()) {
- return null;
- } else {
- return obj;
- }
- }
-
- /**
- * Process edge relationship.
- *
- * @param relationshipObj the relationship obj
- * @param edge the edge
- * @param cleanUp the clean up
- * @return the object
- * @throws InstantiationException the instantiation exception
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws NoSuchMethodException the no such method exception
- * @throws SecurityException the security exception
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIException the AAI exception
- * @throws MalformedURLException the malformed URL exception
- * @throws AAIUnknownObjectException
- * @throws URISyntaxException
- */
- private Object processEdgeRelationship(Introspector relationshipObj, Vertex cousin, String cleanUp, Edge edge) throws UnsupportedEncodingException, AAIUnknownObjectException {
-
-
- //we must look up all parents in this case because we need to compute name-properties
- //we cannot used the cached aaiUri to perform this action currently
- Optional<Pair<Vertex, List<Introspector>>> tuple = this.getParents(relationshipObj.getLoader(), cousin, "true".equals(cleanUp));
- //damaged vertex found, ignore
- if (!tuple.isPresent()) {
- return null;
- }
- List<Introspector> list = tuple.get().getValue1();
- URI uri = this.getURIFromList(list);
-
- URIToRelationshipObject uriParser = null;
- Introspector result = null;
- try {
- uriParser = new URIToRelationshipObject(relationshipObj.getLoader(), uri, this.baseURL);
- result = uriParser.getResult();
- } catch (AAIException | URISyntaxException e) {
- LOGGER.error("Error while processing edge relationship in version " + relationshipObj.getVersion() + " (bad vertex ID=" + tuple.get().getValue0().id().toString() + ": "
- + e.getMessage() + " " + LogFormatTools.getStackTop(e));
- if ("true".equals(cleanUp)) {
- this.deleteWithTraversal(tuple.get().getValue0());
- }
- return null;
- }
- if (!list.isEmpty()) {
- this.addRelatedToProperty(result, list.get(0));
- }
-
- if (edge != null && result.hasProperty("relationship-label")) {
- result.setValue("relationship-label", edge.label());
- }
-
- return result.getUnderlyingObject();
- }
-
- /**
- * Gets the URI for vertex.
- *
- * @param v the v
- * @return the URI for vertex
- * @throws InstantiationException the instantiation exception
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws NoSuchMethodException the no such method exception
- * @throws SecurityException the security exception
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIUnknownObjectException
- */
- public URI getURIForVertex(Vertex v) throws UnsupportedEncodingException {
-
- return getURIForVertex(v, false);
- }
-
- public URI getURIForVertex(Vertex v, boolean overwrite) throws UnsupportedEncodingException {
- URI uri = UriBuilder.fromPath("/unknown-uri").build();
-
- String aaiUri = v.<String>property(AAIProperties.AAI_URI).orElse(null);
-
- if (aaiUri != null && !overwrite) {
- uri = UriBuilder.fromPath(aaiUri).build();
- } else {
- StopWatch.conditionalStart();
- Optional<Pair<Vertex, List<Introspector>>> tuple = this.getParents(this.loader, v, false);
- dbTimeMsecs += StopWatch.stopIfStarted();
- if (tuple.isPresent()) {
- List<Introspector> list = tuple.get().getValue1();
- uri = this.getURIFromList(list);
- }
-
-
- }
- return uri;
- }
- /**
- * Gets the URI from list.
- *
- * @param list the list
- * @return the URI from list
- * @throws UnsupportedEncodingException the unsupported encoding exception
- */
- private URI getURIFromList(List<Introspector> list) throws UnsupportedEncodingException {
- String uri = "";
- StringBuilder sb = new StringBuilder();
- for (Introspector i : list) {
- sb.insert(0, i.getURI());
- }
-
- uri = sb.toString();
- return UriBuilder.fromPath(uri).build();
- }
-
- /**
- * Gets the parents.
- *
- * @param start the start
- * @param removeDamaged the remove damaged
- * @return the parents
- * @throws InstantiationException the instantiation exception
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws NoSuchMethodException the no such method exception
- * @throws SecurityException the security exception
- * @throws AAIUnknownObjectException
- */
- private Optional<Pair<Vertex, List<Introspector>>> getParents(Loader loader, Vertex start, boolean removeDamaged) {
-
- List<Vertex> results = this.engine.getQueryEngine().findParents(start);
- List<Introspector> objs = new ArrayList<>();
- boolean shortCircuit = false;
- for (Vertex v : results) {
- String nodeType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
- Introspector obj = null;
- //vertex on the other end of this edge is bad
- if (nodeType == null) {
- //log something here about what was found and that it was removed
- ErrorLogHelper.logError("AAI-6143", "Found a damaged parent vertex " + v.id().toString());
- if (removeDamaged) {
- this.deleteWithTraversal(v);
- }
- shortCircuit = true;
- } else {
- try {
- obj = loader.introspectorFromName(nodeType);
- } catch (AAIUnknownObjectException e) {
- LOGGER.info("attempted to create node type " + nodeType + " but we do not understand it for version: " + loader.getVersion());
- obj = null;
- }
- }
-
- if (obj == null) {
- //can't make a valid path because we don't understand this object
- // don't include it
- } else {
- this.simpleDbToObject(obj, v);
- objs.add(obj);
- }
- }
-
- //stop processing and don't return anything for this bad vertex
- if (shortCircuit) {
- return Optional.empty();
- }
-
- return Optional.of(new Pair<>(results.get(results.size()-1), objs));
- }
-
- /**
- * Adds the r
- * @throws AAIUnknownObjectException
- * @throws IllegalArgumentException elated to property.
- *
- * @param relationship the relationship
- * @param child the throws IllegalArgumentException, AAIUnknownObjectException child
- */
- public void addRelatedToProperty(Introspector relationship, Introspector child) throws AAIUnknownObjectException {
- String nameProps = child.getMetadata(ObjectMetadata.NAME_PROPS);
- List<Introspector> relatedToProperties = new ArrayList<>();
-
- if (nameProps != null) {
- String[] props = nameProps.split(",");
- for (String prop : props) {
- Introspector relatedTo = relationship.newIntrospectorInstanceOfNestedProperty("related-to-property");
- relatedTo.setValue("property-key", child.getDbName() + "." + prop);
- relatedTo.setValue("property-value", child.getValue(prop));
- relatedToProperties.add(relatedTo);
- }
- }
-
- if (!relatedToProperties.isEmpty()) {
- List relatedToList = (List)relationship.getValue("related-to-property");
- for (Introspector obj : relatedToProperties) {
- relatedToList.add(obj.getUnderlyingObject());
- }
- }
-
- }
-
- /**
- * Creates the edge.
- *
- * @param relationship the relationship
- * @param inputVertex the input vertex
- * @return true, if successful
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIException the AAI exception
- */
- public boolean createEdge(Introspector relationship, Vertex inputVertex) throws UnsupportedEncodingException, AAIException {
-
- Vertex relatedVertex = null;
- StopWatch.conditionalStart();
- QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(relationship);
-
- String label = null;
- if (relationship.hasProperty("relationship-label")) {
- label = relationship.getValue("relationship-label");
- }
-
- List<Vertex> results = parser.getQueryBuilder().toList();
- if (results.isEmpty()) {
- dbTimeMsecs += StopWatch.stopIfStarted();
- AAIException e = new AAIException("AAI_6129", "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri());
- e.getTemplateVars().add(parser.getResultType());
- e.getTemplateVars().add(parser.getUri().toString());
- throw e;
- } else {
- //still an issue if there's more than one
- relatedVertex = results.get(0);
- }
-
- if (relatedVertex != null) {
-
- Edge e;
- try {
- e = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex, label);
- if (e == null) {
- edgeSer.addEdge(this.engine.asAdmin().getTraversalSource(), inputVertex, relatedVertex, label);
- } else {
- //attempted to link two vertexes already linked
- }
- } finally {
- dbTimeMsecs += StopWatch.stopIfStarted();
- }
- }
-
- dbTimeMsecs += StopWatch.stopIfStarted();
- return true;
- }
-
- /**
- * Gets all the edges between of the type.
- *
- * @param aVertex the out vertex
- * @param bVertex the in vertex
- * @return the edges between
- * @throws AAIException the AAI exception
- * @throws NoEdgeRuleFoundException
- */
- private List<Edge> getEdgesBetween(EdgeType type, Vertex aVertex, Vertex bVertex) {
-
- List<Edge> result = new ArrayList<>();
-
- if (bVertex != null) {
- GraphTraversal<Vertex, Edge> findEdgesBetween = null;
- findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE();
- if (EdgeType.TREE.equals(type)) {
- findEdgesBetween = findEdgesBetween
- .not(
- __.or(
- __.has(EdgeProperty.CONTAINS.toString(), "NONE"),
- __.has(EdgeField.PRIVATE.toString(), true)
- )
- );
- } else {
- findEdgesBetween = findEdgesBetween
- .has(EdgeProperty.CONTAINS.toString(), "NONE")
- .not(
- __.has(EdgeField.PRIVATE.toString(), true)
- );
- }
- findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(bVertex.id()));
- result = findEdgesBetween.toList();
- }
-
- return result;
- }
- /**
- * Gets all the edges between the vertexes with the label and type.
- *
- * @param aVertex the out vertex
- * @param bVertex the in vertex
- * @param label
- * @return the edges between
- * @throws AAIException the AAI exception
- */
- private List<Edge> getEdgesBetween(EdgeType type, Vertex aVertex, Vertex bVertex, String label) throws AAIException {
-
- List<Edge> result = new ArrayList<>();
-
- if (bVertex != null) {
- String aType = aVertex.<String>property(AAIProperties.NODE_TYPE).value();
- String bType = bVertex.<String>property(AAIProperties.NODE_TYPE).value();
- EdgeRuleQuery q = new EdgeRuleQuery.Builder(aType, bType).edgeType(type).label(label).build();
- EdgeRule rule;
- try {
- rule = edgeRules.getRule(q);
- } catch (EdgeRuleNotFoundException e) {
- throw new NoEdgeRuleFoundException(e);
- } catch (AmbiguousRuleChoiceException e) {
- throw new MultipleEdgeRuleFoundException(e);
- }
- List<Edge> edges = this.getEdgesBetween(type, aVertex, bVertex);
- for (Edge edge : edges) {
- if (edge.label().equals(rule.getLabel())) {
- result.add(edge);
- }
- }
- }
-
- return result;
- }
-
- /**
- * Gets the edge between with the label and edge type.
- *
- * @param aVertex the out vertex
- * @param bVertex the in vertex
- * @param label
- * @return the edge between
- * @throws AAIException the AAI exception
- * @throws NoEdgeRuleFoundException
- */
- public Edge getEdgeBetween(EdgeType type, Vertex aVertex, Vertex bVertex, String label) throws AAIException {
-
- StopWatch.conditionalStart();
- if (bVertex != null) {
-
- List<Edge> edges = this.getEdgesBetween(type, aVertex, bVertex, label);
-
- if (!edges.isEmpty()) {
- dbTimeMsecs += StopWatch.stopIfStarted();
- return edges.get(0);
- }
-
- }
- dbTimeMsecs += StopWatch.stopIfStarted();
- return null;
- }
- public Edge getEdgeBetween(EdgeType type, Vertex aVertex, Vertex bVertex) throws AAIException {
- return this.getEdgeBetween(type, aVertex, bVertex, null);
- }
-
-
- /**
- * Delete edge.
- *
- * @param relationship the relationship
- * @param inputVertex the input vertex
- * @return true, if successful
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIException the AAI exception
- */
- public boolean deleteEdge(Introspector relationship, Vertex inputVertex) throws UnsupportedEncodingException, AAIException {
-
- Vertex relatedVertex = null;
- StopWatch.conditionalStart();
- QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(relationship);
-
- List<Vertex> results = parser.getQueryBuilder().toList();
-
- String label = null;
- if (relationship.hasProperty("relationship-label")) {
- label = relationship.getValue("relationship-label");
- }
-
- if (results.isEmpty()) {
- dbTimeMsecs += StopWatch.stopIfStarted();
- return false;
- }
-
- relatedVertex = results.get(0);
- Edge edge;
- try {
- edge = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex, label);
- } catch (NoEdgeRuleFoundException e) {
- dbTimeMsecs += StopWatch.stopIfStarted();
- throw new AAIException("AAI_6129", e);
- }
- if (edge != null) {
- edge.remove();
- dbTimeMsecs += StopWatch.stopIfStarted();
- return true;
- } else {
- dbTimeMsecs += StopWatch.stopIfStarted();
- return false;
- }
-
- }
-
- /**
- * Delete items with traversal.
- *
- * @param vertexes the vertexes
- * @throws IllegalStateException the illegal state exception
- */
- public void deleteItemsWithTraversal(List<Vertex> vertexes) throws IllegalStateException {
-
- for (Vertex v : vertexes) {
+
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(DBSerializer.class);
+
+ private final TransactionalGraphEngine engine;
+ private final String sourceOfTruth;
+ private final ModelType introspectionType;
+ private final SchemaVersion version;
+ private final Loader latestLoader;
+ private EdgeSerializer edgeSer;
+ private EdgeIngestor edgeRules;
+ private final Loader loader;
+ private final String baseURL;
+ private double dbTimeMsecs = 0;
+ private long currentTimeMillis;
+
+ private SchemaVersions schemaVersions;
+ private Set<String> namedPropNodes;
+ /**
+ * Instantiates a new DB serializer.
+ *
+ * @param version the version
+ * @param engine the engine
+ * @param introspectionType the introspection type
+ * @param sourceOfTruth the source of truth
+ * @throws AAIException
+ */
+ public DBSerializer(SchemaVersion version, TransactionalGraphEngine engine, ModelType introspectionType, String sourceOfTruth) throws AAIException {
+ this.engine = engine;
+ this.sourceOfTruth = sourceOfTruth;
+ this.introspectionType = introspectionType;
+ this.schemaVersions = SpringContextAware.getBean(SchemaVersions.class);
+ SchemaVersion LATEST = schemaVersions.getDefaultVersion();
+ this.latestLoader = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, LATEST);
+ this.version = version;
+ this.loader = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, version);
+ this.namedPropNodes = this.latestLoader.getNamedPropNodes();
+ this.baseURL = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE);
+ this.currentTimeMillis = System.currentTimeMillis();
+ initBeans();
+ }
+
+ private void initBeans() {
+ //TODO proper spring wiring, but that requires a lot of refactoring so for now we have this
+ ApplicationContext ctx = SpringContextAware.getApplicationContext();
+ EdgeIngestor ei = ctx.getBean(EdgeIngestor.class);
+ setEdgeIngestor(ei);
+ EdgeSerializer es = ctx.getBean(EdgeSerializer.class);
+ setEdgeSerializer(es);
+ }
+
+ private void backupESInit() {
+ setEdgeSerializer(new EdgeSerializer(this.edgeRules));
+ }
+
+ public void setEdgeSerializer(EdgeSerializer edgeSer) {
+ this.edgeSer = edgeSer;
+ }
+
+ public EdgeSerializer getEdgeSeriailizer() {
+ return this.edgeSer;
+ }
+
+ public void setEdgeIngestor(EdgeIngestor ei) {
+ this.edgeRules = ei;
+ }
+
+ public EdgeIngestor getEdgeIngestor() {
+ return this.edgeRules;
+ }
+
+ /**
+ * Touch standard vertex properties.
+ *
+ * @param v the v
+ * @param isNewVertex the is new vertex
+ */
+ public void touchStandardVertexProperties(Vertex v, boolean isNewVertex) {
+ 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.LAST_MOD_TS, timeNowInSec);
+ v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, this.sourceOfTruth);
+
+ }
+
+ private void touchStandardVertexProperties(String nodeType, Vertex v, boolean isNewVertex) {
+
+ v.property(AAIProperties.NODE_TYPE, nodeType);
+ touchStandardVertexProperties(v, isNewVertex);
+
+ }
+
+
+ /**
+ * Creates the new vertex.
+ *
+ * @param wrappedObject the wrapped object
+ * @return the vertex
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public Vertex createNewVertex(Introspector wrappedObject) {
+ Vertex v;
+ try {
+ StopWatch.conditionalStart();
+ v = this.engine.tx().addVertex();
+ touchStandardVertexProperties(wrappedObject.getDbName(), v, true);
+ } finally {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ }
+ return v;
+ }
+
+ /**
+ * Trim class name.
+ *
+ * @param className the class name
+ * @return the string
+ */
+ /*
+ * Removes the classpath from a class name
+ */
+ public String trimClassName(String className) {
+ String returnValue = "";
+
+ if (className.lastIndexOf('.') == -1) {
+ return className;
+ }
+ returnValue = className.substring(className.lastIndexOf('.') + 1, className.length());
+
+ return returnValue;
+ }
+
+ /**
+ * Serialize to db.
+ *
+ * @param obj the obj
+ * @param v the v
+ * @param uriQuery the uri query
+ * @param identifier the identifier
+ * @throws SecurityException the security exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws InterruptedException the interrupted exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIUnknownObjectException
+ */
+ public void serializeToDb(Introspector obj, Vertex v, QueryParser uriQuery, String identifier, String requestContext) throws AAIException, UnsupportedEncodingException {
+ StopWatch.conditionalStart();
+ try {
+ if (uriQuery.isDependent()) {
+ //try to find the parent
+ List<Vertex> vertices = uriQuery.getQueryBuilder().getParentQuery().toList();
+ if (!vertices.isEmpty()) {
+ Vertex parent = vertices.get(0);
+ this.reflectDependentVertex(parent, v, obj, requestContext);
+ } else {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ throw new AAIException("AAI_6114", "No parent Node of type " + uriQuery.getParentResultType() + " for " + identifier);
+ }
+ } else {
+ serializeSingleVertex(v, obj, requestContext);
+ }
+
+ } catch (SchemaViolationException e) {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ throw new AAIException("AAI_6117", e);
+ }
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ }
+
+ public void serializeSingleVertex(Vertex v, Introspector obj, String requestContext) throws UnsupportedEncodingException, AAIException {
+ StopWatch.conditionalStart();
+ try {
+ boolean isTopLevel = obj.isTopLevel();
+ if (isTopLevel) {
+ addUriIfNeeded(v, obj.getURI());
+ }
+
+ processObject(obj, v, requestContext);
+ if (!isTopLevel) {
+ URI uri = this.getURIForVertex(v);
+ URIParser parser = new URIParser(this.loader, uri);
+ if (parser.validate()) {
+ addUriIfNeeded(v, uri.toString());
+ }
+ }
+ } catch (SchemaViolationException e) {
+ throw new AAIException("AAI_6117", e);
+ } finally {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ }
+ }
+
+ private void addUriIfNeeded(Vertex v, String uri) {
+ VertexProperty<String> uriProp = v.property(AAIProperties.AAI_URI);
+ if (!uriProp.isPresent() || (uriProp.isPresent() && !uriProp.value().equals(uri))) {
+ v.property(AAIProperties.AAI_URI, uri);
+ }
+ }
+
+ /**
+ * Process object.
+ *
+ * @param <T> the generic type
+ * @param obj the obj
+ * @param v the v
+ * @return the list
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIUnknownObjectException
+ */
+ /*
+ * Helper method for reflectToDb
+ * Handles all the property setting
+ */
+ private <T> List<Vertex> processObject(Introspector obj, Vertex v, String requestContext) throws UnsupportedEncodingException, AAIException {
+ Set<String> properties = new LinkedHashSet<>(obj.getProperties());
+ properties.remove(AAIProperties.RESOURCE_VERSION);
+ List<Vertex> dependentVertexes = new ArrayList<>();
+ List<Vertex> processedVertexes = new ArrayList<>();
+ boolean isComplexType = false;
+ boolean isListType = false;
+ if (!obj.isContainer()) {
+ this.touchStandardVertexProperties(obj.getDbName(), v, false);
+ }
+ this.executePreSideEffects(obj, v);
+ for (String property : properties) {
+ Object value = null;
+ final String propertyType;
+ propertyType = obj.getType(property);
+ isComplexType = obj.isComplexType(property);
+ isListType = obj.isListType(property);
+ value = obj.getValue(property);
+
+ if (!(isComplexType || isListType)) {
+ boolean canModify = this.canModify(obj, property, requestContext);
+
+ if (canModify) {
+ final Map<PropertyMetadata, String> metadata = obj.getPropertyMetadata(property);
+ String dbProperty = property;
+ if (metadata.containsKey(PropertyMetadata.DB_ALIAS)) {
+ dbProperty = metadata.get(PropertyMetadata.DB_ALIAS);
+ }
+ if (metadata.containsKey(PropertyMetadata.DATA_LINK)) {
+ //data linked properties are ephemeral
+ //they are populated dynamically on GETs
+ continue;
+ }
+ if (value != null) {
+ if (!value.equals(v.property(dbProperty).orElse(null))) {
+ if (propertyType.toLowerCase().contains(".long")) {
+ v.property(dbProperty, new Integer(((Long) value).toString()));
+ } else {
+ v.property(dbProperty, value);
+ }
+ }
+ } else {
+ v.property(dbProperty).remove();
+ }
+ }
+ } else if (isListType) {
+ List<Object> list = (List<Object>) value;
+ if (obj.isComplexGenericType(property)) {
+ if (list != null) {
+ for (Object o : list) {
+ Introspector child = IntrospectorFactory.newInstance(this.introspectionType, o);
+ child.setURIChain(obj.getURI());
+ processedVertexes.add(reflectDependentVertex(v, child, requestContext));
+ }
+ }
+ } else {
+ //simple list case
+ engine.setListProperty(v, property, list);
+ }
+ } else {
+ //method.getReturnType() is not 'simple' then create a vertex and edge recursively returning an edge back to this method
+ if (value != null) { //effectively ignore complex properties not included in the object we're processing
+ if (value.getClass().isArray()) {
+
+ int length = Array.getLength(value);
+ for (int i = 0; i < length; i++) {
+ Object arrayElement = Array.get(value, i);
+ Introspector child = IntrospectorFactory.newInstance(this.introspectionType, arrayElement);
+ child.setURIChain(obj.getURI());
+ processedVertexes.add(reflectDependentVertex(v, child, requestContext));
+
+ }
+ } else if (!property.equals("relationship-list")) {
+ // container case
+ Introspector introspector = IntrospectorFactory.newInstance(this.introspectionType, value);
+ if (introspector.isContainer()) {
+ dependentVertexes.addAll(this.engine.getQueryEngine().findChildrenOfType(v, introspector.getChildDBName()));
+ introspector.setURIChain(obj.getURI());
+
+ processedVertexes.addAll(processObject(introspector, v, requestContext));
+
+ } else {
+ dependentVertexes.addAll(this.engine.getQueryEngine().findChildrenOfType(v, introspector.getDbName()));
+ processedVertexes.add(reflectDependentVertex(v, introspector, requestContext));
+
+ }
+ } else if (property.equals("relationship-list")) {
+ handleRelationships(obj, v);
+ }
+ }
+ }
+ }
+ this.writeThroughDefaults(v, obj);
+ /* handle those vertexes not touched */
+ for (Vertex toBeRemoved : processedVertexes) {
+ dependentVertexes.remove(toBeRemoved);
+ }
+ this.deleteItemsWithTraversal(dependentVertexes);
+
+ this.executePostSideEffects(obj, v);
+ return processedVertexes;
+ }
+
+ /**
+ * Handle relationships.
+ *
+ * @param obj the obj
+ * @param vertex the vertex
+ * @throws SecurityException the security exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ /*
+ * Handles the explicit relationships defined for an obj
+ */
+ private void handleRelationships(Introspector obj, Vertex vertex) throws UnsupportedEncodingException, AAIException {
+
+
+ Introspector wrappedRl = obj.getWrappedValue("relationship-list");
+ processRelationshipList(wrappedRl, vertex);
+
+
+ }
+
+
+ /**
+ * Process relationship list.
+ *
+ * @param wrapped the wrapped
+ * @param v the v
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ private void processRelationshipList(Introspector wrapped, Vertex v) throws UnsupportedEncodingException, AAIException {
+
+ List<Object> relationships = (List<Object>) wrapped.getValue("relationship");
+
+ List<Triplet<Vertex, Vertex, String>> addEdges = new ArrayList<>();
+ List<Edge> existingEdges = this.engine.getQueryEngine().findEdgesForVersion(v, wrapped.getLoader());
+
+ for (Object relationship : relationships) {
+ Edge e = null;
+ Vertex cousinVertex = null;
+ String label = null;
+ Introspector wrappedRel = IntrospectorFactory.newInstance(this.introspectionType, relationship);
+ QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(wrappedRel);
+
+ if (wrappedRel.hasProperty("relationship-label")) {
+ label = wrappedRel.getValue("relationship-label");
+ }
+
+ List<Vertex> results = parser.getQueryBuilder().toList();
+ if (results.isEmpty()) {
+ final AAIException ex = new AAIException("AAI_6129", "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri());
+ ex.getTemplateVars().add(parser.getResultType());
+ ex.getTemplateVars().add(parser.getUri().toString());
+ throw ex;
+ } else {
+ //still an issue if there's more than one
+ cousinVertex = results.get(0);
+ }
+
+ if (cousinVertex != null) {
+ String vType = (String) v.property(AAIProperties.NODE_TYPE).value();
+ String cousinType = (String) cousinVertex.property(AAIProperties.NODE_TYPE).value();
+ EdgeRuleQuery.Builder baseQ = new EdgeRuleQuery.Builder(vType, cousinType).label(label);
+
+
+ if (!edgeRules.hasRule(baseQ.build())) {
+ throw new AAIException("AAI_6120", "No EdgeRule found for passed nodeTypes: " + v.property(AAIProperties.NODE_TYPE).value().toString() + ", "
+ + cousinVertex.property(AAIProperties.NODE_TYPE).value().toString() + (label != null ? (" with label " + label) : "") + ".");
+ } else if (edgeRules.hasRule(baseQ.edgeType(EdgeType.TREE).build()) && !edgeRules.hasRule(baseQ.edgeType(EdgeType.COUSIN).build())) {
+ throw new AAIException("AAI_6145");
+ }
+
+ e = this.getEdgeBetween(EdgeType.COUSIN, v, cousinVertex, label);
+
+ if (e == null) {
+ addEdges.add(new Triplet<>(v, cousinVertex, label));
+ } else {
+ existingEdges.remove(e);
+ }
+ }
+ }
+
+ for (Edge edge : existingEdges) {
+ edge.remove();
+ }
+ for (Triplet<Vertex, Vertex, String> triplet : addEdges) {
+ try {
+ edgeSer.addEdge(this.engine.asAdmin().getTraversalSource(), triplet.getValue0(), triplet.getValue1(), triplet.getValue2());
+ } catch (NoEdgeRuleFoundException e) {
+ throw new AAIException("AAI_6129", e);
+ }
+ }
+
+ }
+
+ /**
+ * Write through defaults.
+ *
+ * @param v the v
+ * @param obj the obj
+ * @throws AAIUnknownObjectException
+ */
+ private void writeThroughDefaults(Vertex v, Introspector obj) throws AAIUnknownObjectException {
+ Introspector latest = this.latestLoader.introspectorFromName(obj.getName());
+ if (latest != null) {
+ Set<String> required = latest.getRequiredProperties();
+
+ for (String field : required) {
+ String defaultValue = null;
+ Object vertexProp = null;
+ defaultValue = latest.getPropertyMetadata(field).get(PropertyMetadata.DEFAULT_VALUE);
+ if (defaultValue != null) {
+ vertexProp = v.<Object>property(field).orElse(null);
+ if (vertexProp == null) {
+ v.property(field, defaultValue);
+ }
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * Reflect dependent vertex.
+ *
+ * @param v the v
+ * @param dependentObj the dependent obj
+ * @return the vertex
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIUnknownObjectException
+ */
+ private Vertex reflectDependentVertex(Vertex v, Introspector dependentObj, String requestContext) throws AAIException, UnsupportedEncodingException {
+
+ //QueryParser p = this.engine.getQueryBuilder().createQueryFromURI(obj.getURI());
+ //List<Vertex> items = p.getQuery().toList();
+ QueryBuilder<Vertex> query = this.engine.getQueryBuilder(v);
+ query.createEdgeTraversal(EdgeType.TREE, v, dependentObj);
+ query.createKeyQuery(dependentObj);
+
+ List<Vertex> items = query.toList();
+
+ Vertex dependentVertex = null;
+ if (items.size() == 1) {
+ dependentVertex = items.get(0);
+ this.verifyResourceVersion("update", dependentObj.getDbName(), dependentVertex.<String>property(AAIProperties.RESOURCE_VERSION).orElse(null), (String) dependentObj.getValue(AAIProperties.RESOURCE_VERSION), (String) dependentObj.getURI());
+ } else {
+ this.verifyResourceVersion("create", dependentObj.getDbName(), "", (String) dependentObj.getValue(AAIProperties.RESOURCE_VERSION), (String) dependentObj.getURI());
+ dependentVertex = createNewVertex(dependentObj);
+ }
+
+ return reflectDependentVertex(v, dependentVertex, dependentObj, requestContext);
+
+ }
+
+ /**
+ * Reflect dependent vertex.
+ *
+ * @param parent the parent
+ * @param child the child
+ * @param obj the obj
+ * @return the vertex
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIUnknownObjectException
+ */
+ private Vertex reflectDependentVertex(Vertex parent, Vertex child, Introspector obj, String requestContext) throws AAIException, UnsupportedEncodingException {
+
+ String parentUri = parent.<String>property(AAIProperties.AAI_URI).orElse(null);
+ if (parentUri != null) {
+ String uri;
+ uri = obj.getURI();
+ addUriIfNeeded(child, parentUri + uri);
+ }
+ processObject(obj, child, requestContext);
+
+ Edge e;
+ e = this.getEdgeBetween(EdgeType.TREE, parent, child, null);
+
+ if (e == null) {
+ String canBeLinked = obj.getMetadata(ObjectMetadata.CAN_BE_LINKED);
+ if (canBeLinked != null && canBeLinked.equals("true")) {
+ Loader ldrForCntxt = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(introspectionType, getVerForContext(requestContext));
+ boolean isFirst = !this.engine.getQueryBuilder(ldrForCntxt, parent).createEdgeTraversal(EdgeType.TREE, parent, obj).hasNext();
+ if (isFirst) {
+ child.property(AAIProperties.LINKED, true);
+ }
+ }
+ edgeSer.addTreeEdge(this.engine.asAdmin().getTraversalSource(), parent, child);
+ }
+ return child;
+
+ }
+
+ private SchemaVersion getVerForContext(String requestContext) {
+ Pattern pattern = Pattern.compile("v[0-9]+");
+ Matcher m = pattern.matcher(requestContext);
+ if (!m.find()) {
+ return this.version;
+ } else {
+ return new SchemaVersion(requestContext);
+ }
+ }
+
+ /**
+ * Db to object.
+ *
+ * @param vertices the vertices
+ * @param obj the obj
+ * @param depth the depth
+ * @param cleanUp the clean up
+ * @return the introspector
+ * @throws AAIException the AAI exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws SecurityException the security exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws MalformedURLException the malformed URL exception
+ * @throws AAIUnknownObjectException
+ * @throws URISyntaxException
+ */
+ public Introspector dbToObject(List<Vertex> vertices, final Introspector obj, int depth, boolean nodeOnly, String cleanUp) throws UnsupportedEncodingException, AAIException {
+ final int internalDepth;
+ if (depth == Integer.MAX_VALUE) {
+ internalDepth = depth--;
+ } else {
+ internalDepth = depth;
+ }
+ StopWatch.conditionalStart();
+ if (vertices.size() > 1 && !obj.isContainer()) {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ throw new AAIException("AAI_6136", "query object mismatch: this object cannot hold multiple items." + obj.getDbName());
+ } else if (obj.isContainer()) {
+ final List getList;
+ String listProperty = null;
+ for (String property : obj.getProperties()) {
+ if (obj.isListType(property) && obj.isComplexGenericType(property)) {
+ listProperty = property;
+ break;
+ }
+ }
+ final String propertyName = listProperty;
+ getList = (List) obj.getValue(listProperty);
+
+ /* This is an experimental multithreading experiment
+ * on get alls.
+ */
+ ExecutorService pool = GetAllPool.getInstance().getPool();
+
+ List<Future<Object>> futures = new ArrayList<>();
+
+ QueryEngine tgEngine = this.engine.getQueryEngine();
+ for (Vertex v : vertices) {
+
+ AaiCallable<Object> task = new AaiCallable<Object>() {
+ @Override
+ public Object process() throws UnsupportedEncodingException, AAIException {
+ Set<Vertex> seen = new HashSet<>();
+ Introspector childObject;
+ try {
+ childObject = obj.newIntrospectorInstanceOfNestedProperty(propertyName);
+ } catch (AAIUnknownObjectException e) {
+ throw e;
+ }
+ try {
+ dbToObject(childObject, v, seen, internalDepth, nodeOnly, cleanUp);
+ } catch (UnsupportedEncodingException e) {
+ throw e;
+ } catch (AAIException e) {
+ throw e;
+ }
+ return childObject.getUnderlyingObject();
+ //getList.add(childObject.getUnderlyingObject());
+ }
+ };
+ futures.add(pool.submit(task));
+ }
+
+ for (Future<Object> future : futures) {
+ try {
+ getList.add(future.get());
+ } catch (ExecutionException e) {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ throw new AAIException("AAI_4000", e);
+ } catch (InterruptedException e) {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ throw new AAIException("AAI_4000", e);
+ }
+ }
+ } else if (vertices.size() == 1) {
+ Set<Vertex> seen = new HashSet<>();
+ dbToObject(obj, vertices.get(0), seen, depth, nodeOnly, cleanUp);
+ } else {
+ //obj = null;
+ }
+
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ return obj;
+ }
+
+ /**
+ * Db to object.
+ *
+ * @param obj the obj
+ * @param v the v
+ * @param seen the seen
+ * @param depth the depth
+ * @param cleanUp the clean up
+ * @return the introspector
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws SecurityException the security exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ * @throws MalformedURLException the malformed URL exception
+ * @throws AAIUnknownObjectException
+ * @throws URISyntaxException
+ */
+ private Introspector dbToObject(Introspector obj, Vertex v, Set<Vertex> seen, int depth, boolean nodeOnly, String cleanUp) throws AAIException, UnsupportedEncodingException {
+
+ if (depth < 0) {
+ return null;
+ }
+ depth--;
+ seen.add(v);
+
+ boolean modified = false;
+ for (String property : obj.getProperties(PropertyPredicates.isVisible())) {
+ List<Object> getList = null;
+ Vertex[] vertices = null;
+
+ if (!(obj.isComplexType(property) || obj.isListType(property))) {
+ this.copySimpleProperty(property, obj, v);
+ modified = true;
+ } else {
+ if (obj.isComplexType(property)) {
+ /* container case */
+
+ if (!property.equals("relationship-list") && depth >= 0) {
+ Introspector argumentObject = obj.newIntrospectorInstanceOfProperty(property);
+ Object result = dbToObject(argumentObject, v, seen, depth + 1, nodeOnly, cleanUp);
+ if (result != null) {
+ obj.setValue(property, argumentObject.getUnderlyingObject());
+ modified = true;
+ }
+ } else if (property.equals("relationship-list") && !nodeOnly) {
+ /* relationships need to be handled correctly */
+ Introspector relationshipList = obj.newIntrospectorInstanceOfProperty(property);
+ relationshipList = createRelationshipList(v, relationshipList, cleanUp);
+ if (relationshipList != null) {
+ modified = true;
+ obj.setValue(property, relationshipList.getUnderlyingObject());
+ modified = true;
+ }
+
+ }
+ } else if (obj.isListType(property)) {
+
+ if (property.equals("any")) {
+ continue;
+ }
+ String genericType = obj.getGenericTypeClass(property).getSimpleName();
+ if (obj.isComplexGenericType(property) && depth >= 0) {
+ final String childDbName = convertFromCamelCase(genericType);
+ String vType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ EdgeRule rule;
+
+ try {
+ rule = edgeRules.getRule(new EdgeRuleQuery.Builder(vType, childDbName).edgeType(EdgeType.TREE).build());
+ } catch (EdgeRuleNotFoundException e) {
+ throw new NoEdgeRuleFoundException(e);
+ } catch (AmbiguousRuleChoiceException e) {
+ throw new MultipleEdgeRuleFoundException(e);
+ }
+ if (!rule.getContains().equals(AAIDirection.NONE.toString())) {
+ //vertices = this.queryEngine.findRelatedVertices(v, Direction.OUT, rule.getLabel(), childDbName);
+ Direction ruleDirection = rule.getDirection();
+ Iterator<Vertex> itr = v.vertices(ruleDirection, rule.getLabel());
+ List<Vertex> verticesList = (List<Vertex>) IteratorUtils.toList(itr);
+ itr = verticesList.stream().filter(item -> {
+ return item.property(AAIProperties.NODE_TYPE).orElse("").equals(childDbName);
+ }).iterator();
+ if (itr.hasNext()) {
+ getList = (List<Object>) obj.getValue(property);
+ }
+ int processed = 0;
+ int removed = 0;
+ while (itr.hasNext()) {
+ Vertex childVertex = itr.next();
+ if (!seen.contains(childVertex)) {
+ Introspector argumentObject = obj.newIntrospectorInstanceOfNestedProperty(property);
+
+ Object result = dbToObject(argumentObject, childVertex, seen, depth, nodeOnly, cleanUp);
+ if (result != null) {
+ getList.add(argumentObject.getUnderlyingObject());
+ }
+
+ processed++;
+ } else {
+ removed++;
+ LOGGER.warn("Cycle found while serializing vertex id={}", childVertex.id().toString());
+ }
+ }
+ if (processed == 0) {
+ //vertices were all seen, reset the list
+ getList = null;
+ }
+ if (processed > 0) {
+ modified = true;
+ }
+ }
+ } else if (obj.isSimpleGenericType(property)) {
+ List<Object> temp = this.engine.getListProperty(v, property);
+ if (temp != null) {
+ getList = (List<Object>) obj.getValue(property);
+ getList.addAll(temp);
+ modified = true;
+ }
+
+ }
+
+ }
+
+ }
+ }
+
+ //no changes were made to this obj, discard the instance
+ if (!modified) {
+ return null;
+ }
+ this.enrichData(obj, v);
+ return obj;
+
+ }
+
+
+ public Introspector getVertexProperties(Vertex v) throws AAIException, UnsupportedEncodingException {
+ String nodeType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ if (nodeType == null) {
+ throw new AAIException("AAI_6143");
+ }
+
+ Introspector obj = this.latestLoader.introspectorFromName(nodeType);
+ Set<Vertex> seen = new HashSet<>();
+ int depth = 0;
+ String cleanUp = "false";
+ boolean nodeOnly = true;
+ StopWatch.conditionalStart();
+ this.dbToObject(obj, v, seen, depth, nodeOnly, cleanUp);
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ return obj;
+
+ }
+
+ public Introspector getLatestVersionView(Vertex v) throws AAIException, UnsupportedEncodingException {
+ String nodeType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ if (nodeType == null) {
+ throw new AAIException("AAI_6143");
+ }
+ Introspector obj = this.latestLoader.introspectorFromName(nodeType);
+ Set<Vertex> seen = new HashSet<>();
+ int depth = AAIProperties.MAXIMUM_DEPTH;
+ String cleanUp = "false";
+ boolean nodeOnly = false;
+ StopWatch.conditionalStart();
+ Tree<Element> tree = this.engine.getQueryEngine().findSubGraph(v, depth, nodeOnly);
+ TreeBackedVertex treeVertex = new TreeBackedVertex(v, tree);
+ this.dbToObject(obj, treeVertex, seen, depth, nodeOnly, cleanUp);
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ return obj;
+ }
+
+ /**
+ * Copy simple property.
+ *
+ * @param property the property
+ * @param obj the obj
+ * @param v the v
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ */
+ private void copySimpleProperty(String property, Introspector obj, Vertex v) {
+
+ final Map<PropertyMetadata, String> metadata = obj.getPropertyMetadata(property);
+ String dbPropertyName = property;
+
+ if (metadata.containsKey(PropertyMetadata.DB_ALIAS)) {
+ dbPropertyName = metadata.get(PropertyMetadata.DB_ALIAS);
+ }
+
+
+ final Object temp = v.<Object>property(dbPropertyName).orElse(null);
+ if (temp != null) {
+ obj.setValue(property, temp);
+ }
+ }
+
+
+ /**
+ * Load the introspector from the hashmap for the given property key
+ *
+ * @param property - vertex property
+ * @param obj - introspector object representing the vertex
+ * @param hashMap - Containing a list of pre-fetched properties for a given vertex
+ */
+ private void copySimplePropertyFromHashMap(String property, Introspector obj, Map<String, Object> hashMap){
+
+ final Map<PropertyMetadata, String> metadata = obj.getPropertyMetadata(property);
+ String dbPropertyName = property;
+
+ if (metadata.containsKey(PropertyMetadata.DB_ALIAS)) {
+ dbPropertyName = metadata.get(PropertyMetadata.DB_ALIAS);
+ }
+
+ final Object temp = hashMap.getOrDefault(dbPropertyName, null);
+
+ if (temp != null) {
+ obj.setValue(property, temp);
+ }
+ }
+
+ /**
+ * Simple db to object.
+ *
+ * @param obj the obj
+ * @param v the v
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ */
+ private void simpleDbToObject(Introspector obj, Vertex v) {
+ for(String key : obj.getProperties()){
+ this.copySimpleProperty(key, obj, v);
+ }
+ }
+
+
+ public Map<String, Object> convertVertexToHashMap(Introspector obj, Vertex v){
+
+ long startTime = System.currentTimeMillis();
+
+ Set<String> simpleProperties = obj.getSimpleProperties(PropertyPredicates.isVisible());
+ String[] simplePropsArray = new String[simpleProperties.size()];
+ simplePropsArray = simpleProperties.toArray(simplePropsArray);
+
+ Map<String, Object> simplePropsHashMap = new HashMap<>(simplePropsArray.length * 2);
+
+ v.properties(simplePropsArray).forEachRemaining((vp) -> simplePropsHashMap.put(vp.key(), vp.value()));
+
+ return simplePropsHashMap;
+ }
+
+ /**
+ * Creates the relationship list.
+ *
+ * @param v the v
+ * @param obj the obj
+ * @param cleanUp the clean up
+ * @return the object
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ * @throws MalformedURLException the malformed URL exception
+ * @throws URISyntaxException
+ */
+ private Introspector createRelationshipList(Vertex v, Introspector obj, String cleanUp) throws UnsupportedEncodingException, AAIException {
+
+ String[] cousinRules = new String[0];
+
+ try {
+ cousinRules = edgeRules.retrieveCachedCousinLabels(obj.getDbName());
+ } catch (ExecutionException e) {
+ LOGGER.warn("Encountered an execution exception while retrieving labels for the node type {} using cached", obj.getDbName(), e);
+ }
+
+ List<Vertex> cousins = null;
+ if(cousinRules != null && cousinRules.length != 0){
+ cousins = this.engine.getQueryEngine().findCousinVertices(v, cousinRules);
+ } else {
+ cousins = this.engine.getQueryEngine().findCousinVertices(v);
+ }
+
+ List<Object> relationshipObjList = obj.getValue("relationship");
+ String aNodeType = v.property("aai-node-type").value().toString();
+
+ TypeAlphabetizer alphabetizer = new TypeAlphabetizer();
+
+ EdgeIngestor edgeIngestor = SpringContextAware.getBean(EdgeIngestor.class);
+ Set<String> keysWithMultipleLabels = edgeIngestor.getMultipleLabelKeys();
+
+ // For the given vertex, find all the cousins
+ // For each cousin retrieve the node type and then
+ // check if the version is greater than the edge label version
+ // meaning is the current version equal to greater than the version
+ // where we introduced the edge labels into the relationship payload
+ // If it is, then we check if the edge key there are multiple labels
+ // If there are multiple labels, then we need to go to the database
+ // to retrieve the labels between itself and cousin vertex
+ // If there is only single label between the edge a and b, then
+ // we can retrieve what that is without going to the database
+ // from using the edge rules json and get the edge rule out of it
+ EdgeRuleQuery.Builder queryBuilder = new EdgeRuleQuery.Builder(aNodeType);
+ for (Vertex cousin : cousins) {
+ VertexProperty vertexProperty = cousin.property("aai-node-type");
+ String bNodeType = null;
+ if(vertexProperty.isPresent()){
+ bNodeType = cousin.property("aai-node-type").value().toString();
+ } else {
+ // If the vertex is missing the aai-node-type
+ // Then its either a bad vertex or its in the process
+ // of getting deleted so we should ignore these vertexes
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("For the vertex {}, unable to retrieve the aai-node-type", v.id().toString());
+ } else {
+ LOGGER.info("Unable to retrieve the aai-node-type for vertex, for more info enable debug log");
+ }
+ continue;
+ }
+ if (obj.getVersion().compareTo(schemaVersions.getEdgeLabelVersion()) >= 0) {
+ String edgeKey = alphabetizer.buildAlphabetizedKey(aNodeType, bNodeType);
+ if(keysWithMultipleLabels.contains(edgeKey)){
+ List<String> edgeLabels = this.getEdgeLabelsBetween(EdgeType.COUSIN, v, cousin);
+ for(String edgeLabel: edgeLabels){
+ Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
+ Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, edgeLabel);
+ if (result != null) {
+ relationshipObjList.add(result);
+ }
+ }
+ } else {
+
+ EdgeRule edgeRule = null;
+
+ // Create a query based on the a nodetype and b nodetype
+ // which is also a cousin edge and ensure the version
+ // is used properly so for example in order to be backwards
+ // compatible if we had allowed a edge between a and b
+ // in a previous release and we decided to remove it from
+ // the edge rules in the future we can display the edge
+ // only for the older apis and the new apis if the edge rule
+ // is removed will not be seen in the newer version of the API
+
+ EdgeRuleQuery ruleQuery = queryBuilder
+ .to(bNodeType)
+ .edgeType(EdgeType.COUSIN)
+ .version(obj.getVersion())
+ .build();
+
+ try {
+ edgeRule = edgeIngestor.getRule(ruleQuery);
+ } catch (EdgeRuleNotFoundException e) {
+ LOGGER.warn("Caught an edge rule not found exception for query {}, {}," +
+ " it could be the edge rule is no longer valid for the existing edge in db",
+ ruleQuery, LogFormatTools.getStackTop(e));
+ continue;
+ } catch (AmbiguousRuleChoiceException e) {
+ LOGGER.error("Caught an ambiguous rule not found exception for query {}, {}",
+ ruleQuery, LogFormatTools.getStackTop(e));
+ continue;
+ }
+
+ Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
+ Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp,edgeRule.getLabel());
+ if (result != null) {
+ relationshipObjList.add(result);
+ }
+ }
+ } else {
+ Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
+ Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, null);
+ if (result != null) {
+ relationshipObjList.add(result);
+ }
+ }
+
+ }
+
+ if (relationshipObjList.isEmpty()) {
+ return null;
+ } else {
+ return obj;
+ }
+ }
+
+ /**
+ * Process edge relationship.
+ *
+ * @param relationshipObj the relationship obj
+ * @param edge the edge
+ * @param cleanUp the clean up
+ * @return the object
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ * @throws MalformedURLException the malformed URL exception
+ * @throws AAIUnknownObjectException
+ * @throws URISyntaxException
+ */
+ private Object processEdgeRelationship(Introspector relationshipObj, Vertex cousin, String cleanUp, String edgeLabel) throws UnsupportedEncodingException, AAIUnknownObjectException {
+
+ VertexProperty aaiUriProperty = cousin.property("aai-uri");
+
+ if(!aaiUriProperty.isPresent()){
+ return null;
+ }
+
+ URI uri = UriBuilder.fromUri(aaiUriProperty.value().toString()).build();
+
+ URIToRelationshipObject uriParser = null;
+ Introspector result = null;
+ try {
+ uriParser = new URIToRelationshipObject(relationshipObj.getLoader(), uri, this.baseURL);
+ result = uriParser.getResult();
+ } catch (AAIException | URISyntaxException e) {
+ LOGGER.error("Error while processing edge relationship in version " + relationshipObj.getVersion() + " (bad vertex ID=" + ": "
+ + e.getMessage() + " " + LogFormatTools.getStackTop(e));
+ return null;
+ }
+
+ VertexProperty cousinVertexNodeType = cousin.property(AAIProperties.NODE_TYPE);
+
+ if(cousinVertexNodeType.isPresent()){
+ if(namedPropNodes.contains(cousinVertexNodeType.value().toString())){
+ Introspector cousinObj = loader.introspectorFromName(cousinVertexNodeType.value().toString());
+ this.simpleDbToObject(cousinObj, cousin);
+ this.addRelatedToProperty(result, cousinObj);
+ }
+ }
+
+ if (edgeLabel != null && result.hasProperty("relationship-label")) {
+ result.setValue("relationship-label", edgeLabel);
+ }
+
+ return result.getUnderlyingObject();
+ }
+
+ /**
+ * Gets the URI for vertex.
+ *
+ * @param v the v
+ * @return the URI for vertex
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIUnknownObjectException
+ */
+ public URI getURIForVertex(Vertex v) throws UnsupportedEncodingException {
+
+ return getURIForVertex(v, false);
+ }
+
+ public URI getURIForVertex(Vertex v, boolean overwrite) throws UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/unknown-uri").build();
+
+ String aaiUri = v.<String>property(AAIProperties.AAI_URI).orElse(null);
+
+ if (aaiUri != null && !overwrite) {
+ uri = UriBuilder.fromPath(aaiUri).build();
+ }
+
+ return uri;
+ }
+
+ /**
+ * Gets the URI from list.
+ *
+ * @param list the list
+ * @return the URI from list
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private URI getURIFromList(List<Introspector> list) throws UnsupportedEncodingException {
+ String uri = "";
+ StringBuilder sb = new StringBuilder();
+ for (Introspector i : list) {
+ sb.insert(0, i.getURI());
+ }
+
+ uri = sb.toString();
+ return UriBuilder.fromPath(uri).build();
+ }
+
+ /**
+ * Adds the r
+ *
+ * @param relationship the relationship
+ * @param child the throws IllegalArgumentException, AAIUnknownObjectException child
+ * @throws AAIUnknownObjectException
+ * @throws IllegalArgumentException elated to property.
+ */
+ public void addRelatedToProperty(Introspector relationship, Introspector child) throws AAIUnknownObjectException {
+ String nameProps = child.getMetadata(ObjectMetadata.NAME_PROPS);
+ List<Introspector> relatedToProperties = new ArrayList<>();
+
+ if (nameProps != null) {
+ String[] props = nameProps.split(",");
+ for (String prop : props) {
+ Introspector relatedTo = relationship.newIntrospectorInstanceOfNestedProperty("related-to-property");
+ relatedTo.setValue("property-key", child.getDbName() + "." + prop);
+ relatedTo.setValue("property-value", child.getValue(prop));
+ relatedToProperties.add(relatedTo);
+ }
+ }
+
+ if (!relatedToProperties.isEmpty()) {
+ List relatedToList = (List) relationship.getValue("related-to-property");
+ for (Introspector obj : relatedToProperties) {
+ relatedToList.add(obj.getUnderlyingObject());
+ }
+ }
+
+ }
+
+ /**
+ * Creates the edge.
+ *
+ * @param relationship the relationship
+ * @param inputVertex the input vertex
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public boolean createEdge(Introspector relationship, Vertex inputVertex) throws UnsupportedEncodingException, AAIException {
+
+ Vertex relatedVertex = null;
+ StopWatch.conditionalStart();
+ QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(relationship);
+
+ String label = null;
+ if (relationship.hasProperty("relationship-label")) {
+ label = relationship.getValue("relationship-label");
+ }
+
+ List<Vertex> results = parser.getQueryBuilder().toList();
+ if (results.isEmpty()) {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ AAIException e = new AAIException("AAI_6129", "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri());
+ e.getTemplateVars().add(parser.getResultType());
+ e.getTemplateVars().add(parser.getUri().toString());
+ throw e;
+ } else {
+ //still an issue if there's more than one
+ relatedVertex = results.get(0);
+ }
+
+ if (relatedVertex != null) {
+
+ Edge e;
+ try {
+ e = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex, label);
+ if (e == null) {
+ edgeSer.addEdge(this.engine.asAdmin().getTraversalSource(), inputVertex, relatedVertex, label);
+ } else {
+ //attempted to link two vertexes already linked
+ }
+ } finally {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ }
+ }
+
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ return true;
+ }
+
+ /**
+ * Gets all the edges between of the type with the specified label.
+ *
+ * @param aVertex the out vertex
+ * @param bVertex the in vertex
+ * @return the edges between
+ * @throws AAIException the AAI exception
+ * @throws NoEdgeRuleFoundException
+ */
+ private Edge getEdgeBetweenWithLabel(EdgeType type, Vertex aVertex, Vertex bVertex, EdgeRule edgeRule) {
+
+ Edge result = null;
+
+ if (bVertex != null) {
+ GraphTraversal<Vertex, Edge> findEdgesBetween = null;
+ if (EdgeType.TREE.equals(type)) {
+ GraphTraversal<Vertex,Vertex> findVertex = this.engine.asAdmin().getTraversalSource().V(bVertex);
+ if(edgeRule.getDirection().equals(Direction.IN)){
+ findEdgesBetween = findVertex.outE(edgeRule.getLabel())
+ .has(EdgeProperty.CONTAINS.toString(), edgeRule.getContains())
+ .not(
+ __.has(EdgeField.PRIVATE.toString(), true)
+ );
+ } else {
+ findEdgesBetween = findVertex.inE(edgeRule.getLabel())
+ .has(EdgeProperty.CONTAINS.toString(), edgeRule.getContains())
+ .not(
+ __.has(EdgeField.PRIVATE.toString(), true)
+ );
+ }
+ findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(aVertex.id())).limit(1);
+ } else {
+ findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE(edgeRule.getLabel());
+ findEdgesBetween = findEdgesBetween
+ .has(EdgeProperty.CONTAINS.toString(), "NONE")
+ .not(
+ __.has(EdgeField.PRIVATE.toString(), true)
+ );
+ findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(bVertex.id())).limit(1);
+ }
+ List<Edge> list = findEdgesBetween.toList();
+ if(!list.isEmpty()){
+ result = list.get(0);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Gets all the edges between of the type.
+ *
+ * @param aVertex the out vertex
+ * @param bVertex the in vertex
+ * @return the edges between
+ * @throws AAIException the AAI exception
+ * @throws NoEdgeRuleFoundException
+ */
+ private List<Edge> getEdgesBetween(EdgeType type, Vertex aVertex, Vertex bVertex) {
+
+ List<Edge> result = new ArrayList<>();
+
+ if (bVertex != null) {
+ GraphTraversal<Vertex, Edge> findEdgesBetween = null;
+ findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE();
+ if (EdgeType.TREE.equals(type)) {
+ findEdgesBetween = findEdgesBetween
+ .not(
+ __.or(
+ __.has(EdgeProperty.CONTAINS.toString(), "NONE"),
+ __.has(EdgeField.PRIVATE.toString(), true)
+ )
+ );
+ } else {
+ findEdgesBetween = findEdgesBetween
+ .has(EdgeProperty.CONTAINS.toString(), "NONE")
+ .not(
+ __.has(EdgeField.PRIVATE.toString(), true)
+ );
+ }
+ findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(bVertex.id()));
+ result = findEdgesBetween.toList();
+ }
+
+ return result;
+ }
+
+ /**
+ * Gets all the edges string between of the type.
+ *
+ * @param aVertex the out vertex
+ * @param bVertex the in vertex
+ * @return the edges between
+ * @throws AAIException the AAI exception
+ * @throws NoEdgeRuleFoundException
+ */
+ private List<String> getEdgeLabelsBetween(EdgeType type, Vertex aVertex, Vertex bVertex) {
+
+ List<String> result = new ArrayList<>();
+
+ if (bVertex != null) {
+ GraphTraversal<Vertex, Edge> findEdgesBetween = null;
+ findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE();
+ if (EdgeType.TREE.equals(type)) {
+ findEdgesBetween = findEdgesBetween
+ .not(
+ __.or(
+ __.has(EdgeProperty.CONTAINS.toString(), "NONE"),
+ __.has(EdgeField.PRIVATE.toString(), true)
+ )
+ );
+ } else {
+ findEdgesBetween = findEdgesBetween
+ .has(EdgeProperty.CONTAINS.toString(), "NONE")
+ .not(
+ __.has(EdgeField.PRIVATE.toString(), true)
+ );
+ }
+ findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(bVertex.id()));
+ result = findEdgesBetween.label().toList();
+ }
+ return result;
+ }
+
+ /**
+ * Gets all the edges string between of the type.
+ *
+ * @param aVertex the out vertex
+ * @param bVertex the in vertex
+ * @return the edges between
+ * @throws AAIException the AAI exception
+ * @throws NoEdgeRuleFoundException
+ */
+ private Long getEdgeLabelsCount(Vertex aVertex, Vertex bVertex) {
+
+ Long result = null;
+
+ if (bVertex != null) {
+ GraphTraversal<Vertex, Edge> findEdgesBetween = null;
+ findEdgesBetween = this.engine.asAdmin().getTraversalSource().V(aVertex).bothE();
+ findEdgesBetween = findEdgesBetween
+ .has(EdgeProperty.CONTAINS.toString(), "NONE")
+ .not(
+ __.has(EdgeField.PRIVATE.toString(), true)
+ );
+ findEdgesBetween = findEdgesBetween.filter(__.otherV().hasId(bVertex.id()));
+ result = findEdgesBetween.count().next();
+ }
+ return result;
+ }
+ /**
+ * Gets all the edges between the vertexes with the label and type.
+ *
+ * @param aVertex the out vertex
+ * @param bVertex the in vertex
+ * @param label
+ * @return the edges between
+ * @throws AAIException the AAI exception
+ */
+ private Edge getEdgesBetween(EdgeType type, Vertex aVertex, Vertex bVertex, String label) throws AAIException {
+
+ Edge edge = null;
+
+ if (bVertex != null) {
+ String aType = aVertex.<String>property(AAIProperties.NODE_TYPE).value();
+ String bType = bVertex.<String>property(AAIProperties.NODE_TYPE).value();
+ EdgeRuleQuery q = new EdgeRuleQuery.Builder(aType, bType).edgeType(type).label(label).build();
+ EdgeRule rule;
+ try {
+ rule = edgeRules.getRule(q);
+ } catch (EdgeRuleNotFoundException e) {
+ throw new NoEdgeRuleFoundException(e);
+ } catch (AmbiguousRuleChoiceException e) {
+ throw new MultipleEdgeRuleFoundException(e);
+ }
+ edge = this.getEdgeBetweenWithLabel(type, aVertex, bVertex, rule);
+ }
+
+ return edge;
+ }
+
+ /**
+ * Gets the edge between with the label and edge type.
+ *
+ * @param aVertex the out vertex
+ * @param bVertex the in vertex
+ * @param label
+ * @return the edge between
+ * @throws AAIException the AAI exception
+ * @throws NoEdgeRuleFoundException
+ */
+ public Edge getEdgeBetween(EdgeType type, Vertex aVertex, Vertex bVertex, String label) throws AAIException {
+
+ StopWatch.conditionalStart();
+ if (bVertex != null) {
+
+ Edge edge = this.getEdgesBetween(type, aVertex, bVertex, label);
+ if (edge != null) {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ return edge;
+ }
+
+ }
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ return null;
+ }
+
+ public Edge getEdgeBetween(EdgeType type, Vertex aVertex, Vertex bVertex) throws AAIException {
+ return this.getEdgeBetween(type, aVertex, bVertex, null);
+ }
+
+
+ /**
+ * Delete edge.
+ *
+ * @param relationship the relationship
+ * @param inputVertex the input vertex
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public boolean deleteEdge(Introspector relationship, Vertex inputVertex) throws UnsupportedEncodingException, AAIException {
+
+ Vertex relatedVertex = null;
+ StopWatch.conditionalStart();
+ QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(relationship);
+
+ List<Vertex> results = parser.getQueryBuilder().toList();
+
+ String label = null;
+ if (relationship.hasProperty("relationship-label")) {
+ label = relationship.getValue("relationship-label");
+ }
+
+ if (results.isEmpty()) {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ return false;
+ }
+
+ relatedVertex = results.get(0);
+ Edge edge;
+ try {
+ edge = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex, label);
+ } catch (NoEdgeRuleFoundException e) {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ throw new AAIException("AAI_6129", e);
+ }
+ if (edge != null) {
+ edge.remove();
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ return true;
+ } else {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ return false;
+ }
+
+ }
+
+ /**
+ * Delete items with traversal.
+ *
+ * @param vertexes the vertexes
+ * @throws IllegalStateException the illegal state exception
+ */
+ public void deleteItemsWithTraversal(List<Vertex> vertexes) throws IllegalStateException {
+
+ for (Vertex v : vertexes) {
LOGGER.debug("About to delete the vertex with id: " + v.id());
- deleteWithTraversal(v);
- }
-
- }
-
- /**
- * Delete with traversal.
- *
- * @param startVertex the start vertex
- */
- public void deleteWithTraversal(Vertex startVertex) {
- StopWatch.conditionalStart();
- List<Vertex> results = this.engine.getQueryEngine().findDeletable(startVertex);
-
- for (Vertex v : results) {
- LOGGER.warn("Removing vertex " + v.id().toString());
-
- v.remove();
- }
- dbTimeMsecs += StopWatch.stopIfStarted();
- }
-
- /**
- * Delete.
- *
- * @param v the v
- * @param resourceVersion the resource version
- * @throws IllegalArgumentException the illegal argument exception
- * @throws AAIException the AAI exception
- * @throws InterruptedException the interrupted exception
- */
- public void delete(Vertex v, List<Vertex> deletableVertices, String resourceVersion, boolean enableResourceVersion) throws IllegalArgumentException, AAIException {
-
- boolean result = verifyDeleteSemantics(v, resourceVersion, enableResourceVersion);
- /*
- * The reason why I want to call PreventDeleteSemantics second time is to catch the prevent-deletes in a chain
- * These are far-fewer than seeing a prevnt-delete on the vertex to be deleted
- * So its better to make these in 2 steps
- */
- if(result && !deletableVertices.isEmpty()){
- result = verifyPreventDeleteSemantics(deletableVertices);
- }
- if (result) {
-
- try {
- deleteWithTraversal(v);
- } catch (IllegalStateException e) {
- throw new AAIException("AAI_6110", e);
- }
-
- }
-
- }
-
-
- /**
- * Delete.
- *
- * @param v the v
- * @param resourceVersion the resource version
- * @throws IllegalArgumentException the illegal argument exception
- * @throws AAIException the AAI exception
- * @throws InterruptedException the interrupted exception
- */
- public void delete(Vertex v, String resourceVersion, boolean enableResourceVersion) throws IllegalArgumentException, AAIException {
-
- boolean result = verifyDeleteSemantics(v, resourceVersion, enableResourceVersion);
-
- if (result) {
-
- try {
- deleteWithTraversal(v);
- } catch (IllegalStateException e) {
- throw new AAIException("AAI_6110", e);
- }
-
- }
-
- }
- /**
- * Verify delete semantics.
- *
- * @param vertex the vertex
- * @param resourceVersion the resource version
- * @return true, if successful
- * @throws AAIException the AAI exception
- */
- private boolean verifyDeleteSemantics(Vertex vertex, String resourceVersion, boolean enableResourceVersion) throws AAIException {
- boolean result = true;
- String nodeType = "";
- String errorDetail = " unknown delete semantic found";
- String aaiExceptionCode = "";
- nodeType = vertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
- if (enableResourceVersion && !this.verifyResourceVersion("delete", nodeType, vertex.<String>property(AAIProperties.RESOURCE_VERSION).orElse(null), resourceVersion, nodeType)) {
- }
- List<Vertex> vertices = new ArrayList<Vertex>();
- vertices.add(vertex);
- result = verifyPreventDeleteSemantics(vertices);
-
- return result;
- }
-
- /**
- * Verify Prevent delete semantics.
- * @param vertices the list of vertices
- * @return true, if successful
- * @throws AAIException the AAI exception
- */
- private boolean verifyPreventDeleteSemantics(List<Vertex> vertices) throws AAIException {
- boolean result = true;
- String nodeType = "";
- String errorDetail = " unknown delete semantic found";
- String aaiExceptionCode = "";
-
- StopWatch.conditionalStart();
- /*
- * This takes in all the vertices in a cascade-delete-chain and checks if there is any edge with a "prevent-delete" condition
- * If yes - that should prevent the deletion of the vertex
- * Dedup makes sure we dont capture the prevent-delete vertices twice
- * The prevent-delete vertices are stored so that the error message displays what prevents the delete
- */
-
- List<Object> preventDeleteVertices = this.engine.asAdmin().getReadOnlyTraversalSource().V(vertices).
- union(__.inE().has(EdgeProperty.PREVENT_DELETE.toString(), AAIDirection.IN.toString()).outV().values(AAIProperties.NODE_TYPE),
- __.outE().has(EdgeProperty.PREVENT_DELETE.toString(), AAIDirection.OUT.toString()).inV().values(AAIProperties.NODE_TYPE))
- .dedup().toList();
-
- dbTimeMsecs += StopWatch.stopIfStarted();
- if (!preventDeleteVertices.isEmpty()) {
- aaiExceptionCode = "AAI_6110";
- errorDetail = String.format("Object is being reference by additional objects preventing it from being deleted. Please clean up references from the following types %s", preventDeleteVertices);
- result = false;
- }
- if (!result) {
- throw new AAIException(aaiExceptionCode, errorDetail);
- }
- return result;
- }
-
- /**
- * Verify resource version.
- *
- * @param action the action
- * @param nodeType the node type
- * @param currentResourceVersion the current resource version
- * @param resourceVersion the resource version
- * @param uri the uri
- * @return true, if successful
- * @throws AAIException the AAI exception
- */
- public boolean verifyResourceVersion(String action, String nodeType, String currentResourceVersion, String resourceVersion, String uri) throws AAIException {
- String enabled = "";
- String errorDetail = "";
- String aaiExceptionCode = "";
- if (currentResourceVersion == null) {
- currentResourceVersion = "";
- }
-
- if (resourceVersion == null) {
- resourceVersion = "";
- }
- try {
- enabled = AAIConfig.get(AAIConstants.AAI_RESVERSION_ENABLEFLAG);
- } catch (AAIException e) {
- ErrorLogHelper.logException(e);
- }
- if (enabled.equals("true")) {
- if (!currentResourceVersion.equals(resourceVersion)) {
- if (action.equals("create") && !resourceVersion.equals("")) {
- errorDetail = "resource-version passed for " + action + " of " + uri;
- aaiExceptionCode = "AAI_6135";
- } else if (resourceVersion.equals("")) {
- errorDetail = "resource-version not passed for " + action + " of " + uri;
- aaiExceptionCode = "AAI_6130";
- } else {
- errorDetail = "resource-version MISMATCH for " + action + " of " + uri;
- aaiExceptionCode = "AAI_6131";
- }
-
- throw new AAIException(aaiExceptionCode, errorDetail);
-
- }
- }
- return true;
- }
-
- /**
- * Convert from camel case.
- *
- * @param name the name
- * @return the string
- */
- private String convertFromCamelCase (String name) {
- String result = "";
- result = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, name);
-
- NamingExceptions exceptions = NamingExceptions.getInstance();
- result = exceptions.getDBName(result);
-
- return result;
- }
-
- private boolean canModify(Introspector obj, String propName, String requestContext) {
- final String readOnly = obj.getPropertyMetadata(propName).get(PropertyMetadata.READ_ONLY);
- if (readOnly != null) {
- final String[] items = readOnly.split(",");
- for (String item : items) {
- if (requestContext.equals(item)) {
- return false;
- }
- }
- }
- return true;
- }
-
- private void executePreSideEffects(Introspector obj, Vertex self) throws AAIException {
-
- SideEffectRunner runner = new SideEffectRunner
- .Builder(this.engine, this).addSideEffect(DataCopy.class).addSideEffect(PrivateEdge.class).build();
-
- runner.execute(obj, self);
- }
-
- private void executePostSideEffects(Introspector obj, Vertex self) throws AAIException {
-
- SideEffectRunner runner = new SideEffectRunner
- .Builder(this.engine, this).addSideEffect(DataLinkWriter.class).build();
-
- runner.execute(obj, self);
- }
-
- private void enrichData(Introspector obj, Vertex self) throws AAIException {
-
- SideEffectRunner runner = new SideEffectRunner
- .Builder(this.engine, this).addSideEffect(DataLinkReader.class).build();
-
- runner.execute(obj, self);
- }
-
- public double getDBTimeMsecs() {
- return (dbTimeMsecs);
- }
-
- /**
- * Db to object With Filters
- * This is for a one-time run with Tenant Isloation to only filter relationships
- * TODO: Chnage the original dbToObject to take filter parent/cousins
- *
- * @param obj the obj
- * @param v the vertex from the graph
- * @param depth the depth
- * @param nodeOnly specify if to exclude relationships or not
- * @param filterCousinNodes
- * @return the introspector
- * @throws AAIException the AAI exception
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws SecurityException the security exception
- * @throws InstantiationException the instantiation exception
- * @throws NoSuchMethodException the no such method exception
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws MalformedURLException the malformed URL exception
- * @throws AAIUnknownObjectException
- * @throws URISyntaxException
- */
- //TODO - See if you can merge the 2 dbToObjectWithFilters
- public Introspector dbToObjectWithFilters(Introspector obj, Vertex v, Set<Vertex> seen, int depth, boolean nodeOnly, List<String> filterCousinNodes, List<String> filterParentNodes) throws AAIException, UnsupportedEncodingException {
- String cleanUp = "false";
- if (depth < 0) {
- return null;
- }
- depth--;
- seen.add(v);
- boolean modified = false;
- for (String property : obj.getProperties(PropertyPredicates.isVisible())) {
- List<Object> getList = null;
- Vertex[] vertices = null;
-
- if (!(obj.isComplexType(property) || obj.isListType(property))) {
- this.copySimpleProperty(property, obj, v);
- modified = true;
- } else {
- if (obj.isComplexType(property)) {
- /* container case */
-
- if (!property.equals("relationship-list") && depth >= 0) {
- Introspector argumentObject = obj.newIntrospectorInstanceOfProperty(property);
- Object result = dbToObjectWithFilters(argumentObject, v, seen, depth+1, nodeOnly, filterCousinNodes, filterParentNodes);
- if (result != null) {
- obj.setValue(property, argumentObject.getUnderlyingObject());
- modified = true;
- }
- } else if (property.equals("relationship-list") && !nodeOnly){
- /* relationships need to be handled correctly */
- Introspector relationshipList = obj.newIntrospectorInstanceOfProperty(property);
- relationshipList = createFilteredRelationshipList(v, relationshipList, cleanUp, filterCousinNodes);
- if (relationshipList != null) {
- modified = true;
- obj.setValue(property, relationshipList.getUnderlyingObject());
- modified = true;
- }
-
- }
- } else if (obj.isListType(property)) {
-
- if (property.equals("any")) {
- continue;
- }
- String genericType = obj.getGenericTypeClass(property).getSimpleName();
- if (obj.isComplexGenericType(property) && depth >= 0) {
- final String childDbName = convertFromCamelCase(genericType);
- String vType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
- EdgeRule rule;
-
- boolean isthisParentRequired = filterParentNodes.parallelStream().anyMatch(childDbName::contains);
-
- EdgeRuleQuery q = new EdgeRuleQuery.Builder(vType, childDbName).edgeType(EdgeType.TREE).build();
-
- try {
- rule = edgeRules.getRule(q);
- } catch (EdgeRuleNotFoundException e) {
- throw new NoEdgeRuleFoundException(e);
- } catch (AmbiguousRuleChoiceException e) {
- throw new MultipleEdgeRuleFoundException(e);
- }
- if (!rule.getContains().equals(AAIDirection.NONE.toString()) && isthisParentRequired) {
- //vertices = this.queryEngine.findRelatedVertices(v, Direction.OUT, rule.getLabel(), childDbName);
- Direction ruleDirection = rule.getDirection();
- Iterator<Vertex> itr = v.vertices(ruleDirection, rule.getLabel());
- List<Vertex> verticesList = (List<Vertex>)IteratorUtils.toList(itr);
- itr = verticesList.stream().filter(item -> {
- return item.property(AAIProperties.NODE_TYPE).orElse("").equals(childDbName);
- }).iterator();
- if (itr.hasNext()) {
- getList = (List<Object>)obj.getValue(property);
- }
- int processed = 0;
- int removed = 0;
- while (itr.hasNext()) {
- Vertex childVertex = itr.next();
- if (!seen.contains(childVertex)) {
- Introspector argumentObject = obj.newIntrospectorInstanceOfNestedProperty(property);
-
- Object result = dbToObjectWithFilters(argumentObject, childVertex, seen, depth, nodeOnly, filterCousinNodes, filterParentNodes);
- if (result != null) {
- getList.add(argumentObject.getUnderlyingObject());
- }
-
- processed++;
- } else {
- removed++;
- LOGGER.warn("Cycle found while serializing vertex id={}", childVertex.id().toString());
- }
- }
- if (processed == 0) {
- //vertices were all seen, reset the list
- getList = null;
- }
- if (processed > 0) {
- modified = true;
- }
- }
- } else if (obj.isSimpleGenericType(property)) {
- List<Object> temp = this.engine.getListProperty(v, property);
- if (temp != null) {
- getList = (List<Object>)obj.getValue(property);
- getList.addAll(temp);
- modified = true;
- }
-
- }
-
- }
-
- }
- }
-
- //no changes were made to this obj, discard the instance
- if (!modified) {
- return null;
- }
- this.enrichData(obj, v);
- return obj;
-
- }
-
- /**
- * Creates the relationship list with the filtered node types.
- *
- * @param v the v
- * @param obj the obj
- * @param cleanUp the clean up
- * @return the object
- * @throws InstantiationException the instantiation exception
- * @throws IllegalAccessException the illegal access exception
- * @throws IllegalArgumentException the illegal argument exception
- * @throws InvocationTargetException the invocation target exception
- * @throws NoSuchMethodException the no such method exception
- * @throws SecurityException the security exception
- * @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIException the AAI exception
- * @throws MalformedURLException the malformed URL exception
- * @throws URISyntaxException
- */
- private Introspector createFilteredRelationshipList(Vertex v, Introspector obj, String cleanUp, List<String> filterNodes) throws UnsupportedEncodingException, AAIException {
- List<Vertex> allCousins = this.engine.getQueryEngine().findCousinVertices(v);
-
- Iterator<Vertex> cousinVertices = allCousins.stream().filter(item -> {
- String node = (String)item.property(AAIProperties.NODE_TYPE).orElse("");
- return filterNodes.parallelStream().anyMatch(node::contains);
- }).iterator();
-
-
- List<Vertex> cousins = (List<Vertex>)IteratorUtils.toList(cousinVertices);
-
- //items.parallelStream().anyMatch(inputStr::contains)
- List<Object> relationshipObjList = obj.getValue("relationship");
- for (Vertex cousin : cousins) {
-
- Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
- Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, null);
- if (result != null) {
- relationshipObjList.add(result);
- }
-
-
- }
-
- if (relationshipObjList.isEmpty()) {
- return null;
- } else {
- return obj;
- }
- }
+ deleteWithTraversal(v);
+ }
+
+ }
+
+ /**
+ * Delete with traversal.
+ *
+ * @param startVertex the start vertex
+ */
+ public void deleteWithTraversal(Vertex startVertex) {
+ StopWatch.conditionalStart();
+ List<Vertex> results = this.engine.getQueryEngine().findDeletable(startVertex);
+
+ for (Vertex v : results) {
+ LOGGER.warn("Removing vertex " + v.id().toString());
+
+ v.remove();
+ }
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ }
+
+ /**
+ * Delete.
+ *
+ * @param v the v
+ * @param resourceVersion the resource version
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws AAIException the AAI exception
+ * @throws InterruptedException the interrupted exception
+ */
+ public void delete(Vertex v, List<Vertex> deletableVertices, String resourceVersion, boolean enableResourceVersion) throws IllegalArgumentException, AAIException {
+
+ boolean result = verifyDeleteSemantics(v, resourceVersion, enableResourceVersion);
+ /*
+ * The reason why I want to call PreventDeleteSemantics second time is to catch the prevent-deletes in a chain
+ * These are far-fewer than seeing a prevnt-delete on the vertex to be deleted
+ * So its better to make these in 2 steps
+ */
+ if (result && !deletableVertices.isEmpty()) {
+ result = verifyPreventDeleteSemantics(deletableVertices);
+ }
+ if (result) {
+
+ try {
+ deleteWithTraversal(v);
+ } catch (IllegalStateException e) {
+ throw new AAIException("AAI_6110", e);
+ }
+
+ }
+
+ }
+
+
+ /**
+ * Delete.
+ *
+ * @param v the v
+ * @param resourceVersion the resource version
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws AAIException the AAI exception
+ * @throws InterruptedException the interrupted exception
+ */
+ public void delete(Vertex v, String resourceVersion, boolean enableResourceVersion) throws IllegalArgumentException, AAIException {
+
+ boolean result = verifyDeleteSemantics(v, resourceVersion, enableResourceVersion);
+
+ if (result) {
+
+ try {
+ deleteWithTraversal(v);
+ } catch (IllegalStateException e) {
+ throw new AAIException("AAI_6110", e);
+ }
+
+ }
+
+ }
+
+ /**
+ * Verify delete semantics.
+ *
+ * @param vertex the vertex
+ * @param resourceVersion the resource version
+ * @return true, if successful
+ * @throws AAIException the AAI exception
+ */
+ private boolean verifyDeleteSemantics(Vertex vertex, String resourceVersion, boolean enableResourceVersion) throws AAIException {
+ boolean result = true;
+ String nodeType = "";
+ String errorDetail = " unknown delete semantic found";
+ String aaiExceptionCode = "";
+ nodeType = vertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ if (enableResourceVersion && !this.verifyResourceVersion("delete", nodeType, vertex.<String>property(AAIProperties.RESOURCE_VERSION).orElse(null), resourceVersion, nodeType)) {
+ }
+ List<Vertex> vertices = new ArrayList<Vertex>();
+ vertices.add(vertex);
+ result = verifyPreventDeleteSemantics(vertices);
+
+ return result;
+ }
+
+ /**
+ * Verify Prevent delete semantics.
+ *
+ * @param vertices the list of vertices
+ * @return true, if successful
+ * @throws AAIException the AAI exception
+ */
+ private boolean verifyPreventDeleteSemantics(List<Vertex> vertices) throws AAIException {
+ boolean result = true;
+ String nodeType = "";
+ String errorDetail = " unknown delete semantic found";
+ String aaiExceptionCode = "";
+
+ StopWatch.conditionalStart();
+ /*
+ * This takes in all the vertices in a cascade-delete-chain and checks if there is any edge with a "prevent-delete" condition
+ * If yes - that should prevent the deletion of the vertex
+ * Dedup makes sure we dont capture the prevent-delete vertices twice
+ * The prevent-delete vertices are stored so that the error message displays what prevents the delete
+ */
+
+ List<Object> preventDeleteVertices = this.engine.asAdmin().getReadOnlyTraversalSource().V(vertices).
+ union(__.inE().has(EdgeProperty.PREVENT_DELETE.toString(), AAIDirection.IN.toString()).outV().values(AAIProperties.NODE_TYPE),
+ __.outE().has(EdgeProperty.PREVENT_DELETE.toString(), AAIDirection.OUT.toString()).inV().values(AAIProperties.NODE_TYPE))
+ .dedup().toList();
+
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ if (!preventDeleteVertices.isEmpty()) {
+ aaiExceptionCode = "AAI_6110";
+ errorDetail = String.format("Object is being reference by additional objects preventing it from being deleted. Please clean up references from the following types %s", preventDeleteVertices);
+ result = false;
+ }
+ if (!result) {
+ throw new AAIException(aaiExceptionCode, errorDetail);
+ }
+ return result;
+ }
+
+ /**
+ * Verify resource version.
+ *
+ * @param action the action
+ * @param nodeType the node type
+ * @param currentResourceVersion the current resource version
+ * @param resourceVersion the resource version
+ * @param uri the uri
+ * @return true, if successful
+ * @throws AAIException the AAI exception
+ */
+ public boolean verifyResourceVersion(String action, String nodeType, String currentResourceVersion, String resourceVersion, String uri) throws AAIException {
+ String enabled = "";
+ String errorDetail = "";
+ String aaiExceptionCode = "";
+ if (currentResourceVersion == null) {
+ currentResourceVersion = "";
+ }
+
+ if (resourceVersion == null) {
+ resourceVersion = "";
+ }
+ try {
+ enabled = AAIConfig.get(AAIConstants.AAI_RESVERSION_ENABLEFLAG);
+ } catch (AAIException e) {
+ ErrorLogHelper.logException(e);
+ }
+ if (enabled.equals("true")) {
+ if (!currentResourceVersion.equals(resourceVersion)) {
+ if (action.equals("create") && !resourceVersion.equals("")) {
+ errorDetail = "resource-version passed for " + action + " of " + uri;
+ aaiExceptionCode = "AAI_6135";
+ } else if (resourceVersion.equals("")) {
+ errorDetail = "resource-version not passed for " + action + " of " + uri;
+ aaiExceptionCode = "AAI_6130";
+ } else {
+ errorDetail = "resource-version MISMATCH for " + action + " of " + uri;
+ aaiExceptionCode = "AAI_6131";
+ }
+
+ throw new AAIException(aaiExceptionCode, errorDetail);
+
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Convert from camel case.
+ *
+ * @param name the name
+ * @return the string
+ */
+ private String convertFromCamelCase (String name) {
+ String result = "";
+ result = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, name);
+
+ NamingExceptions exceptions = NamingExceptions.getInstance();
+ result = exceptions.getDBName(result);
+
+ return result;
+ }
+
+ private boolean canModify(Introspector obj, String propName, String requestContext) {
+ final String readOnly = obj.getPropertyMetadata(propName).get(PropertyMetadata.READ_ONLY);
+ if (readOnly != null) {
+ final String[] items = readOnly.split(",");
+ for (String item : items) {
+ if (requestContext.equals(item)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private void executePreSideEffects(Introspector obj, Vertex self) throws AAIException {
+
+ SideEffectRunner runner = new SideEffectRunner
+ .Builder(this.engine, this).addSideEffect(DataCopy.class).addSideEffect(PrivateEdge.class).build();
+
+ runner.execute(obj, self);
+ }
+
+ private void executePostSideEffects(Introspector obj, Vertex self) throws AAIException {
+
+ SideEffectRunner runner = new SideEffectRunner
+ .Builder(this.engine, this).addSideEffect(DataLinkWriter.class).build();
+
+ runner.execute(obj, self);
+ }
+
+ private void enrichData(Introspector obj, Vertex self) throws AAIException {
+
+ SideEffectRunner runner = new SideEffectRunner
+ .Builder(this.engine, this).addSideEffect(DataLinkReader.class).build();
+
+ runner.execute(obj, self);
+ }
+
+ public double getDBTimeMsecs() {
+ return (dbTimeMsecs);
+ }
+
+ /**
+ * Db to object With Filters
+ * This is for a one-time run with Tenant Isloation to only filter relationships
+ * TODO: Chnage the original dbToObject to take filter parent/cousins
+ *
+ * @param obj the obj
+ * @param v the vertex from the graph
+ * @param depth the depth
+ * @param nodeOnly specify if to exclude relationships or not
+ * @param filterCousinNodes
+ * @return the introspector
+ * @throws AAIException the AAI exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws SecurityException the security exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws MalformedURLException the malformed URL exception
+ * @throws AAIUnknownObjectException
+ * @throws URISyntaxException
+ */
+ //TODO - See if you can merge the 2 dbToObjectWithFilters
+ public Introspector dbToObjectWithFilters(Introspector obj, Vertex v, Set<Vertex> seen, int depth, boolean nodeOnly, List<String> filterCousinNodes, List<String> filterParentNodes) throws AAIException, UnsupportedEncodingException {
+ String cleanUp = "false";
+ if (depth < 0) {
+ return null;
+ }
+ depth--;
+ seen.add(v);
+ boolean modified = false;
+ for (String property : obj.getProperties(PropertyPredicates.isVisible())) {
+ List<Object> getList = null;
+ Vertex[] vertices = null;
+
+ if (!(obj.isComplexType(property) || obj.isListType(property))) {
+ this.copySimpleProperty(property, obj, v);
+ modified = true;
+ } else {
+ if (obj.isComplexType(property)) {
+ /* container case */
+
+ if (!property.equals("relationship-list") && depth >= 0) {
+ Introspector argumentObject = obj.newIntrospectorInstanceOfProperty(property);
+ Object result = dbToObjectWithFilters(argumentObject, v, seen, depth + 1, nodeOnly, filterCousinNodes, filterParentNodes);
+ if (result != null) {
+ obj.setValue(property, argumentObject.getUnderlyingObject());
+ modified = true;
+ }
+ } else if (property.equals("relationship-list") && !nodeOnly) {
+ /* relationships need to be handled correctly */
+ Introspector relationshipList = obj.newIntrospectorInstanceOfProperty(property);
+ relationshipList = createFilteredRelationshipList(v, relationshipList, cleanUp, filterCousinNodes);
+ if (relationshipList != null) {
+ modified = true;
+ obj.setValue(property, relationshipList.getUnderlyingObject());
+ modified = true;
+ }
+
+ }
+ } else if (obj.isListType(property)) {
+
+ if (property.equals("any")) {
+ continue;
+ }
+ String genericType = obj.getGenericTypeClass(property).getSimpleName();
+ if (obj.isComplexGenericType(property) && depth >= 0) {
+ final String childDbName = convertFromCamelCase(genericType);
+ String vType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ EdgeRule rule;
+
+ boolean isthisParentRequired = filterParentNodes.parallelStream().anyMatch(childDbName::contains);
+
+ EdgeRuleQuery q = new EdgeRuleQuery.Builder(vType, childDbName).edgeType(EdgeType.TREE).build();
+
+ try {
+ rule = edgeRules.getRule(q);
+ } catch (EdgeRuleNotFoundException e) {
+ throw new NoEdgeRuleFoundException(e);
+ } catch (AmbiguousRuleChoiceException e) {
+ throw new MultipleEdgeRuleFoundException(e);
+ }
+ if (!rule.getContains().equals(AAIDirection.NONE.toString()) && isthisParentRequired) {
+ //vertices = this.queryEngine.findRelatedVertices(v, Direction.OUT, rule.getLabel(), childDbName);
+ Direction ruleDirection = rule.getDirection();
+ Iterator<Vertex> itr = v.vertices(ruleDirection, rule.getLabel());
+ List<Vertex> verticesList = (List<Vertex>) IteratorUtils.toList(itr);
+ itr = verticesList.stream().filter(item -> {
+ return item.property(AAIProperties.NODE_TYPE).orElse("").equals(childDbName);
+ }).iterator();
+ if (itr.hasNext()) {
+ getList = (List<Object>) obj.getValue(property);
+ }
+ int processed = 0;
+ int removed = 0;
+ while (itr.hasNext()) {
+ Vertex childVertex = itr.next();
+ if (!seen.contains(childVertex)) {
+ Introspector argumentObject = obj.newIntrospectorInstanceOfNestedProperty(property);
+
+ Object result = dbToObjectWithFilters(argumentObject, childVertex, seen, depth, nodeOnly, filterCousinNodes, filterParentNodes);
+ if (result != null) {
+ getList.add(argumentObject.getUnderlyingObject());
+ }
+
+ processed++;
+ } else {
+ removed++;
+ LOGGER.warn("Cycle found while serializing vertex id={}", childVertex.id().toString());
+ }
+ }
+ if (processed == 0) {
+ //vertices were all seen, reset the list
+ getList = null;
+ }
+ if (processed > 0) {
+ modified = true;
+ }
+ }
+ } else if (obj.isSimpleGenericType(property)) {
+ List<Object> temp = this.engine.getListProperty(v, property);
+ if (temp != null) {
+ getList = (List<Object>) obj.getValue(property);
+ getList.addAll(temp);
+ modified = true;
+ }
+
+ }
+
+ }
+
+ }
+ }
+
+ //no changes were made to this obj, discard the instance
+ if (!modified) {
+ return null;
+ }
+ this.enrichData(obj, v);
+ return obj;
+
+ }
+
+ /**
+ * Creates the relationship list with the filtered node types.
+ *
+ * @param v the v
+ * @param obj the obj
+ * @param cleanUp the clean up
+ * @return the object
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ * @throws MalformedURLException the malformed URL exception
+ * @throws URISyntaxException
+ */
+ private Introspector createFilteredRelationshipList(Vertex v, Introspector obj, String cleanUp, List<String> filterNodes) throws UnsupportedEncodingException, AAIException {
+ List<Vertex> allCousins = this.engine.getQueryEngine().findCousinVertices(v);
+
+ Iterator<Vertex> cousinVertices = allCousins.stream().filter(item -> {
+ String node = (String) item.property(AAIProperties.NODE_TYPE).orElse("");
+ return filterNodes.parallelStream().anyMatch(node::contains);
+ }).iterator();
+
+
+ List<Vertex> cousins = (List<Vertex>) IteratorUtils.toList(cousinVertices);
+
+ //items.parallelStream().anyMatch(inputStr::contains)
+ List<Object> relationshipObjList = obj.getValue("relationship");
+ for (Vertex cousin : cousins) {
+
+ Introspector relationshipObj = obj.newIntrospectorInstanceOfNestedProperty("relationship");
+ Object result = processEdgeRelationship(relationshipObj, cousin, cleanUp, null);
+ if (result != null) {
+ relationshipObjList.add(result);
+ }
+
+
+ }
+
+ if (relationshipObjList.isEmpty()) {
+ return null;
+ } else {
+ return obj;
+ }
+ }
}
diff --git a/aai-core/src/main/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngine.java b/aai-core/src/main/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngine.java
index 2158c894..d072db55 100644
--- a/aai-core/src/main/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngine.java
+++ b/aai-core/src/main/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngine.java
@@ -30,6 +30,7 @@ import static org.onap.aai.edges.enums.EdgeProperty.DELETE_OTHER_V;
import java.util.List;
import java.util.Set;
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
@@ -45,12 +46,12 @@ import org.onap.aai.logging.StopWatch;
/*
* This class needs some big explanation despite its compact size.
- * This controls all the queries performed by the CRUD API in A&AI.
+ * This controls all the queries performed by the CRUD API in A&AI.
* findParents, findChildren, and findDeletable require special attention
* These methods use 'repeat'. You cannot use 'emit' with repeat currently
* as it is extremely buggy as of tinkerpop-3.0.1-incubating. The way around
* it (for now) is to sideEffect all the vertices we traverse into an ArrayList.
- *
+ *
*/
public class GraphTraversalQueryEngine extends QueryEngine {
@@ -70,6 +71,7 @@ public class GraphTraversalQueryEngine extends QueryEngine {
public List<Vertex> findParents(Vertex start) {
try {
StopWatch.conditionalStart();
+
@SuppressWarnings("unchecked")
final GraphTraversal<Vertex, Vertex> pipe = this.g.V(start).emit(v -> true).repeat(__.union(__.inE().has(CONTAINS.toString(), OUT.toString()).outV(), __.outE().has(CONTAINS.toString(), IN.toString()).inV()));
return pipe.toList();
@@ -79,19 +81,36 @@ public class GraphTraversalQueryEngine extends QueryEngine {
}
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Vertex> findParents(String[] uris) {
+ try {
+ StopWatch.conditionalStart();
+ final GraphTraversal<Vertex, Vertex> pipe = this.g.V()
+ .has(AAIProperties.AAI_URI, P.within(uris))
+ .order().by(AAIProperties.AAI_URI, Order.decr);
+ return pipe.toList();
+ }
+ finally {
+ dbTimeMsecs += StopWatch.stopIfStarted();
+ }
+ }
+
/**
* {@inheritDoc}
*/
@Override
public List<Vertex> findAllChildren(Vertex start) {
-
+
@SuppressWarnings("unchecked")
GraphTraversal<Vertex, Vertex> pipe = this.g
.V(start).emit(v -> true).repeat(__.union(__.outE().has(CONTAINS.toString(), OUT.toString()).inV(), __.inE().has(CONTAINS.toString(), IN.toString()).outV()));
-
+
return pipe.toList();
-
+
}
/**
@@ -104,10 +123,10 @@ public class GraphTraversalQueryEngine extends QueryEngine {
__.outE().has(CONTAINS.toString(), OUT.toString()).inV(),
__.inE().has(CONTAINS.toString(), IN.toString()).outV()
).has(AAIProperties.NODE_TYPE, type).dedup();
-
+
return pipe.toList();
}
-
+
/**
* {@inheritDoc}
*/
@@ -118,7 +137,7 @@ public class GraphTraversalQueryEngine extends QueryEngine {
__.outE().has(CONTAINS.toString(), OUT.toString()),
__.inE().has(CONTAINS.toString(), IN.toString())
).otherV().dedup();
-
+
return pipe.toList();
}
@@ -135,7 +154,7 @@ public class GraphTraversalQueryEngine extends QueryEngine {
__.inE().has(DELETE_OTHER_V.toString(), IN.toString()).outV()
)
).dedup();
-
+
return pipe.toList();
}
@@ -158,11 +177,11 @@ public class GraphTraversalQueryEngine extends QueryEngine {
default:
break;
}
-
+
pipe.has(AAIProperties.NODE_TYPE, nodeType).dedup();
return pipe.toList();
}
-
+
@Override
public Tree<Element> findSubGraph(Vertex start, int iterations, boolean nodeOnly) {
final GraphTraversal<Vertex, ?> t = this.g.V(start).emit(v -> true).times(iterations).repeat(
@@ -204,13 +223,13 @@ public class GraphTraversalQueryEngine extends QueryEngine {
__.has("private", true)
)
.dedup();
-
+
return pipeline.toList();
}
@Override
- public List<Vertex> findCousinVertices(Vertex start) {
+ public List<Vertex> findCousinVertices(Vertex start, String... labels) {
// Start at the given vertex
// Do a union to copy the start vertex to be run against all
// so for the start vertex it gets all of in edges that contains other v set to none
@@ -223,8 +242,8 @@ public class GraphTraversalQueryEngine extends QueryEngine {
GraphTraversal<Vertex, Vertex> pipeline = this.g
.V(start)
.union(
- __.inE().has(CONTAINS.toString(), NONE.toString()),
- __.outE().has(CONTAINS.toString(), NONE.toString())
+ __.inE(labels).has(CONTAINS.toString(), NONE.toString()),
+ __.outE(labels).has(CONTAINS.toString(), NONE.toString())
)
.not(
__.has(PRIVATE.toString(), true)
@@ -234,7 +253,7 @@ public class GraphTraversalQueryEngine extends QueryEngine {
return pipeline.toList();
}
-
+
public double getDBTimeMsecs() {
return (dbTimeMsecs);
}
diff --git a/aai-core/src/main/java/org/onap/aai/serialization/engines/query/QueryEngine.java b/aai-core/src/main/java/org/onap/aai/serialization/engines/query/QueryEngine.java
index c2929468..110f8628 100644
--- a/aai-core/src/main/java/org/onap/aai/serialization/engines/query/QueryEngine.java
+++ b/aai-core/src/main/java/org/onap/aai/serialization/engines/query/QueryEngine.java
@@ -42,16 +42,33 @@ public abstract class QueryEngine {
public QueryEngine (GraphTraversalSource g) {
this.g = g;
}
-
+
/**
* Finds all the parents/grandparents/etc of the given start node.
*
* @param start - the start vertex whose parent chain you want
* @return the list of start and start's parent, grandparent, etc, in
- * order (ie {start, parent, grandparent, etc}
+ * order (ie {start, parent, grandparent, etc}
*/
public abstract List<Vertex> findParents(Vertex start);
-
+
+ /**
+ * Finds all the parents/grandparents/etc of the given start node.
+ *
+ * This method should be used in place of the #findParents(Vertex)
+ * as since the aai-uri is added the lookup for finding the parents
+ * using the given list of aai-uri will be much faster than using
+ * a traversal to follow a start vertex and keep repeating since
+ * as the number of different type of edges keeps growing that call
+ * will be more expensive than using the aai-uri's as they are fast lookup
+ *
+ * @param uris - list of the uris representing the aai-uris of
+ * parent, grandparent, etc
+ * @return the list of start and start's parent, grandparent, etc, in
+ * order (ie {start, parent, grandparent, etc}
+ */
+ public abstract List<Vertex> findParents(String [] uris);
+
/**
* Finds all children, grandchildren, etc of start
*
@@ -59,7 +76,7 @@ public abstract class QueryEngine {
* @return the list of child/grandchild/etc vertices
*/
public abstract List<Vertex> findAllChildren(Vertex start);
-
+
/**
* Finds all immediate children of start (no grandchildren or so forth) of the given type
* @param start - the start vertex
@@ -67,14 +84,14 @@ public abstract class QueryEngine {
* @return the list of immediate child vertices of given type
*/
public abstract List<Vertex> findChildrenOfType(Vertex start, String type);
-
+
/**
* Finds all immediate children of start (no grandchildren or so forth)
* @param start - the start vertex
* @return the list of immediate child vertices
*/
public abstract List<Vertex> findChildren(Vertex start);
-
+
/**
* Find all vertices that should be deleted in a cascade from a delete of start
*
@@ -82,34 +99,34 @@ public abstract class QueryEngine {
* @return the list of vertices to be deleted when start is deleted
*/
public abstract List<Vertex> findDeletable(Vertex start);
-
+
/**
* Finds the subgraph under start, including cousins as well as start's children/grandchildren/etc.
* More specifically, this includes start, all its descendants, start's cousins, and start's
* descendants' cousins (but not any of the cousins' cousins or descendants), and the edges
* connecting them.
- *
+ *
* @param start - the start vertex
- * @return - Tree containing nodes and edges of the subgraph
+ * @return - Tree containing nodes and edges of the subgraph
*/
public Tree<Element> findSubGraph(Vertex start) {
return findSubGraph(start, AAIProperties.MAXIMUM_DEPTH, false);
}
-
+
/**
* Finds the subgraph under start, including cousins as well as start's children/grandchildren/etc.
* More specifically, this includes start, all its descendants, start's cousins, and start's
* descendants' cousins (but not any of the cousins' cousins or descendants), and the edges
* connecting them.
- *
+ *
* @param start - the start vertex
- * @param iterations - depth of the subgraph, this limits how many generations of
+ * @param iterations - depth of the subgraph, this limits how many generations of
* descendants are included
* @param nodeOnly - if true the subgraph will NOT include the cousins
- * @return Tree containing nodes and edges of the subgraph
+ * @return Tree containing nodes and edges of the subgraph
*/
public abstract Tree<Element> findSubGraph(Vertex start, int iterations, boolean nodeOnly);
-
+
/**
* Find vertices of type nodeType related to start by edges of the given
* direction and label.
@@ -125,23 +142,23 @@ public abstract class QueryEngine {
/**
* Finds cousin edges connecting start to other vertices only of types defined in an old version.
* The idea is that if a user is using an old version, they won't understand any new node types in
- * subsequent versions. Thus, revealing edges to new types will cause problems. This methods
+ * subsequent versions. Thus, revealing edges to new types will cause problems. This methods
* filters any such edges out.
- *
+ *
* @param start - the start vertex
* @param loader - loader for retrieving the list of allowed node types for the desired version
* (version is set when the loader was instantiated)
* @return list of cousin edges between start and any node types understood by the version specified in loader
*/
public abstract List<Edge> findEdgesForVersion(Vertex start, Loader loader);
-
+
/**
- * Finds all cousins of start.
- *
+ * Finds all cousins of start.
+ *
* @param start - the start vertex
* @return list of start's cousin vertices
*/
- public abstract List<Vertex> findCousinVertices(Vertex start);
+ public abstract List<Vertex> findCousinVertices(Vertex start, String... labels);
public abstract double getDBTimeMsecs();
diff --git a/aai-core/src/test/java/org/onap/aai/HttpTestUtil.java b/aai-core/src/test/java/org/onap/aai/HttpTestUtil.java
index 82a3efdf..92cb59c5 100644
--- a/aai-core/src/test/java/org/onap/aai/HttpTestUtil.java
+++ b/aai-core/src/test/java/org/onap/aai/HttpTestUtil.java
@@ -52,11 +52,11 @@ import static org.mockito.Mockito.when;
public class HttpTestUtil extends RESTAPI {
-
- protected HttpEntry traversalHttpEntry;
-
- protected HttpEntry traversalUriHttpEntry;
-
+
+ protected HttpEntry traversalHttpEntry;
+
+ protected HttpEntry traversalUriHttpEntry;
+
private static final EELFLogger logger = EELFManager.getInstance().getLogger(HttpTestUtil.class);
protected static final MediaType APPLICATION_JSON = MediaType.valueOf("application/json");
@@ -77,7 +77,7 @@ public class HttpTestUtil extends RESTAPI {
this.queryStyle = qs;
traversalHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class);
traversalUriHttpEntry = SpringContextAware.getBean("traversalUriHttpEntry", HttpEntry.class);
-
+
}
public void init(){
@@ -121,7 +121,10 @@ public class HttpTestUtil extends RESTAPI {
try {
- uri = uri.replaceAll("/aai/", "");
+ if(uri.startsWith("/aai/")){
+ uri = uri.substring(5);
+ }
+
logger.info("Starting the put request for the uri {} with payload {}", uri, payload);
String [] arr = uri.split("/");
@@ -142,7 +145,7 @@ public class HttpTestUtil extends RESTAPI {
Mockito.when(uriInfo.getPath()).thenReturn(uri);
DBConnectionType type = DBConnectionType.REALTIME;
-
+
traversalHttpEntry.setHttpEntryProperties(version, type);
Loader loader = traversalHttpEntry.getLoader();
dbEngine = traversalHttpEntry.getDbEngine();
@@ -206,7 +209,7 @@ public class HttpTestUtil extends RESTAPI {
return response;
}
- public Response doGet(String uri) throws UnsupportedEncodingException, AAIException {
+ public Response doGet(String uri, String depth){
this.init();
Response response = null;
@@ -215,8 +218,11 @@ public class HttpTestUtil extends RESTAPI {
try {
- uri = uri.replaceAll("/aai/", "");
- logger.info("Starting the GET request for the uri {} with depth {}", uri, "all");
+ if(uri.startsWith("/aai/")){
+ uri = uri.substring(5);
+ }
+
+ logger.info("Starting the GET request for the uri {} with depth {}", uri, depth);
String [] arr = uri.split("/");
@@ -240,21 +246,29 @@ public class HttpTestUtil extends RESTAPI {
dbEngine = traversalHttpEntry.getDbEngine();
URI uriObject = UriBuilder.fromPath(uri).build();
- URIToObject uriToObject = new URIToObject(loader, uriObject);
- String objType = uriToObject.getEntityName();
- queryParameters.add("depth", "all");
+ if(depth != null){
+ queryParameters.add("depth", depth);
+ }
+
QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject, queryParameters);
Mockito.when(uriInfo.getPath()).thenReturn(uri);
+ URIToObject uriToObject = new URIToObject(loader, uriObject);
+ String objType = "";
+ if (!uriQuery.getContainerType().equals("")) {
+ objType = uriQuery.getContainerType();
+ } else {
+ objType = uriQuery.getResultType();
+ }
logger.info("Unmarshalling the payload to this {}", objType);
Introspector obj = loader.introspectorFromName(objType);
DBRequest dbRequest =
- new DBRequest.Builder(HttpMethod.GET, uriObject, uriQuery, obj, httpHeaders, uriInfo, "JUNIT-TRANSACTION")
- .build();
+ new DBRequest.Builder(HttpMethod.GET, uriObject, uriQuery, obj, httpHeaders, uriInfo, "JUNIT-TRANSACTION")
+ .build();
List<DBRequest> dbRequestList = new ArrayList<>();
dbRequestList.add(dbRequest);
@@ -288,6 +302,10 @@ public class HttpTestUtil extends RESTAPI {
return response;
}
+ public Response doGet(String uri) throws UnsupportedEncodingException, AAIException {
+ return this.doGet(uri, "all");
+ }
+
public Response doDelete(String uri, String resourceVersion) throws UnsupportedEncodingException, AAIException {
this.init();
@@ -321,7 +339,7 @@ public class HttpTestUtil extends RESTAPI {
Mockito.when(uriInfo.getPath()).thenReturn(uri);
DBConnectionType type = DBConnectionType.REALTIME;
traversalHttpEntry.setHttpEntryProperties(version, type);
-
+
traversalHttpEntry.setHttpEntryProperties(version, type);
Loader loader = traversalHttpEntry.getLoader();
dbEngine = traversalHttpEntry.getDbEngine();
diff --git a/aai-core/src/test/java/org/onap/aai/parsers/uri/URIToObjectTest.java b/aai-core/src/test/java/org/onap/aai/parsers/uri/URIToObjectTest.java
index c7c1f4ca..fc2c64a1 100644
--- a/aai-core/src/test/java/org/onap/aai/parsers/uri/URIToObjectTest.java
+++ b/aai-core/src/test/java/org/onap/aai/parsers/uri/URIToObjectTest.java
@@ -19,6 +19,7 @@
*/
package org.onap.aai.parsers.uri;
+import org.onap.aai.schema.enums.ObjectMetadata;
import org.onap.aai.setup.SchemaVersion;
import org.junit.Ignore;
@@ -65,7 +66,7 @@ public class URIToObjectTest extends AAISetup {
currentVersion = schemaVersions.getDefaultVersion();
loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getRelatedLinkVersion());
}
-
+
@Test
public void uri() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
URI uri = UriBuilder.fromPath("/aai/" + loader.getVersion() + "/cloud-infrastructure/cloud-regions/cloud-region/mycloudowner/mycloudregionid/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3").build();
@@ -74,11 +75,11 @@ public class URIToObjectTest extends AAISetup {
String expected = "{\"cloud-owner\":\"mycloudowner\",\"cloud-region-id\":\"mycloudregionid\",\"tenants\":{\"tenant\":[{\"tenant-id\":\"key1\",\"vservers\":{\"vserver\":[{\"vserver-id\":\"key2\",\"l-interfaces\":{\"l-interface\":[{\"interface-name\":\"key3\"}]}}]}}]}}";
String topEntity = "cloud-region";
String entity = "l-interface";
-
+
testSet(result.marshal(false), parse, expected, topEntity, entity, version);
}
-
+
/**
* Uri no version.
*
@@ -86,7 +87,7 @@ public class URIToObjectTest extends AAISetup {
* @throws AAIException the AAI exception
* @throws IllegalArgumentException the illegal argument exception
* @throws UnsupportedEncodingException the unsupported encoding exception
- * @throws AAIUnknownObjectException
+ * @throws AAIUnknownObjectException
*/
@Test
public void uriNoVersion() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException, AAIUnknownObjectException {
@@ -106,12 +107,12 @@ public class URIToObjectTest extends AAISetup {
String expected = "{\"cloud-owner\":\"mycloudowner\",\"cloud-region-id\":\"mycloudregionid\",\"tenants\":{\"tenant\":[{\"tenant-id\":\"key1\",\"tenant-name\":\"name1\",\"vservers\":{\"vserver\":[{\"vserver-id\":\"key2\",\"vserver-name\":\"name2\",\"l-interfaces\":{\"l-interface\":[{\"interface-name\":\"key3\"}]}}]}}]}}";
String topEntity = "cloud-region";
String entity = "l-interface";
-
+
testSet(result.marshal(false), parse, expected, topEntity, entity, version);
-
+
}
-
+
/**
* Bad URI.
@@ -124,13 +125,13 @@ public class URIToObjectTest extends AAISetup {
@Test
public void badURI() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
URI uri = UriBuilder.fromPath("/aai/" + loader.getVersion() + "/cloud-infrastructure/cloud-regions/cloud-region/mycloudowner/mycloudregionid/tenants/tenant/key1/vservers/vserver/key2/l-interadsfaces/l-interface/key3").build();
-
+
thrown.expect(AAIException.class);
thrown.expect(hasProperty("code", is("AAI_3000")));
-
+
new URIToObject(loader, uri);
}
-
+
/**
* Starts with valid namespace.
*
@@ -147,10 +148,10 @@ public class URIToObjectTest extends AAISetup {
String expected = "{\"cloud-owner\":\"mycloudowner\",\"cloud-region-id\":\"mycloudregionid\",\"tenants\":{\"tenant\":[{\"tenant-id\":\"key1\",\"vservers\":{\"vserver\":[{\"vserver-id\":\"key2\",\"l-interfaces\":{\"l-interface\":[{\"interface-name\":\"key3\"}]}}]}}]}}";
String topEntity = "cloud-region";
String entity = "l-interface";
-
+
testSet(result.marshal(false), parse, expected, topEntity, entity, version);
}
-
+
/**
* Single top level.
*
@@ -165,14 +166,14 @@ public class URIToObjectTest extends AAISetup {
URIToObject parse = new URIToObject(loader, uri);
Introspector result = parse.getTopEntity();
String expected = "{\"vnf-id\":\"key1\"}";
-
+
String topEntity = "generic-vnf";
String entity = "generic-vnf";
-
+
testSet(result.marshal(false), parse, expected, topEntity, entity, version);
}
-
+
/**
* Naming exceptions.
*
@@ -190,11 +191,11 @@ public class URIToObjectTest extends AAISetup {
String expected = "{\"vnf-id\":\"key1\",\"port-groups\":{\"port-group\":[{\"interface-id\":\"key2\",\"cvlan-tags\":{\"cvlan-tag-entry\":[{\"cvlan-tag\":655}]}}]}}";
String topEntity = "vce";
String entity = "cvlan-tag";
-
+
testSet(result.marshal(false), parse, expected, topEntity, entity, version);
}
-
+
/**
* No list object.
*
@@ -212,23 +213,23 @@ public class URIToObjectTest extends AAISetup {
String entity = "l3-interface-ipv4-address-list";
String expected = "{\"equipment-name\":\"0e6189fd-9257-49b9-a3be-d7ba980ccfc9\",\"lag-interfaces\":{\"lag-interface\":[{\"interface-name\":\"8ae5aa76-d597-4382-b219-04f266fe5e37\",\"l-interfaces\":{\"l-interface\":[{\"interface-name\":\"9e141d03-467b-437f-b4eb-b3133ec1e205\",\"l3-interface-ipv4-address-list\":[{\"l3-interface-ipv4-address\":\"8f19f0ea-a81f-488e-8d5c-9b7b53696c11\"}]}]}}]}}";
testSet(result.marshal(false), parse, expected, topEntity, entity, version);
-
+
}
-
+
@Test
public void relativePath() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
URI uri = UriBuilder.fromPath("./l-interfaces/l-interface/key1").build();
URIToObject parse = new URIToObject(loader, uri);
Introspector result = parse.getEntity();
String expected = "{\"interface-name\":\"key1\"}";
-
+
String topEntity = "l-interface";
String entity = "l-interface";
-
+
testSet(result.marshal(false), parse, expected, topEntity, entity, version);
}
-
+
/**
* Test set.
*
@@ -241,15 +242,15 @@ public class URIToObjectTest extends AAISetup {
*/
public void testSet(String json, URIToObject parse, String expected, String topEntity, String entity, SchemaVersion version) {
assertEquals("blah", expected, json);
-
+
assertEquals("top entity", topEntity, parse.getTopEntityName());
assertEquals("entity", entity, parse.getEntityName());
assertEquals("entity object", entity, parse.getEntity().getDbName());
-
+
assertEquals("parent list object", 1, parse.getParentList().size());
-
+
assertEquals("object version", version, parse.getObjectVersion());
}
}
diff --git a/aai-core/src/test/java/org/onap/aai/rest/EdgeNotValidAnymoreTest.java b/aai-core/src/test/java/org/onap/aai/rest/EdgeNotValidAnymoreTest.java
new file mode 100644
index 00000000..1a69fc58
--- /dev/null
+++ b/aai-core/src/test/java/org/onap/aai/rest/EdgeNotValidAnymoreTest.java
@@ -0,0 +1,120 @@
+/**
+ * ============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.rest;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.janusgraph.core.JanusGraph;
+import org.janusgraph.core.JanusGraphTransaction;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.aai.AAISetup;
+import org.onap.aai.HttpTestUtil;
+import org.onap.aai.PayloadUtil;
+import org.onap.aai.db.props.AAIProperties;
+import org.onap.aai.dbmap.AAIGraph;
+import org.onap.aai.edges.enums.EdgeField;
+import org.onap.aai.edges.enums.EdgeProperty;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.serialization.engines.QueryStyle;
+
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.util.UUID;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+
+public class EdgeNotValidAnymoreTest extends AAISetup {
+
+ private HttpTestUtil testUtil;
+
+ @Before
+ public void setupData() throws IOException, AAIException {
+
+ String cloudRegionEndpoint = "/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/junit-cloud-owner-with-vlan/junit-cloud-region-with-vlan";
+
+ String cloudRegionBody = PayloadUtil.getResourcePayload("cloud-region-with-vlan.json");
+ testUtil = new HttpTestUtil(QueryStyle.TRAVERSAL_URI);
+ testUtil.doPut(cloudRegionEndpoint, cloudRegionBody);
+
+ JanusGraphTransaction transaction = AAIGraph.getInstance().getGraph().newTransaction();
+ GraphTraversalSource g = transaction.traversal();
+
+ Vertex configurationVertex = g.addV()
+ .property( AAIProperties.NODE_TYPE, "configuration")
+ .property( "configuration-id", "ci1")
+ .property( "configuration-type", "ci1")
+ .property( AAIProperties.AAI_URI, "/network/configurations/configuration/ci1")
+ .property(AAIProperties.SOURCE_OF_TRUTH, "JUNIT")
+ .next();
+
+ Vertex vlanVertex = g.V()
+ .has("vlan-interface", "test-vlan-interface-1")
+ .has(AAIProperties.NODE_TYPE, "vlan")
+ .next();
+
+ Edge edge = configurationVertex.addEdge("org.onap.relationships.inventory.PartOf", vlanVertex);
+ addEdge(edge);
+
+ transaction.commit();
+ }
+
+ public void addEdge(Edge edge) {
+ edge.property(EdgeProperty.CONTAINS.toString(), "NONE");
+ edge.property(EdgeProperty.DELETE_OTHER_V.toString(), "NONE");
+ edge.property(EdgeProperty.PREVENT_DELETE.toString(), "NONE");
+ edge.property(EdgeField.PRIVATE.toString(), false);
+ edge.property(AAIProperties.AAI_UUID, UUID.randomUUID().toString());
+ }
+
+ @Test
+ public void testWhenEdgeRuleIsNoLongerValidEnsureItRetrievesVertexesWithoutOldEdges() {
+
+ String endpoint = "/aai/v14/network/configurations";
+
+ Response response = testUtil.doGet(endpoint, null);
+ assertThat(response.getStatus(), is(200));
+
+ String body = response.getEntity().toString();
+
+ assertThat(body, containsString("configuration-id"));
+ assertThat(body, not(containsString("vlan")));
+ }
+
+ @After
+ public void teardown(){
+
+ JanusGraph janusGraph = AAIGraph.getInstance().getGraph();
+ JanusGraphTransaction transaction = janusGraph.newTransaction();
+ GraphTraversalSource g = transaction.traversal();
+
+ g.V()
+ .has(AAIProperties.SOURCE_OF_TRUTH, "JUNIT")
+ .toList()
+ .forEach((edge) -> edge.remove());
+
+ transaction.commit();
+ }
+}
diff --git a/aai-core/src/test/java/org/onap/aai/rest/EntitlementTest.java b/aai-core/src/test/java/org/onap/aai/rest/EntitlementTest.java
new file mode 100644
index 00000000..3559b9d6
--- /dev/null
+++ b/aai-core/src/test/java/org/onap/aai/rest/EntitlementTest.java
@@ -0,0 +1,96 @@
+/**
+ * ============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.rest;
+
+import com.jayway.jsonpath.JsonPath;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.onap.aai.AAISetup;
+import org.onap.aai.HttpTestUtil;
+import org.onap.aai.PayloadUtil;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.serialization.engines.QueryStyle;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.springframework.test.annotation.DirtiesContext;
+
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(value = Parameterized.class)
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
+public class EntitlementTest extends AAISetup {
+
+ private HttpTestUtil httpTestUtil;
+
+ @Parameterized.Parameter(value = 0)
+ public QueryStyle queryStyle;
+
+ private String vnfPayload;
+
+ private String vnfUri;
+
+ @Parameterized.Parameters(name = "QueryStyle.{0}")
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {QueryStyle.TRAVERSAL_URI}
+ });
+ }
+
+ @Before
+ public void setUp() throws IOException {
+ httpTestUtil = new HttpTestUtil(queryStyle);
+ vnfPayload = PayloadUtil.getResourcePayload("vnf.json");
+ vnfUri = "/aai/v14/network/generic-vnfs/generic-vnf/vnf1";
+ }
+
+ @Test
+ public void testPutGenericVnfAndThenInsertEntitlement() throws IOException, AAIException {
+ String entitlementPayload = PayloadUtil.getResourcePayload("entitlement.json");
+ String entitlementUri = "/aai/v14/network/generic-vnfs/generic-vnf/vnf1/entitlements/entitlement/g1/r1";
+ Response response = httpTestUtil.doPut(vnfUri, vnfPayload);
+ assertEquals("Expected the Generic Vnf to be created", 201, response.getStatus());
+
+ response = httpTestUtil.doGet(vnfUri);
+ assertEquals("Expected the Generic Vnf to be found", 200, response.getStatus());
+ String jsonResponse = response.getEntity().toString();
+ JSONAssert.assertEquals(vnfPayload, jsonResponse, false);
+
+ response = httpTestUtil.doPut(entitlementUri, entitlementPayload);
+ assertEquals("Expected the Entitlement to be created", 201, response.getStatus());
+ }
+
+ @After
+ public void tearDown() throws UnsupportedEncodingException, AAIException {
+ Response response = httpTestUtil.doGet(vnfUri);
+ assertEquals("Expected the Generic Vnf to be found", 200, response.getStatus());
+ String jsonResponse = response.getEntity().toString();
+ String resourceVersion = JsonPath.read(jsonResponse, "$.resource-version");
+ response = httpTestUtil.doDelete(vnfUri, resourceVersion);
+ assertEquals("Expected the cloud region to be deleted", 204, response.getStatus());
+ }
+}
diff --git a/aai-core/src/test/java/org/onap/aai/rest/ModelElementTest.java b/aai-core/src/test/java/org/onap/aai/rest/ModelElementTest.java
new file mode 100644
index 00000000..d808c993
--- /dev/null
+++ b/aai-core/src/test/java/org/onap/aai/rest/ModelElementTest.java
@@ -0,0 +1,98 @@
+/**
+ * ============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.rest;
+
+import com.jayway.jsonpath.JsonPath;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.onap.aai.AAISetup;
+import org.onap.aai.HttpTestUtil;
+import org.onap.aai.PayloadUtil;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.serialization.engines.QueryStyle;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.springframework.test.annotation.DirtiesContext;
+
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(value = Parameterized.class)
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
+public class ModelElementTest extends AAISetup {
+
+ private HttpTestUtil httpTestUtil;
+
+ @Parameterized.Parameter(value = 0)
+ public QueryStyle queryStyle;
+
+ private String modelPayload;
+ private String modelElementPayload;
+
+ private String modelUri;
+ private String modelElementUri;
+
+ @Parameterized.Parameters(name = "QueryStyle.{0}")
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {QueryStyle.TRAVERSAL_URI}
+ });
+ }
+
+ @Before
+ public void setUp() throws IOException {
+ httpTestUtil = new HttpTestUtil(queryStyle);
+ modelPayload = PayloadUtil.getResourcePayload("model.json");
+ modelElementPayload = PayloadUtil.getResourcePayload("model-element.json");
+ modelUri = "/aai/v14/service-design-and-creation/models/model/24c04fc5-f3f8-43ec-8792-c6f940638676-test1";
+ modelElementUri = "/aai/v14/service-design-and-creation/models/model/24c04fc5-f3f8-43ec-8792-c6f940638676-test1/model-vers/model-ver/0c4c59f0-9864-43ca-b0c2-ca38746b72a5-test1/model-elements/model-element/0dc2b8b6-af8d-4213-970b-7861a603fc86-test1/model-constraints/model-constraint/782ba24a-28ab-4fd0-8e69-da10cc5373f3-test1/constrained-element-sets/constrained-element-set/a33e65c3-1198-4d4c-9799-2b521e4c4212-test1/element-choice-sets/element-choice-set/7df27a94-06c8-46ef-9fc2-5900d8cffbb0-test1/model-elements/model-element/acf8b6cf-e051-4c1b-bcad-b24792f826cf-test1";
+ }
+
+ @Test
+ public void testPutModelAndThenModelElementAndItShouldSucceed() throws IOException, AAIException {
+ Response response = httpTestUtil.doPut(modelUri, modelPayload);
+ assertEquals("Expected the cloud region to be created", 201, response.getStatus());
+
+ response = httpTestUtil.doGet(modelUri);
+ assertEquals("Expected the cloud region to be found", 200, response.getStatus());
+ String jsonResponse = response.getEntity().toString();
+ JSONAssert.assertEquals(modelPayload, jsonResponse, false);
+
+ response = httpTestUtil.doPut(modelElementUri, modelElementPayload);
+ assertEquals("Expected the cloud region to be created", 201, response.getStatus());
+ }
+
+ @After
+ public void tearDown() throws UnsupportedEncodingException, AAIException {
+ Response response = httpTestUtil.doGet(modelUri);
+ assertEquals("Expected the cloud region to be found", 200, response.getStatus());
+ String jsonResponse = response.getEntity().toString();
+ String resourceVersion = JsonPath.read(jsonResponse, "$.resource-version");
+ response = httpTestUtil.doDelete(modelUri, resourceVersion);
+ assertEquals("Expected the cloud region to be deleted", 204, response.getStatus());
+ }
+}
diff --git a/aai-core/src/test/java/org/onap/aai/rest/PserverDuplicateTest.java b/aai-core/src/test/java/org/onap/aai/rest/PserverDuplicateTest.java
new file mode 100644
index 00000000..71e53be8
--- /dev/null
+++ b/aai-core/src/test/java/org/onap/aai/rest/PserverDuplicateTest.java
@@ -0,0 +1,135 @@
+/**
+ * ============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.rest;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.janusgraph.core.JanusGraph;
+import org.janusgraph.core.JanusGraphTransaction;
+import org.junit.Test;
+import org.onap.aai.AAISetup;
+import org.onap.aai.HttpTestUtil;
+import org.onap.aai.db.props.AAIProperties;
+import org.onap.aai.dbmap.AAIGraph;
+import org.onap.aai.serialization.engines.QueryStyle;
+
+import javax.ws.rs.core.Response;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class PserverDuplicateTest extends AAISetup {
+
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(PserverDuplicateTest.class);
+
+ private HttpTestUtil testUtil;
+
+ private String hostname;
+
+ public boolean createDuplicate() throws InterruptedException {
+
+ hostname = getHostname();
+ final String aaiUri = "/cloud-infrastructure/pservers/pserver/" + hostname;
+ final int threads = getNumberOfThreads();
+
+ ExecutorService service = Executors.newFixedThreadPool(threads);
+
+ JanusGraph janusGraph = AAIGraph.getInstance().getGraph();
+ // Due to the lazy instantiation of the graph, it needs to create a new transaction to create schema
+ janusGraph.newTransaction().rollback();
+
+ service.invokeAll(
+ IntStream.range(0, threads)
+ .mapToObj((i) -> (Callable<Void>) () -> {
+ JanusGraphTransaction transaction = janusGraph.newTransaction();
+ GraphTraversalSource g = transaction.traversal();
+ g.addV()
+ .property(AAIProperties.AAI_URI, aaiUri)
+ .property(AAIProperties.NODE_TYPE, "pserver")
+ .property("hostname", hostname)
+ .next();
+ transaction.commit();
+ return null;
+ }).collect(Collectors.toList())
+ , 7, TimeUnit.SECONDS
+ );
+
+ JanusGraphTransaction readOnlyTransaction = AAIGraph.getInstance().getGraph().buildTransaction().readOnly().start();
+ GraphTraversalSource g = readOnlyTransaction.traversal();
+
+ List<Vertex> pserverList = g.V().has(AAIProperties.AAI_URI, aaiUri).toList();
+ LOGGER.debug("Number of pservers with uri {} is {}", aaiUri, pserverList.size());
+
+ testUtil = new HttpTestUtil(QueryStyle.TRAVERSAL_URI);
+
+ if(pserverList.size() == 1){
+ return false;
+ }
+ return true;
+ }
+
+
+ @Test
+ public void testWhenDuplicatesExistInGraphThatGetAllSuceeds() throws InterruptedException {
+
+ int totalRetries = getNumOfRetries();
+ for(int retry = 0; retry < totalRetries; retry++){
+ if(!this.createDuplicate()){
+ if(retry == (totalRetries-1)){
+ fail("Unable to produce duplicates in the graph, " +
+ "please increase retry or ignore test if it becomes impossible to create duplicate this test");
+ }
+ } else {
+ // Successfully created a duplicate in the janus graph
+ break;
+ }
+ }
+
+ String endpoint = "/aai/v14/cloud-infrastructure/pservers";
+
+ Response response = testUtil.doGet(endpoint, null);
+ LOGGER.info("GET ALL Pservers with duplicates status code {} and body {}", response.getStatus(), response.getEntity());
+ assertThat(response.getStatus(), is(200));
+ }
+
+ public String getHostname(){
+ return UUID.randomUUID().toString();
+ }
+
+ public int getNumOfRetries(){
+ return 10;
+ }
+
+ public int getNumberOfThreads(){
+ return 10;
+ }
+}
+
diff --git a/aai-core/src/test/java/org/onap/aai/rest/VipAddressListTest.java b/aai-core/src/test/java/org/onap/aai/rest/VipAddressListTest.java
new file mode 100644
index 00000000..0351c2c3
--- /dev/null
+++ b/aai-core/src/test/java/org/onap/aai/rest/VipAddressListTest.java
@@ -0,0 +1,99 @@
+/**
+ * ============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.rest;
+
+import com.jayway.jsonpath.JsonPath;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.onap.aai.AAISetup;
+import org.onap.aai.HttpTestUtil;
+import org.onap.aai.PayloadUtil;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.serialization.engines.QueryStyle;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(value = Parameterized.class)
+public class VipAddressListTest extends AAISetup {
+
+ private HttpTestUtil httpTestUtil;
+
+ @Parameterized.Parameter(value = 0)
+ public QueryStyle queryStyle;
+
+ @Parameterized.Parameters(name = "QueryStyle.{0}")
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {QueryStyle.TRAVERSAL_URI}
+ });
+ }
+
+ @Before
+ public void setUp(){
+ httpTestUtil = new HttpTestUtil(queryStyle);
+ }
+
+ @Test
+ public void testPutWithAllCloudRegionChildrenNodesAndCheckIfDeleteIsSuccessful() throws IOException, AAIException {
+
+ String cloudRegionPayload = PayloadUtil.getResourcePayload("cloud-region.json");
+ String cloudRegionUri = "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/cloud-region-owner-with-vip-ipv4/cloud-region-id-with-vip-ipv4";
+
+ Response response = httpTestUtil.doPut(cloudRegionUri, cloudRegionPayload);
+ assertEquals("Expected the cloud region to be created", 201, response.getStatus());
+
+ response = httpTestUtil.doGet(cloudRegionUri);
+ assertEquals("Expected the cloud region to be found", 200, response.getStatus());
+ String jsonResponse = response.getEntity().toString();
+
+ JSONAssert.assertEquals(cloudRegionPayload, jsonResponse, false);
+
+ String vipIpv4Uri = cloudRegionUri + "/vip-ipv4-address-list/vip-ipv4-address-list-1";
+ String vipIpv4Payload = PayloadUtil.getResourcePayload("vip-ipv4-address-list.json");
+
+ response = httpTestUtil.doPut(vipIpv4Uri, vipIpv4Payload);
+ assertEquals("Expected the ipv4 address list to be created", 201, response.getStatus());
+
+ response = httpTestUtil.doGet(vipIpv4Uri);
+ assertEquals("Expected the ipv4 address list to be found", 200, response.getStatus());
+
+ jsonResponse = response.getEntity().toString();
+ String resourceVersion = JsonPath.read(jsonResponse, "$.resource-version");
+
+ response = httpTestUtil.doDelete(vipIpv4Uri, resourceVersion);
+ assertEquals("Expected the ipv4 address list to be deleted", 204, response.getStatus());
+
+ response = httpTestUtil.doGet(cloudRegionUri);
+ jsonResponse = response.getEntity().toString();
+ resourceVersion = JsonPath.read(jsonResponse, "$.resource-version");
+
+ response = httpTestUtil.doDelete(cloudRegionUri, resourceVersion);
+ assertEquals("Expected the cloud region to be deleted", 204, response.getStatus());
+ }
+}
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 a5b968b3..5041c7d1 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
@@ -465,16 +465,18 @@ public class DbSerializerTest extends AAISetup {
public void getURIForVertexTest() throws AAIException, URISyntaxException, UnsupportedEncodingException {
engine.startTransaction();
- Vertex cr = engine.tx().addVertex("aai-node-type", "cloud-region", "cloud-owner", "me", "cloud-region-id", "123");
+ Vertex cr = engine.tx().addVertex("aai-node-type", "cloud-region", "cloud-owner", "me", "cloud-region-id", "123", "aai-uri", "/cloud-infrastructure/cloud-regions/cloud-region/me/123");
Vertex ten = engine.tx().addVertex("aai-node-type", "tenant", "tenant-id", "453");
edgeSer.addTreeEdge(engine.tx().traversal(), cr, ten);
+ ten.property("aai-uri", "/cloud-infrastructure/cloud-regions/cloud-region/me/123/tenants/tenant/453");
+
URI compare = new URI("/cloud-infrastructure/cloud-regions/cloud-region/me/123/tenants/tenant/453");
assertEquals(compare, dbser.getURIForVertex(ten));
- cr.property("aai-node-type").remove();
URI compareFailure = new URI("/unknown-uri");
+ ten.property("aai-uri").remove();
assertEquals(compareFailure, dbser.getURIForVertex(ten));
}
@@ -619,9 +621,10 @@ public class DbSerializerTest extends AAISetup {
public void serializeSingleVertexChildTest() throws AAIException, UnsupportedEncodingException {
engine.startTransaction();
- Vertex cr = engine.tx().addVertex("aai-node-type", "cloud-region", "cloud-owner", "me", "cloud-region-id", "123");
+ Vertex cr = engine.tx().addVertex("aai-node-type", "cloud-region", "cloud-owner", "me", "cloud-region-id", "123", "aai-uri", "/cloud-infrastructure/cloud-regions/cloud-region/me/123");
Introspector tenIn = loader.introspectorFromName("tenant");
Vertex ten = dbser.createNewVertex(tenIn);
+ ten.property("aai-uri", cr.property("aai-uri").value().toString() + "/tenants/tenant/453");
edgeSer.addTreeEdge(engine.tx().traversal(), cr, ten);
@@ -639,8 +642,8 @@ public class DbSerializerTest extends AAISetup {
public void getVertexPropertiesRelationshipHasLabelTest() throws AAIException, UnsupportedEncodingException {
engine.startTransaction();
- Vertex gvnf = engine.tx().addVertex("aai-node-type","generic-vnf","vnf-id","vnf-123");
- Vertex vnfc = engine.tx().addVertex("aai-node-type","vnfc","vnfc-name","vnfc-123");
+ Vertex gvnf = engine.tx().addVertex("aai-node-type","generic-vnf","vnf-id","vnf-123","aai-uri", "/network/generic-vnfs/generic-vnf/vnf-123");
+ Vertex vnfc = engine.tx().addVertex("aai-node-type","vnfc","vnfc-name","vnfc-123","aai-uri", "/network/vnfcs/vnfc/vnfc-123");
edgeSer.addEdge(engine.tx().traversal(), gvnf, vnfc);
@@ -672,8 +675,8 @@ public class DbSerializerTest extends AAISetup {
engine.startTransaction();
- Vertex gvnf = engine.tx().addVertex("aai-node-type","generic-vnf","vnf-id","vnf-123");
- Vertex vnfc = engine.tx().addVertex("aai-node-type","vnfc","vnfc-name","vnfc-123");
+ Vertex gvnf = engine.tx().addVertex("aai-node-type","generic-vnf","vnf-id","vnf-123", "aai-uri", "/network/generic-vnfs/generic-vnf/vnf-123");
+ Vertex vnfc = engine.tx().addVertex("aai-node-type","vnfc","vnfc-name","vnfc-123", "aai-uri", "/network/vnfcs/vnfc/vnfc-123");
edgeSer.addEdge(engine.tx().traversal(), gvnf, vnfc);
diff --git a/aai-core/src/test/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngineTest.java b/aai-core/src/test/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngineTest.java
index a24855b8..b9431217 100644
--- a/aai-core/src/test/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngineTest.java
+++ b/aai-core/src/test/java/org/onap/aai/serialization/engines/query/GraphTraversalQueryEngineTest.java
@@ -38,6 +38,7 @@ import org.springframework.test.annotation.DirtiesContext;
import java.io.InputStream;
import java.util.*;
+import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -53,30 +54,30 @@ public class GraphTraversalQueryEngineTest extends AAISetup {
public void testFindParents() throws AAIException {
//setup
Graph graph = TinkerGraph.open();
-
+
Vertex cloudreg = graph.addVertex(T.id, "00", "aai-node-type", "cloud-region");
Vertex tenant = graph.addVertex(T.id, "10", "aai-node-type", "tenant");
Vertex vserver = graph.addVertex(T.id, "20", "aai-node-type", "vserver");
-
+
GraphTraversalSource g = graph.traversal();
-
+
edgeSer.addTreeEdge(g, cloudreg, tenant);
edgeSer.addTreeEdge(g, tenant, vserver);
-
+
//expect start vertex back plus any parents
List<Vertex> crExpected = new ArrayList<>(Arrays.asList(cloudreg)); //no parents
List<Vertex> tenExpected = new ArrayList<>(Arrays.asList(tenant, cloudreg)); //only has the immediate parent
List<Vertex> vsExpected = new ArrayList<>(Arrays.asList(vserver, tenant, cloudreg)); //parent & grandparent
-
+
GraphTraversalQueryEngine engine = new GraphTraversalQueryEngine(g);
-
+
//test
List<Vertex> crRes = engine.findParents(cloudreg);
assertTrue(crRes.containsAll(crExpected) && crExpected.containsAll(crRes));
-
+
List<Vertex> tenRes = engine.findParents(tenant);
assertTrue(tenRes.containsAll(tenExpected) && tenExpected.containsAll(tenRes));
-
+
List<Vertex> vsRes = engine.findParents(vserver);
assertTrue(vsRes.containsAll(vsExpected) && vsExpected.containsAll(vsRes));
//verify expected ordering - start, parent, grandparent
@@ -84,131 +85,157 @@ public class GraphTraversalQueryEngineTest extends AAISetup {
assertTrue(vsRes.get(1).equals(tenant));
assertTrue(vsRes.get(2).equals(cloudreg));
}
-
+
+ @Test
+ public void testFindAllParentsGivenAaiUris(){
+
+ //setup
+ Graph graph = TinkerGraph.open();
+
+ Vertex cloudreg = graph.addVertex(T.id, "00", "aai-node-type", "cloud-region", "aai-uri", "/cloud-infrastructure/cloud-regions/cloud-region/testowner/testid");
+ Vertex tenant = graph.addVertex(T.id, "10", "aai-node-type", "tenant", "aai-uri", "/cloud-infrastructure/cloud-regions/cloud-region/testowner/testid/tenants/tenant/testTenant1");
+ Vertex vserver = graph.addVertex(T.id, "20", "aai-node-type", "vserver", "aai-uri", "/cloud-infrastructure/cloud-regions/cloud-region/testowner/testid/tenants/tenant/testTenant1/vservers/vserver/testVserver1");
+
+ String [] uris = new String[]{
+ "/cloud-infrastructure/cloud-regions/cloud-region/testowner/testid/tenants/tenant/testTenant1",
+ "/cloud-infrastructure/cloud-regions/cloud-region/testowner/testid/tenants/tenant/testTenant1/vservers/vserver/testVserver1",
+ "/cloud-infrastructure/cloud-regions/cloud-region/testowner/testid"
+ };
+
+ GraphTraversalSource g = graph.traversal();
+ GraphTraversalQueryEngine queryEngine = new GraphTraversalQueryEngine(g);
+ List<Vertex> vertices = queryEngine.findParents(uris);
+
+ assertThat("Returned vertices should be 3 cloud region, tenant and vserver", vertices.size(), is(3));
+ assertThat("Expected the first element back to be vserver", vertices.get(0), is(vserver));
+ assertThat("Expected the second element back to be tenant", vertices.get(1), is(tenant));
+ assertThat("Expected the element back to be cloud region", vertices.get(2), is(cloudreg));
+ }
+
@Test
public void testFindAllChildren() throws AAIException {
//setup
Graph graph = TinkerGraph.open();
-
+
Vertex cloudreg = graph.addVertex(T.id, "00", "aai-node-type", "cloud-region");
Vertex tenant = graph.addVertex(T.id, "10", "aai-node-type", "tenant");
Vertex vserver = graph.addVertex(T.id, "20", "aai-node-type", "vserver");
Vertex vserver2 = graph.addVertex(T.id, "21", "aai-node-type", "vserver");
Vertex oam = graph.addVertex(T.id, "30", "aai-node-type", "oam-network");
-
+
GraphTraversalSource g = graph.traversal();
-
+
edgeSer.addTreeEdge(g, cloudreg, tenant);
edgeSer.addTreeEdge(g, tenant, vserver);
edgeSer.addTreeEdge(g, tenant, vserver2);
edgeSer.addTreeEdge(g, cloudreg, oam);
-
+
List<Vertex> crExpected = new ArrayList<>(Arrays.asList(cloudreg, tenant, vserver, vserver2, oam));
List<Vertex> vsExpected = new ArrayList<>(Arrays.asList(vserver));
-
+
GraphTraversalQueryEngine engine = new GraphTraversalQueryEngine(g);
-
+
//test
List<Vertex> crRes = engine.findAllChildren(cloudreg);
assertTrue(crRes.containsAll(crExpected) && crExpected.containsAll(crRes));
-
+
List<Vertex> vsRes = engine.findAllChildren(vserver);
assertTrue(vsRes.containsAll(vsExpected) && vsExpected.containsAll(vsRes));
}
-
+
@Test
public void testFindChildrenOfType() throws AAIException {
//setup
Graph graph = TinkerGraph.open();
-
+
Vertex gv = graph.addVertex(T.id, "00", "aai-node-type", "generic-vnf");
Vertex lint1 = graph.addVertex(T.id, "10", "aai-node-type", "l-interface");
Vertex lint2 = graph.addVertex(T.id, "11", "aai-node-type", "l-interface");
Vertex lag = graph.addVertex(T.id, "20", "aai-node-type", "lag-interface");
Vertex lint3 = graph.addVertex(T.id, "12", "aai-node-type", "l-interface");
-
+
GraphTraversalSource g = graph.traversal();
-
+
edgeSer.addTreeEdge(g, gv, lint1);
edgeSer.addTreeEdge(g, gv, lint2);
edgeSer.addTreeEdge(g, gv, lag);
edgeSer.addTreeEdge(g, lag, lint3);
-
+
List<Vertex> expected = new ArrayList<>(Arrays.asList(lint1, lint2));
-
+
GraphTraversalQueryEngine engine = new GraphTraversalQueryEngine(g);
-
+
//test
List<Vertex> results = engine.findChildrenOfType(gv, "l-interface");
assertTrue(results.containsAll(expected) && expected.containsAll(results));
}
-
+
@Test
public void testFindChildren() throws AAIException {
//setup
Graph graph = TinkerGraph.open();
-
+
Vertex gv = graph.addVertex(T.id, "00", "aai-node-type", "generic-vnf");
Vertex lint1 = graph.addVertex(T.id, "10", "aai-node-type", "l-interface");
Vertex lint2 = graph.addVertex(T.id, "11", "aai-node-type", "l-interface");
Vertex lag = graph.addVertex(T.id, "20", "aai-node-type", "lag-interface");
Vertex lint3 = graph.addVertex(T.id, "12", "aai-node-type", "l-interface");
-
+
GraphTraversalSource g = graph.traversal();
-
+
edgeSer.addTreeEdge(g, gv, lint1);
edgeSer.addTreeEdge(g, gv, lint2);
edgeSer.addTreeEdge(g, gv, lag);
edgeSer.addTreeEdge(g, lag, lint3);
-
+
List<Vertex> expected = new ArrayList<>(Arrays.asList(lint1, lint2, lag));
-
+
GraphTraversalQueryEngine engine = new GraphTraversalQueryEngine(g);
-
+
//test
List<Vertex> results = engine.findChildren(gv);
assertTrue(results.containsAll(expected) && expected.containsAll(results));
}
-
+
@Test
public void testFindRelatedVertices() throws AAIException {
//setup
-
+
Graph graph = TinkerGraph.open();
-
+
Vertex gv = graph.addVertex(T.id, "00", "aai-node-type", "generic-vnf");
Vertex lint = graph.addVertex(T.id, "10", "aai-node-type", "l-interface");
Vertex lint2 = graph.addVertex(T.id, "11", "aai-node-type", "l-interface");
Vertex log = graph.addVertex(T.id, "20", "aai-node-type", "logical-link");
-
+
GraphTraversalSource g = graph.traversal();
-
+
edgeSer.addTreeEdge(g, gv, lint);
edgeSer.addEdge(g, lint, log);
edgeSer.addEdge(g, log, lint2);
-
+
List<Vertex> outExpected = new ArrayList<>(Arrays.asList(lint));
List<Vertex> inExpected = new ArrayList<>(Arrays.asList(lint, lint2));
List<Vertex> bothExpected = new ArrayList<>(Arrays.asList(log));
-
+
GraphTraversalQueryEngine engine = new GraphTraversalQueryEngine(g);
-
+
//test
List<Vertex> outRes = engine.findRelatedVertices(gv, Direction.IN, "org.onap.relationships.inventory.BelongsTo", "l-interface");
assertTrue(outRes.containsAll(outExpected) && outExpected.containsAll(outRes));
List<Vertex> inRes = engine.findRelatedVertices(log, Direction.IN, "tosca.relationships.network.LinksTo", "l-interface");
assertTrue(inRes.containsAll(inExpected) && inExpected.containsAll(inRes));
-
+
List<Vertex> bothRes = engine.findRelatedVertices(lint, Direction.BOTH, "tosca.relationships.network.LinksTo", "logical-link");
assertTrue(bothRes.containsAll(bothExpected) && bothExpected.containsAll(bothRes));
}
-
+
@Test
public void testFindSubGraph() throws AAIException, EdgeRuleNotFoundException, AmbiguousRuleChoiceException {
//setup
Graph graph = TinkerGraph.open();
-
+
Vertex cr = graph.addVertex(T.id, "00", "aai-node-type", "cloud-region");
Vertex ten = graph.addVertex(T.id, "10", "aai-node-type", "tenant");
Vertex ten2 = graph.addVertex(T.id, "11", "aai-node-type", "tenant");
@@ -225,7 +252,7 @@ public class GraphTraversalQueryEngineTest extends AAISetup {
Vertex modelVer = graph.addVertex(T.id, "100", "aai-node-type", "model-ver");
GraphTraversalSource g = graph.traversal();
-
+
Edge crTen = edgeSer.addTreeEdge(g, cr, ten);
Edge crTen2 = edgeSer.addTreeEdge(g, cr, ten2);
Edge tenVs = edgeSer.addTreeEdge(g, ten, vs);
@@ -234,14 +261,14 @@ public class GraphTraversalQueryEngineTest extends AAISetup {
Edge lintLog = edgeSer.addEdge(g, lint, log);
Edge vsGv = edgeSer.addEdge(g, vs, gv);
edgeSer.addEdge(g, gv, vnfc);
-
+
edgeSer.addTreeEdge(g, gv, lag);
edgeSer.addTreeEdge(g, lag, lint2);
Edge modelVerEdge = edgeSer.addPrivateEdge(g, gv, modelVer, null);
edgeSer.addTreeEdge(g, comp, ctag);
Edge crComp = edgeSer.addEdge(g, cr, comp);
-
+
//findSubGraph(cr, 0, true)
List<Element> expected1 = new ArrayList<>(Arrays.asList(cr));
//findSubGraph(cr, 2, true)
@@ -249,48 +276,48 @@ public class GraphTraversalQueryEngineTest extends AAISetup {
crTen, crTen2, tenVs, tenVs2));
//findSubGraph(cr)
List<Element> expected3 = new ArrayList<>(Arrays.asList(cr, ten, ten2, comp, vs, vs2, lint, gv, log,
- crTen, crTen2, crComp, tenVs, tenVs2, vsLInt,
+ crTen, crTen2, crComp, tenVs, tenVs2, vsLInt,
vsGv, lintLog));
-
+
GraphTraversalQueryEngine engine = new GraphTraversalQueryEngine(g);
-
+
//test
Tree<Element> res1 = engine.findSubGraph(cr, 0, true);
Set<Element> resList1 = treeToList(res1);
assertTrue(resList1.containsAll(expected1) && expected1.containsAll(resList1));
-
+
Tree<Element> res2 = engine.findSubGraph(cr, 2, true);
Set<Element> resList2 = treeToList(res2);
assertTrue(resList2.containsAll(expected2) && expected2.containsAll(resList2));
-
+
Tree<Element> res3 = engine.findSubGraph(cr);
Set<Element> resList3 = treeToList(res3);
assertThat(resList3, containsInAnyOrder(expected3.toArray()));
// assertTrue(resList3.containsAll(expected3) && expected3.containsAll(resList3));
}
-
+
/**
- * convenience helper method to make it easier to check the contents of the tree against
+ * convenience helper method to make it easier to check the contents of the tree against
* a list of expected results
* @param tree - the tree whose contents you want in collection form
* @return set of the contents of the tree
*/
private Set<Element> treeToList(Tree<Element> tree) {
Set<Element> ret = new HashSet<>();
-
+
for (Element key : tree.keySet()) {
ret.add(key);
ret.addAll(treeToList(tree.get(key)));
}
-
+
return ret;
}
-
+
@Test
public void testFindEdgesForVersion() throws AAIException, EdgeRuleNotFoundException, AmbiguousRuleChoiceException {
//setup
Graph graph = TinkerGraph.open();
-
+
Vertex gv = graph.addVertex(T.id, "00", "aai-node-type", "generic-vnf");
Vertex vnfc = graph.addVertex(T.id, "10", "aai-node-type", "vnfc");
Vertex lob = graph.addVertex(T.id, "20", "aai-node-type", "line-of-business");
@@ -303,16 +330,16 @@ public class GraphTraversalQueryEngineTest extends AAISetup {
.addEdge("some-edge", cr, CONTAINS.toString(), "NONE");
GraphTraversalSource g = graph.traversal();
-
+
edgeSer.addTreeEdge(g, gv, lint); //tree edge so shouldn't appear in results
Edge gvVnfc = edgeSer.addEdge(g, gv, vnfc);
edgeSer.addEdge(g, gv, lob); //v11/12 not v10
Edge gvMvEdge = edgeSer.addPrivateEdge(g, gv, mv, null);
List<Edge> expected = new ArrayList<>(Arrays.asList(gvVnfc));
-
+
GraphTraversalQueryEngine engine = new GraphTraversalQueryEngine(g);
-
+
//test
Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getRelatedLinkVersion());
List<Edge> results = engine.findEdgesForVersion(gv, loader);
@@ -322,27 +349,27 @@ public class GraphTraversalQueryEngineTest extends AAISetup {
results = engine.findEdgesForVersion(cr, loader);
assertThat(results, containsInAnyOrder(expected.toArray()));
}
-
+
@Test
public void testFindCousinVertices() throws AAIException {
//setup
Graph graph = TinkerGraph.open();
-
+
Vertex gv = graph.addVertex(T.id, "00", "aai-node-type", "generic-vnf");
Vertex vnfc = graph.addVertex(T.id, "10", "aai-node-type", "vnfc");
Vertex lob = graph.addVertex(T.id, "20", "aai-node-type", "line-of-business");
Vertex lint = graph.addVertex(T.id, "30", "aai-node-type", "l-interface");
-
+
GraphTraversalSource g = graph.traversal();
-
+
edgeSer.addTreeEdge(g, gv, lint); //tree edge so shouldn't appear in results
edgeSer.addEdge(g, gv, vnfc);
edgeSer.addEdge(g, gv, lob);
-
+
List<Vertex> expected = new ArrayList<>(Arrays.asList(vnfc, lob));
-
+
GraphTraversalQueryEngine engine = new GraphTraversalQueryEngine(g);
-
+
//test
List<Vertex> results = engine.findCousinVertices(gv);
assertTrue(results.containsAll(expected) && expected.containsAll(results));
diff --git a/aai-core/src/test/resources/payloads/resource/cloud-region-with-vlan.json b/aai-core/src/test/resources/payloads/resource/cloud-region-with-vlan.json
new file mode 100644
index 00000000..bad4fadf
--- /dev/null
+++ b/aai-core/src/test/resources/payloads/resource/cloud-region-with-vlan.json
@@ -0,0 +1,50 @@
+{
+ "cloud-owner" : "junit-cloud-owner-with-vlan",
+ "cloud-region-id" : "junit-cloud-region-with-vlan",
+ "cloud-type" : "P9P1X6U9eDXR",
+ "owner-defined-type" : "OUrR8kI6Br",
+ "tenants" : {
+ "tenant" : [ {
+ "tenant-id" : "tenant1-with-vlan",
+ "tenant-name" : "yhgVBcv3Pr",
+ "vservers" : {
+ "vserver" : [ {
+ "vserver-id" : "vserver1-with-vlan",
+ "vserver-name" : "P3SJ347Uyv",
+ "vserver-name2" : "1dHd",
+ "vserver-selflink" : "v7dU8H",
+ "in-maint" : false,
+ "is-closed-loop-disabled" : true,
+ "l-interfaces" : {
+ "l-interface" : [ {
+ "interface-name" : "top-linterface-with-vlan",
+ "interface-role" : "3W1FAJGSQ",
+ "v6-wan-link-ip" : "WugWw3N",
+ "selflink" : "Of4j0pU",
+ "interface-id" : "eoW",
+ "macaddr" : "XNbbIy33",
+ "network-name" : "ZETDv5sGhiS",
+ "management-option" : "qR3RyCxgEU",
+ "vlans" : {
+ "vlan" : [ {
+ "vlan-interface" : "test-vlan-interface-1",
+ "vlan-id-inner" : 884,
+ "vlan-id-outer" : 992,
+ "speed-value" : "RyFPm",
+ "speed-units" : "ZrckmLff7b",
+ "vlan-description" : "zjAeUFgeagpf",
+ "backdoor-connection" : "gANMvUquB",
+ "vpn-key" : "l0rV7bb2Sc",
+ "orchestration-status" : "WVnLpbzIx",
+ "in-maint" : false,
+ "prov-status" : "tYMRi6df",
+ "is-ip-unnumbered" : false
+ } ]
+ }
+ } ]
+ }
+ } ]
+ }
+ } ]
+ }
+}
diff --git a/aai-core/src/test/resources/payloads/resource/cloud-region.json b/aai-core/src/test/resources/payloads/resource/cloud-region.json
new file mode 100644
index 00000000..0bbf6398
--- /dev/null
+++ b/aai-core/src/test/resources/payloads/resource/cloud-region.json
@@ -0,0 +1,4 @@
+{
+ "cloud-owner": "cloud-region-owner-with-vip-ipv4",
+ "cloud-region-id": "cloud-region-id-with-vip-ipv4"
+}
diff --git a/aai-core/src/test/resources/payloads/resource/entitlement.json b/aai-core/src/test/resources/payloads/resource/entitlement.json
new file mode 100644
index 00000000..09afb617
--- /dev/null
+++ b/aai-core/src/test/resources/payloads/resource/entitlement.json
@@ -0,0 +1,4 @@
+{
+ "group-uuid":"g1",
+ "resource-uuid":"r1"
+}
diff --git a/aai-core/src/test/resources/payloads/resource/model-element.json b/aai-core/src/test/resources/payloads/resource/model-element.json
new file mode 100644
index 00000000..935f1b05
--- /dev/null
+++ b/aai-core/src/test/resources/payloads/resource/model-element.json
@@ -0,0 +1,230 @@
+{
+ "model-element-uuid": "acf8b6cf-e051-4c1b-bcad-b24792f826cf-test1",
+ "new-data-del-flag": "7hWigbwQCh",
+ "cardinality": "loWHX7E8X",
+ "linkage-points": [
+ "Ve4JU"
+ ],
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "01b757d5-6468-48d0-a1cd-2aa8310dadab-test1",
+ "new-data-del-flag": "IXoM0QnE0W",
+ "cardinality": "THLHKl"
+ },
+ {
+ "model-element-uuid": "2e5d5696-2221-4bcf-a493-e0ca92e323de-test1",
+ "new-data-del-flag": "icATJZ7Vbhz",
+ "cardinality": "tOIz"
+ }
+ ]
+ },
+ "model-constraints": {
+ "model-constraint": [
+ {
+ "model-constraint-uuid": "9f2e872b-000e-4bb9-9398-f308a997dd4f-test1",
+ "constrained-element-set-uuid-to-replace": "XfAVftTYu",
+ "constrained-element-sets": {
+ "constrained-element-set": [
+ {
+ "constrained-element-set-uuid": "103cc6f7-b648-4a3f-b5aa-0ffdac4d4bc5-test1",
+ "constraint-type": "FLKyNFdqbSSje",
+ "check-type": "IDLSYTM",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "5c063d38-d83e-4fe5-a721-86296fe39267-test1",
+ "element-choice-set-name": "EFc5b4k7LN8hF",
+ "cardinality": "xx8",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "0b7a5aa2-5061-4916-a2c6-5280e67e0a71-test1",
+ "new-data-del-flag": "x1Lo15W",
+ "cardinality": "COu"
+ },
+ {
+ "model-element-uuid": "f0af348b-1701-409f-bb11-e3acc77ad718-test1",
+ "new-data-del-flag": "eiWkNQEj",
+ "cardinality": "3aju5XtI"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "2c0888a6-fb6d-4a72-b0a1-3349c90d9e33-test1",
+ "element-choice-set-name": "Ko4",
+ "cardinality": "aXjnyYfCRFTDK",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "ea8853be-8473-4f80-8229-9041864e143e-test1",
+ "new-data-del-flag": "4tirsCs0fjDdS",
+ "cardinality": "v2hbEn8u"
+ },
+ {
+ "model-element-uuid": "f1267f37-5aa0-4f4a-ae66-3cf782ff4a9d-test1",
+ "new-data-del-flag": "mzuWZTlc9f",
+ "cardinality": "ysBXVL"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "constrained-element-set-uuid": "a82256df-5bc8-4433-851f-9b09f63432b4-test1",
+ "constraint-type": "qgnLpj",
+ "check-type": "zFug3wfyCe5cF",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "3ce79981-c0cc-4210-9dab-89b8866797be-test1",
+ "element-choice-set-name": "rZ2f7Es",
+ "cardinality": "H1b",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "52362a88-eb7a-4fe5-a6d5-1ca414cfed64-test1",
+ "new-data-del-flag": "8cQmvQgeKJz",
+ "cardinality": "6T7GiwYlJR5"
+ },
+ {
+ "model-element-uuid": "e9d00d89-a340-4ef1-ab19-63367a5e8642-test1",
+ "new-data-del-flag": "ec8DWfYeMJdr",
+ "cardinality": "Bumc8fT7"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "335bac38-9739-4ff7-8743-e186310d86a9-test1",
+ "element-choice-set-name": "K0MH",
+ "cardinality": "rL3fH1Oz",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "29244639-38ab-45b2-82b7-b91001ad56da-test1",
+ "new-data-del-flag": "YZGbB6",
+ "cardinality": "ushcYd"
+ },
+ {
+ "model-element-uuid": "e36d3159-bfa7-465a-849f-de9ca6d4f304-test1",
+ "new-data-del-flag": "ZtzRhZbxv2i",
+ "cardinality": "NE4m8n5hj"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "model-constraint-uuid": "9e74a97c-52a9-43b4-bb9d-144cb5a2216e-test1",
+ "constrained-element-set-uuid-to-replace": "bZqdarfk6",
+ "constrained-element-sets": {
+ "constrained-element-set": [
+ {
+ "constrained-element-set-uuid": "6c4db1da-8860-4445-a0ad-3ae00709e2bb-test1",
+ "constraint-type": "Xzat2eVcU36g",
+ "check-type": "3Y5Bi32VkRHFl",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "33dc52b0-3461-4ca6-a195-c3cacc2ab426-test1",
+ "element-choice-set-name": "2ziwMvQGmanJ",
+ "cardinality": "7XXcdT5sqsOf",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "c0fb7805-dfc4-4972-9a1c-d9409560f6e3-test1",
+ "new-data-del-flag": "262Lx",
+ "cardinality": "0ZaryC"
+ },
+ {
+ "model-element-uuid": "e868506d-ef7d-4843-9c1b-47712c7c1b77-test1",
+ "new-data-del-flag": "f7cKUCEbVuj6",
+ "cardinality": "6LlYciE99"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "aca6b107-ba99-4e10-aef5-ff35a5b25a60-test1",
+ "element-choice-set-name": "lqfZDs",
+ "cardinality": "9AwB7",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "527faaf0-f989-47a4-9ffd-4ea16d034be1-test1",
+ "new-data-del-flag": "mPra14ZfLilOw",
+ "cardinality": "y6mYr6"
+ },
+ {
+ "model-element-uuid": "dfd7c245-0a28-494d-b388-faf27481674c-test1",
+ "new-data-del-flag": "muGR",
+ "cardinality": "TUj4Z"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "constrained-element-set-uuid": "17999338-a062-4447-b8c3-b27228255ede-test1",
+ "constraint-type": "WhTbdWCLyA",
+ "check-type": "tN02MBeB",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "633c6757-2270-48fb-bff7-61145e6c943f-test1",
+ "element-choice-set-name": "Ith1PEe6",
+ "cardinality": "8sta",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "827c40a9-cabe-460a-b537-2f117ca62db5-test1",
+ "new-data-del-flag": "fS65rXWQY",
+ "cardinality": "Kq42Z8GzCh"
+ },
+ {
+ "model-element-uuid": "c107a4bd-59e4-4249-bbc3-a006645dcb01-test1",
+ "new-data-del-flag": "EtgTeJdo19",
+ "cardinality": "tvzpgg"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "930260d8-4cfd-4494-ba2c-d619c143a390-test1",
+ "element-choice-set-name": "ugDc0",
+ "cardinality": "K8MXjV",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "f17f9eea-d421-4e8a-8628-32a4b56507ef-test1",
+ "new-data-del-flag": "rjAbq7gyZWe",
+ "cardinality": "VbDCFB9"
+ },
+ {
+ "model-element-uuid": "ee1d800e-46c1-4bb0-8664-f257850ffff9-test1",
+ "new-data-del-flag": "YontPXK4sj4s",
+ "cardinality": "UQnNPld4sE"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+}
diff --git a/aai-core/src/test/resources/payloads/resource/model.json b/aai-core/src/test/resources/payloads/resource/model.json
new file mode 100644
index 00000000..a86a1de8
--- /dev/null
+++ b/aai-core/src/test/resources/payloads/resource/model.json
@@ -0,0 +1,975 @@
+{
+ "model-invariant-id": "24c04fc5-f3f8-43ec-8792-c6f940638676-test1",
+ "model-type": "woZ4dpF3TM",
+ "model-vers": {
+ "model-ver": [
+ {
+ "model-version-id": "0c4c59f0-9864-43ca-b0c2-ca38746b72a5-test1",
+ "model-name": "vzZn3Q3h",
+ "model-version": "RcN2FIwUF",
+ "distribution-status": "qcCHkye",
+ "model-description": "qcPB4hOig9",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "0dc2b8b6-af8d-4213-970b-7861a603fc86-test1",
+ "new-data-del-flag": "OzhypC",
+ "cardinality": "vNpFfHn",
+ "linkage-points": [
+ "BTDVw7pA"
+ ],
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "0ff7bfc5-e42b-474d-b728-cfdc08310971-test1",
+ "new-data-del-flag": "v54vhcTX",
+ "cardinality": "uHLsCw"
+ },
+ {
+ "model-element-uuid": "4fb1b036-9963-467e-93fe-c6e499859b2e-test1",
+ "new-data-del-flag": "UAJAjOCe9dIiW",
+ "cardinality": "8PhfKI"
+ }
+ ]
+ },
+ "model-constraints": {
+ "model-constraint": [
+ {
+ "model-constraint-uuid": "782ba24a-28ab-4fd0-8e69-da10cc5373f3-test1",
+ "constrained-element-set-uuid-to-replace": "8vcq",
+ "constrained-element-sets": {
+ "constrained-element-set": [
+ {
+ "constrained-element-set-uuid": "a33e65c3-1198-4d4c-9799-2b521e4c4212-test1",
+ "constraint-type": "4jqozTvJSD",
+ "check-type": "J9aM",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "7df27a94-06c8-46ef-9fc2-5900d8cffbb0-test1",
+ "element-choice-set-name": "wjNT",
+ "cardinality": "XSPmZH",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "fcf1450b-cf5c-414a-99c0-2bd7ca247997-test1",
+ "new-data-del-flag": "uhwWkaDw",
+ "cardinality": "jeBU9v"
+ },
+ {
+ "model-element-uuid": "85bfca5f-03ac-4653-a3b4-bdfad8dd1c13-test1",
+ "new-data-del-flag": "L2BQe2kyA",
+ "cardinality": "asciE2y7RWGVa"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "d20040e2-0417-4a2d-978e-e6c9f353a0c5-test1",
+ "element-choice-set-name": "x7vEDj5",
+ "cardinality": "A6f2Us",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "5cdcbb91-22eb-4c12-9a54-b8c3ff5aa591-test1",
+ "new-data-del-flag": "BCo",
+ "cardinality": "FejO1GRl"
+ },
+ {
+ "model-element-uuid": "7a401382-7d45-40f9-8fe7-236629273226-test1",
+ "new-data-del-flag": "zFj",
+ "cardinality": "9DzyB7u"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "constrained-element-set-uuid": "2f7a375a-135d-461b-b806-e7cd636506f4-test1",
+ "constraint-type": "Toy",
+ "check-type": "uYEWZon81Wa",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "8aab42ee-561f-4506-ab66-6432442193f8-test1",
+ "element-choice-set-name": "RpJJn1eRQL",
+ "cardinality": "q0XXZ52",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "2a35ad40-02ef-4947-b20c-94a90440ffc7-test1",
+ "new-data-del-flag": "gXHt5O5XyRKb",
+ "cardinality": "idg0cH"
+ },
+ {
+ "model-element-uuid": "7aae6c34-086e-477b-845a-01cedc2a4e25-test1",
+ "new-data-del-flag": "Zwj",
+ "cardinality": "3vkT"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "f42dcd25-aa82-401f-b987-5d0f46d6b5d6-test1",
+ "element-choice-set-name": "Cuon",
+ "cardinality": "cfxfo3MAF",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "2f9f4c5c-216c-45c0-913b-5513faa6f887-test1",
+ "new-data-del-flag": "2ZTs",
+ "cardinality": "zki"
+ },
+ {
+ "model-element-uuid": "6abd9eb0-59b2-45d1-bc31-51913bc9f54b-test1",
+ "new-data-del-flag": "9cQkkA",
+ "cardinality": "NGY7CgvUQDN"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "model-constraint-uuid": "8544de93-b647-4d79-aa55-a3ebe01664e7-test1",
+ "constrained-element-set-uuid-to-replace": "phbhKDPCcUjK",
+ "constrained-element-sets": {
+ "constrained-element-set": [
+ {
+ "constrained-element-set-uuid": "61624b66-e059-49c6-a97c-06ca4643e259-test1",
+ "constraint-type": "gp0nB63dH",
+ "check-type": "NFnVJKceCMc",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "f85f1ee8-d28f-4128-83d8-02c2e07f9e27-test1",
+ "element-choice-set-name": "8noi",
+ "cardinality": "mTFoGk",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "1e15718d-17e8-4a34-852e-2edede549b63-test1",
+ "new-data-del-flag": "f3p1f",
+ "cardinality": "c0Z6zG0iKX"
+ },
+ {
+ "model-element-uuid": "4ad51c91-1e90-4683-b9ea-017cf0bc528e-test1",
+ "new-data-del-flag": "05r47Aldegi",
+ "cardinality": "aoF"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "fb2c7824-fc87-4fe9-93c6-10586a59384e-test1",
+ "element-choice-set-name": "EIjKr0w3tJ",
+ "cardinality": "qlw6EFFF",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "2395bed7-399d-41cd-81af-e5002854bc69-test1",
+ "new-data-del-flag": "Uj2",
+ "cardinality": "eLHBGqv7wz5z"
+ },
+ {
+ "model-element-uuid": "77840aeb-0868-49c1-a97d-6ded16115174-test1",
+ "new-data-del-flag": "rOR",
+ "cardinality": "ddXm59kMQ01y"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "constrained-element-set-uuid": "4f1f30ee-5bd5-4f19-b11d-23ebf0fcd569-test1",
+ "constraint-type": "Ul7rn0Gyh",
+ "check-type": "5KpT6x",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "d2b9a3f5-29de-45ba-ad5a-184e0635607a-test1",
+ "element-choice-set-name": "OWFEeT",
+ "cardinality": "g2wvznpf",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "93d0b10b-529a-4ad4-88fa-afc7273ec538-test1",
+ "new-data-del-flag": "BHqDTu",
+ "cardinality": "bUZd3Zj4b"
+ },
+ {
+ "model-element-uuid": "fd6548f8-211a-4194-a78e-857efc443180-test1",
+ "new-data-del-flag": "ygDuebv",
+ "cardinality": "UZx1v0HH7I"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "f393b086-40b6-47d9-b28a-b830d5d7f896-test1",
+ "element-choice-set-name": "dxt8afBT",
+ "cardinality": "L3mtZIH342JVw",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "d802155e-8e16-4b9d-986a-d0f490d83e56-test1",
+ "new-data-del-flag": "cPapfw",
+ "cardinality": "4O3aiKf"
+ },
+ {
+ "model-element-uuid": "64cf1800-77b7-4c1d-80b2-38fc156769a6-test1",
+ "new-data-del-flag": "T2dc7t3",
+ "cardinality": "LTrGUfoB7imS"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "model-element-uuid": "1db3d04c-92c6-4100-b851-16a0a2318909-test1",
+ "new-data-del-flag": "9Gc",
+ "cardinality": "vtJk",
+ "linkage-points": [
+ "NKC5OiZl"
+ ],
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "16b90f9d-d2ed-46e8-8a0d-f2907ecf723d-test1",
+ "new-data-del-flag": "jcjL",
+ "cardinality": "qxX"
+ },
+ {
+ "model-element-uuid": "46afb085-7025-4a35-99e3-6170dc98b74b-test1",
+ "new-data-del-flag": "tXgrF6T4HrirE",
+ "cardinality": "55waV3oUI"
+ }
+ ]
+ },
+ "model-constraints": {
+ "model-constraint": [
+ {
+ "model-constraint-uuid": "6f6fbf96-c9a7-4393-9e81-284d194ba6a3-test1",
+ "constrained-element-set-uuid-to-replace": "HF81PuSuM",
+ "constrained-element-sets": {
+ "constrained-element-set": [
+ {
+ "constrained-element-set-uuid": "cf2d2ff1-1ffc-4ad6-b3ce-8729c3352637-test1",
+ "constraint-type": "XfD",
+ "check-type": "mVERn7luqFc",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "85fb8953-f86d-4d58-8ca2-3169cba074c6-test1",
+ "element-choice-set-name": "4s6Jf",
+ "cardinality": "KL8eVh9xZ",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "7b1fd5b5-b633-4ed6-a9e8-9c3430eaaae0-test1",
+ "new-data-del-flag": "uNbESfr",
+ "cardinality": "aEj2c5UXN2qW"
+ },
+ {
+ "model-element-uuid": "c67a3856-3812-4c16-abb3-484fe68ba65e-test1",
+ "new-data-del-flag": "cg1GbGyps",
+ "cardinality": "cCPBuauJ"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "4748a324-a8aa-420a-9f48-0fd0b7418a1a-test1",
+ "element-choice-set-name": "U3JuW0tx",
+ "cardinality": "4jpXRS43G",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "daad8caa-dbfc-487a-91d4-a93021a86e0c-test1",
+ "new-data-del-flag": "ZoRQyflmIqEaA",
+ "cardinality": "Mu7PzxNg8cta"
+ },
+ {
+ "model-element-uuid": "e5a640f1-1203-410c-8665-0ee325179368-test1",
+ "new-data-del-flag": "thsF0L",
+ "cardinality": "fViD"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "constrained-element-set-uuid": "5d1b2701-d719-4eb5-b5bc-355f99042648-test1",
+ "constraint-type": "4wPy2Xd",
+ "check-type": "sDuGfZji",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "d01f1c5b-5ba1-4c21-b80d-901867a1d810-test1",
+ "element-choice-set-name": "FdrVe6o",
+ "cardinality": "F1MXs1fET0jr3",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "6e059bfe-5386-4491-8e84-b1b6dd8b5333-test1",
+ "new-data-del-flag": "DfodMIT72h7",
+ "cardinality": "KvRbLIJFL"
+ },
+ {
+ "model-element-uuid": "ea73886a-ff64-4d3c-9b17-5ae5b2196dea-test1",
+ "new-data-del-flag": "n9PnoK5",
+ "cardinality": "0E3fM6"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "abb55d08-28b6-48d8-b19e-91b12c096649-test1",
+ "element-choice-set-name": "MRFYeF7",
+ "cardinality": "b64jIhgbYH7",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "c449a692-bd7d-4d86-b46e-1c417b17099f-test1",
+ "new-data-del-flag": "ApwuLwUkkw",
+ "cardinality": "m23c6lsF"
+ },
+ {
+ "model-element-uuid": "7cb770d9-55d8-45d2-8b9b-abdff7a2c88b-test1",
+ "new-data-del-flag": "MeSjvno",
+ "cardinality": "lGFfcOOl19"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "model-constraint-uuid": "ce9e9365-1fec-4c29-8201-c4417ee2ea1d-test1",
+ "constrained-element-set-uuid-to-replace": "Buq56Km4W9BD",
+ "constrained-element-sets": {
+ "constrained-element-set": [
+ {
+ "constrained-element-set-uuid": "3dcea521-a227-46f3-bd4f-ef1fcff0755e-test1",
+ "constraint-type": "WZr",
+ "check-type": "pxJXuyaXvsaQy",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "19dc8b4a-c58b-4ff8-b507-877c6521d91a-test1",
+ "element-choice-set-name": "af5CO7sD5TWwz",
+ "cardinality": "uGwotewgnmls",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "5d476750-ddc3-4822-b629-5fba93445ed9-test1",
+ "new-data-del-flag": "mMjS6OflV3c",
+ "cardinality": "Gidw5"
+ },
+ {
+ "model-element-uuid": "d4d4f1f6-ad60-4a94-b076-eb36db6fb362-test1",
+ "new-data-del-flag": "kWLrcR",
+ "cardinality": "AU6llmk"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "d6616e1a-3de5-4981-a216-805bdd97d65e-test1",
+ "element-choice-set-name": "9w67AaiJNt0",
+ "cardinality": "kKax01oqb",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "bb11c9c1-5013-4b51-9a06-9729addfd4af-test1",
+ "new-data-del-flag": "ANM8TN0a",
+ "cardinality": "UPtA8wc4m"
+ },
+ {
+ "model-element-uuid": "71b323c0-1829-414e-85f6-99f4b5835e44-test1",
+ "new-data-del-flag": "okC9",
+ "cardinality": "1KP3eU5j8"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "constrained-element-set-uuid": "77d1cc2d-6e94-4a4f-a7ec-f725605f18d3-test1",
+ "constraint-type": "inJa",
+ "check-type": "JkoIos3V",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "9893bb02-e422-4810-bccc-a594b0489ded-test1",
+ "element-choice-set-name": "ZIync",
+ "cardinality": "WZfSZe",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "b0aaa08d-a7fe-44ae-a6d8-d21645831a23-test1",
+ "new-data-del-flag": "RdwsDmBBz",
+ "cardinality": "Ry6V3zZtLOS"
+ },
+ {
+ "model-element-uuid": "a2670e8e-f57e-4c0e-9522-6d16b4e2cf18-test1",
+ "new-data-del-flag": "aCECwDjNyauTZ",
+ "cardinality": "a28MCzMm24JBI"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "321ccc75-61ae-4358-af89-53809a28f956-test1",
+ "element-choice-set-name": "HjNWjs",
+ "cardinality": "bxRIxMP",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "41965df8-b42d-47ba-8bf6-cade35804311-test1",
+ "new-data-del-flag": "CPLVd",
+ "cardinality": "4Ij4hep2"
+ },
+ {
+ "model-element-uuid": "db7ee384-420e-44fb-a1ca-809f94add6b8-test1",
+ "new-data-del-flag": "Cj5GVv",
+ "cardinality": "1LSdRvvzBBfa"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "metadata": {
+ "metadatum": [
+ {
+ "metaname": "8b3496f1-822e-4acf-b1fc-d07a494d3a86-test1",
+ "metaval": "gZwqNxIDsw"
+ },
+ {
+ "metaname": "d9a50737-f3df-4156-881d-e3875031b413-test1",
+ "metaval": "qMugMK"
+ }
+ ]
+ }
+ },
+ {
+ "model-version-id": "1e6ec4df-ad66-40bc-8f1d-ba40c835e77e-test1",
+ "model-name": "wStuf",
+ "model-version": "HAm",
+ "distribution-status": "zsKxpTc5YTW1",
+ "model-description": "zxHpALNUvX8V",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "b1ac6004-59bd-4372-ab16-f327d04d647e-test1",
+ "new-data-del-flag": "j58MXR",
+ "cardinality": "9Xr0gNa",
+ "linkage-points": [
+ "LmE7mpec2"
+ ],
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "38295729-dc3b-4b7b-87e3-446513a802df-test1",
+ "new-data-del-flag": "R5KeFH8",
+ "cardinality": "9wkk9Z"
+ },
+ {
+ "model-element-uuid": "b1ac08c3-3047-4637-8796-6b5e43bbad19-test1",
+ "new-data-del-flag": "KOS9kMuahku",
+ "cardinality": "F6A"
+ }
+ ]
+ },
+ "model-constraints": {
+ "model-constraint": [
+ {
+ "model-constraint-uuid": "0c7f45c8-2552-400a-b029-e20cddda592b-test1",
+ "constrained-element-set-uuid-to-replace": "105ZUJ",
+ "constrained-element-sets": {
+ "constrained-element-set": [
+ {
+ "constrained-element-set-uuid": "162ea223-ae49-4e6d-ba30-8215c433a7e2-test1",
+ "constraint-type": "GAq",
+ "check-type": "ippNik",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "5caa493c-e804-4c28-aad6-3389a1801e29-test1",
+ "element-choice-set-name": "oLPlXWcCL",
+ "cardinality": "ns6",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "ff8f0de4-220f-4f7f-8447-07c67ed8a109-test1",
+ "new-data-del-flag": "TlLVzdU5Mz",
+ "cardinality": "wQI"
+ },
+ {
+ "model-element-uuid": "fd6018bc-b3ce-4073-b494-848c06aaef83-test1",
+ "new-data-del-flag": "ZIkOtmdu8ij",
+ "cardinality": "XfOsai"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "45d079e2-94f8-4c75-9e58-fca00da8e032-test1",
+ "element-choice-set-name": "nfOh9SvgG",
+ "cardinality": "j5u1OHFt",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "3edbf250-7039-47cd-b31d-019e5639006b-test1",
+ "new-data-del-flag": "Qo5M8AB",
+ "cardinality": "crDs4E"
+ },
+ {
+ "model-element-uuid": "566c492a-4b8d-4393-9634-5deb36114390-test1",
+ "new-data-del-flag": "tSl",
+ "cardinality": "xZK7oAuI1"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "constrained-element-set-uuid": "6efd9e99-bca6-4f3b-a7dc-38ad373c38e9-test1",
+ "constraint-type": "v3RYRkCdTm",
+ "check-type": "adGnhMq6P4",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "09d59684-e8e5-4e08-93af-b2a65d0328e6-test1",
+ "element-choice-set-name": "Q1rPa",
+ "cardinality": "ENpTrUR",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "904654a2-4d7d-4d07-af26-ddb881dd05d7-test1",
+ "new-data-del-flag": "76D6azxVm1XR9",
+ "cardinality": "R0Zb34f"
+ },
+ {
+ "model-element-uuid": "898cfb56-6e36-4b03-8967-9384d06b3a3e-test1",
+ "new-data-del-flag": "SJtXdr4",
+ "cardinality": "vG4JrjQ8"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "9ac87d60-51c5-4dd6-bb1e-1b8dd234b5a9-test1",
+ "element-choice-set-name": "azv",
+ "cardinality": "oJfnKsDO5k",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "6ec8304f-8159-4344-b06d-faf1001fd275-test1",
+ "new-data-del-flag": "3s5zQjf8Vwl4",
+ "cardinality": "6SogRPhZX38Ol"
+ },
+ {
+ "model-element-uuid": "cfd9b055-3d8a-4429-9ea6-078a2270e469-test1",
+ "new-data-del-flag": "VaW81J59tqiY",
+ "cardinality": "t1mNuU7JnNc7L"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "model-constraint-uuid": "fe9d4b0d-dc65-4440-a10f-5237f135255c-test1",
+ "constrained-element-set-uuid-to-replace": "pWv26",
+ "constrained-element-sets": {
+ "constrained-element-set": [
+ {
+ "constrained-element-set-uuid": "ea1473a3-e72d-4838-b8d8-7c8e86e0b3c8-test1",
+ "constraint-type": "Mdbb0G5nLxcx3",
+ "check-type": "a8rlES",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "86726d80-74d6-4b7e-9532-65ebb76133ef-test1",
+ "element-choice-set-name": "fBm0",
+ "cardinality": "csPsKpgV",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "c0df13d1-a8be-4bc0-a572-44ca28d35d62-test1",
+ "new-data-del-flag": "k9x8eFMP",
+ "cardinality": "5xHWzWretpyAN"
+ },
+ {
+ "model-element-uuid": "ef4f9a86-a1b8-48ef-a7aa-ff56a1879ef7-test1",
+ "new-data-del-flag": "JdujO3QQr4",
+ "cardinality": "N6pvsIK"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "07f1ae12-8e40-4c42-bb8c-e5931f82be84-test1",
+ "element-choice-set-name": "by4K",
+ "cardinality": "HfJt7",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "aed78a3d-de9e-4825-88b3-8251a822e87c-test1",
+ "new-data-del-flag": "NbAWo0r1su",
+ "cardinality": "GIHSc"
+ },
+ {
+ "model-element-uuid": "451ef346-a43e-4d9c-ae94-4d14f12b7776-test1",
+ "new-data-del-flag": "o6GI",
+ "cardinality": "Hbbm3HRFeXw8U"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "constrained-element-set-uuid": "1b3d0f60-b438-4789-b711-5d48c211e9b3-test1",
+ "constraint-type": "G7HBqSqa8",
+ "check-type": "Rky",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "c47b3c18-912b-4781-82a9-961702e58712-test1",
+ "element-choice-set-name": "ntxJ1ETx96",
+ "cardinality": "6B1XDdERKUk0f",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "d451967f-5cb9-4aba-8595-938d44bed081-test1",
+ "new-data-del-flag": "pwHvYjtFEvmn",
+ "cardinality": "X6jiiniZ24e3"
+ },
+ {
+ "model-element-uuid": "0f6196d6-b3b7-451a-a3d8-2a0a9bf401b7-test1",
+ "new-data-del-flag": "YFY4Dmyr",
+ "cardinality": "CMF05rTle1"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "927a4c5d-c06f-474c-bc39-b1bf8edbd5a9-test1",
+ "element-choice-set-name": "C19",
+ "cardinality": "7xCo",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "b839b84d-4508-4aa6-8c32-0566a25d62d1-test1",
+ "new-data-del-flag": "QdvVPKk",
+ "cardinality": "QWO7FG"
+ },
+ {
+ "model-element-uuid": "20df13a4-aad9-46ed-8c40-d2c9ee25c0c0-test1",
+ "new-data-del-flag": "aFu39uCq",
+ "cardinality": "wFwAw3L3wT2x5"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "model-element-uuid": "c198c7e7-162f-4b36-ab18-1ea652940569-test1",
+ "new-data-del-flag": "c9VM1nU9",
+ "cardinality": "na6ev",
+ "linkage-points": [
+ "Qn71",
+ "VqVquEM"
+ ],
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "5a3d5001-ed82-4586-9f8e-f4754c5a7a18-test1",
+ "new-data-del-flag": "x5unCqf",
+ "cardinality": "SelKZSH"
+ },
+ {
+ "model-element-uuid": "b150a826-8d8e-4e76-8661-6cbc67fd0d9a-test1",
+ "new-data-del-flag": "9LfZWv",
+ "cardinality": "uMtY5vRkmCnw"
+ }
+ ]
+ },
+ "model-constraints": {
+ "model-constraint": [
+ {
+ "model-constraint-uuid": "43871728-3816-470f-9b36-4097731910a4-test1",
+ "constrained-element-set-uuid-to-replace": "R8Uhk",
+ "constrained-element-sets": {
+ "constrained-element-set": [
+ {
+ "constrained-element-set-uuid": "0fd99298-8079-4a3c-bbed-dce0ceadf790-test1",
+ "constraint-type": "JFVkmI9ilV",
+ "check-type": "9eqnm",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "22a978b9-4dcc-4c7d-b88a-6bdbab97dd7c-test1",
+ "element-choice-set-name": "4fHNNV",
+ "cardinality": "VBAiH",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "d9bef0c1-07c9-4251-b621-196be3b7870e-test1",
+ "new-data-del-flag": "FQen9U2BTGx",
+ "cardinality": "ohd"
+ },
+ {
+ "model-element-uuid": "60d8b814-8035-4010-8d46-9db2e5962f17-test1",
+ "new-data-del-flag": "2aJgwjV3UZv",
+ "cardinality": "WMb"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "a5b753eb-162e-4bea-8185-43b7e96c0770-test1",
+ "element-choice-set-name": "k9Ud",
+ "cardinality": "VAL51",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "1ecfe4f4-6696-4df4-8b93-b2b3fa39c377-test1",
+ "new-data-del-flag": "SRFYVMGe",
+ "cardinality": "muxuy0DZBBW"
+ },
+ {
+ "model-element-uuid": "96acb4b2-f178-4119-8c32-6c5901896417-test1",
+ "new-data-del-flag": "wbzd",
+ "cardinality": "M0Y7Meota"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "constrained-element-set-uuid": "b22dc84b-5568-4b7d-9b58-0bc90c969619-test1",
+ "constraint-type": "waPRf1NGHeFy",
+ "check-type": "YziABbwA4",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "fb4d5b28-2083-4bb6-a87d-e53eadd14d54-test1",
+ "element-choice-set-name": "VnX7QOx",
+ "cardinality": "qk4aMYBkw",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "1b5481f2-66c9-4cd4-89ee-492e333570fe-test1",
+ "new-data-del-flag": "ba6QIyym",
+ "cardinality": "zUJ9gpkRq"
+ },
+ {
+ "model-element-uuid": "c9918ba3-dcb3-46e8-870f-316251f459a3-test1",
+ "new-data-del-flag": "X2MIS2y",
+ "cardinality": "u3xIyaL"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "f5a14c3b-6536-4803-9660-4a2f2263dfdd-test1",
+ "element-choice-set-name": "KiVnNej1flt",
+ "cardinality": "AwImrctM5",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "e5e3b7db-7336-498b-8eca-f43f979dda68-test1",
+ "new-data-del-flag": "v3JnIH7JEK",
+ "cardinality": "pzypSipEOA"
+ },
+ {
+ "model-element-uuid": "24426103-516b-4634-83f6-0b02db4d10ed-test1",
+ "new-data-del-flag": "lNx",
+ "cardinality": "OFMiiE1w4K"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "model-constraint-uuid": "310f083b-2d76-4e2d-ab82-b4c6b2a49637-test1",
+ "constrained-element-set-uuid-to-replace": "70UQQ",
+ "constrained-element-sets": {
+ "constrained-element-set": [
+ {
+ "constrained-element-set-uuid": "f6b24791-facd-41d8-8b4e-b76d750ef3e8-test1",
+ "constraint-type": "eBTDI1Xx",
+ "check-type": "uyscxXaNEt",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "efc328ed-3302-4808-b25a-adbbe88af7d9-test1",
+ "element-choice-set-name": "HwpVVTGb6e",
+ "cardinality": "dZ78oR",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "1f20c582-952d-4489-a45b-b7b898062bc4-test1",
+ "new-data-del-flag": "Vq8f3STu8ez",
+ "cardinality": "5lN"
+ },
+ {
+ "model-element-uuid": "77f61b0a-ecf4-43ed-84b8-478372922557-test1",
+ "new-data-del-flag": "OrbNIIvUvTQ",
+ "cardinality": "CwT1hp9uUn"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "7561f91e-5d71-4871-b745-5974a29fa4f0-test1",
+ "element-choice-set-name": "JyMxtTdSzEYI",
+ "cardinality": "CU5",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "7857bb38-b373-4f32-bfed-fb698b38f288-test1",
+ "new-data-del-flag": "qGYsqE",
+ "cardinality": "m1wtW502"
+ },
+ {
+ "model-element-uuid": "27097500-1e6a-4692-bcfc-8c5751094416-test1",
+ "new-data-del-flag": "e3LD9ESy1h2we",
+ "cardinality": "a0jEiwQq"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "constrained-element-set-uuid": "a63f212b-0608-4676-a801-eae9704ca6f8-test1",
+ "constraint-type": "1s642QAY3emE",
+ "check-type": "3sR23Vt",
+ "element-choice-sets": {
+ "element-choice-set": [
+ {
+ "element-choice-set-uuid": "e6f1f3eb-61c5-4e00-877b-253d41dc8bc1-test1",
+ "element-choice-set-name": "EBhZUZSbs",
+ "cardinality": "1LrK8RM4o33LD",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "323c6b90-7aba-41ad-8313-5a4a2b2c56ae-test1",
+ "new-data-del-flag": "R3oKjC8hz87",
+ "cardinality": "LT8Phj"
+ },
+ {
+ "model-element-uuid": "6a4f5cbe-6251-402e-aa0c-d42284acf4f3-test1",
+ "new-data-del-flag": "XeIPIYLqyIL",
+ "cardinality": "pGK"
+ }
+ ]
+ }
+ },
+ {
+ "element-choice-set-uuid": "4937bd81-08f1-4cb7-b3bd-9c9db142a791-test1",
+ "element-choice-set-name": "VXcx",
+ "cardinality": "hIKH",
+ "model-elements": {
+ "model-element": [
+ {
+ "model-element-uuid": "db4ddcd0-6a57-47af-b72d-f10e806bd779-test1",
+ "new-data-del-flag": "2lsYwLYukGh43",
+ "cardinality": "zhcfiBQ"
+ },
+ {
+ "model-element-uuid": "7f0823ec-87f7-4f0a-b6ed-d19571917f3d-test1",
+ "new-data-del-flag": "8xUASuYyIym",
+ "cardinality": "ktmQThTtgu"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "metadata": {
+ "metadatum": [
+ {
+ "metaname": "a4f78e88-e09f-4ca1-b26a-093141044aea-test1",
+ "metaval": "kfsTQsxZk"
+ },
+ {
+ "metaname": "1d153c8b-ba38-4566-876b-53795a71b8f9-test1",
+ "metaval": "xr0Z"
+ }
+ ]
+ }
+ }
+ ]
+ }
+}
diff --git a/aai-core/src/test/resources/payloads/resource/vip-ipv4-address-list.json b/aai-core/src/test/resources/payloads/resource/vip-ipv4-address-list.json
new file mode 100644
index 00000000..4978d2af
--- /dev/null
+++ b/aai-core/src/test/resources/payloads/resource/vip-ipv4-address-list.json
@@ -0,0 +1,6 @@
+{
+ "vip-ipv4-address": "vip-ipv4-address-list-1",
+ "vip-ipv4-prefix-length": 3333,
+ "vlan-id-inner": 3333,
+ "vlan-id-outer": 3333
+}
diff --git a/aai-core/src/test/resources/payloads/resource/vnf.json b/aai-core/src/test/resources/payloads/resource/vnf.json
new file mode 100644
index 00000000..e3e7a35f
--- /dev/null
+++ b/aai-core/src/test/resources/payloads/resource/vnf.json
@@ -0,0 +1,4 @@
+{
+ "vnf-id":"vnf1",
+ "vnf-type":"someval"
+}
diff --git a/aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeIngestor.java b/aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeIngestor.java
index dfcd0db3..c2c58d5f 100644
--- a/aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeIngestor.java
+++ b/aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeIngestor.java
@@ -1,4 +1,4 @@
-/**
+/**
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
@@ -20,11 +20,16 @@
package org.onap.aai.edges;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.onap.aai.edges.enums.DirectionNotation;
import org.onap.aai.edges.enums.EdgeField;
@@ -34,6 +39,8 @@ import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException;
import org.onap.aai.setup.ConfigTranslator;
import org.onap.aai.setup.SchemaVersion;
import org.onap.aai.setup.SchemaVersions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -51,15 +58,25 @@ import static com.jayway.jsonpath.Criteria.where;
*/
@Component
public class EdgeIngestor {
- private Map<SchemaVersion, List<DocumentContext>> versionJsonFilesMap;
+
+ private static final Logger LOG = LoggerFactory.getLogger(EdgeIngestor.class);
+
+ private Map<SchemaVersion, List<DocumentContext>> versionJsonFilesMap;
private static final String READ_START = "$.rules.[?]";
private static final String READ_ALL_START = "$.rules.*";
private SchemaVersions schemaVersions;
+
+ private Set<String> multipleLabelKeys;
+
+ private final LoadingCache<SchemaFilter,Multimap<String,EdgeRule>> cacheFilterStore;
+
+ private final LoadingCache<String, String[]> cousinLabelStore;
+
//-----ingest-----//
/**
* Instantiates the EdgeIngestor bean.
- *
+ *
* @param translator - ConfigTranslator autowired in by Spring framework which
* contains the configuration information needed to ingest the desired files.
*/
@@ -69,20 +86,41 @@ public class EdgeIngestor {
JsonIngestor ji = new JsonIngestor();
this.schemaVersions = schemaVersions;
versionJsonFilesMap = ji.ingest(filesToIngest);
+ this.cacheFilterStore = CacheBuilder.newBuilder()
+ .maximumSize(2000)
+ .build(
+ new CacheLoader<SchemaFilter, Multimap<String, EdgeRule>>() {
+ @Override
+ public Multimap<String, EdgeRule> load(SchemaFilter key) {
+ return extractRules(key);
+ }
+ }
+ );
+
+ this.cousinLabelStore = CacheBuilder.newBuilder()
+ .maximumSize(50)
+ .build(
+ new CacheLoader<String, String[]>() {
+ @Override
+ public String[] load(String key) throws Exception {
+ return retrieveCousinLabels(key);
+ }
+ }
+ );
}
-
+
//-----methods for getting rule info-----//
-
+
/**
* Gets list of all edge rules defined in the latest version's schema
- *
+ *
* @return Multimap<String, EdgeRule> of node names keys to the EdgeRules associated with those types
- * where the key takes the form of
+ * where the key takes the form of
* {alphabetically first nodetype}|{alphabetically second nodetype}. Map will be empty if
* no rules are found.
* ex: buildAlphabetizedKey("l-interface", "logical-link") -> "l-interface|logical-link"
* buildAlphabetizedKey("logical-link", "l-interface") -> "l-interface|logical-link"
- *
+ *
* This is alphabetical order to normalize the keys, as sometimes there will be multiple
* rules for a pair of node types but the from/to value in the json is flipped for some of them.
* @throws EdgeRuleNotFoundException if none found
@@ -90,17 +128,47 @@ public class EdgeIngestor {
public Multimap<String, EdgeRule> getAllCurrentRules() throws EdgeRuleNotFoundException {
return getAllRules(schemaVersions.getDefaultVersion());
}
-
+
+ /**
+ * Retrieves all the nodes that contain multiple edge labels
+ *
+ * A lazy instantiation to retrieve all this info on first call
+ *
+ * @return a set containing a list of strings where each string is
+ * concatenated by a pipe (|) character such as aNodeType|bNodeType
+ */
+ public Set<String> getMultipleLabelKeys(){
+
+ if(multipleLabelKeys == null){
+ multipleLabelKeys = new HashSet<>();
+ try {
+ final Multimap<String, EdgeRule> edges = this.getAllCurrentRules();
+ if(edges == null || edges.isEmpty()){
+ LOG.warn("Unable to find any edge rules for the latest version");
+ }
+ edges.keySet().forEach((key) -> {
+ Collection<EdgeRule> rules = edges.get(key);
+ if(rules.size() > 1){
+ multipleLabelKeys.add(key);
+ }
+ });
+ } catch (EdgeRuleNotFoundException e) {
+ LOG.info("For the latest schema version, unable to find any edges with multiple keys");
+ }
+ }
+
+ return multipleLabelKeys;
+ }
/**
* Gets list of all edge rules defined in the given version's schema
- *
+ *
* @return Multimap<String, EdgeRule> of node names keys to the EdgeRules associated with those types
- * where the key takes the form of
+ * where the key takes the form of
* {alphabetically first nodetype}|{alphabetically second nodetype}. Map will be empty if
* no rules are found.
* ex: buildAlphabetizedKey("l-interface", "logical-link") -> "l-interface|logical-link"
* buildAlphabetizedKey("logical-link", "l-interface") -> "l-interface|logical-link"
- *
+ *
* This is alphabetical order to normalize the keys, as sometimes there will be multiple
* rules for a pair of node types but the from/to value in the json is flipped for some of them.
* @throws EdgeRuleNotFoundException if none found
@@ -113,19 +181,19 @@ public class EdgeIngestor {
return found;
}
}
-
+
/**
* Finds the rules (if any) matching the given query criteria. If none, the returned Multimap
* will be empty.
- *
+ *
* @param q - EdgeRuleQuery with filter criteria set
- *
- * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
+ *
+ * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
* {alphabetically first nodetype}|{alphabetically second nodetype}. Map will be empty if
* no rules are found.
* ex: buildAlphabetizedKey("l-interface", "logical-link") -> "l-interface|logical-link"
* buildAlphabetizedKey("logical-link", "l-interface") -> "l-interface|logical-link"
- *
+ *
* This is alphabetical order to normalize the keys, as sometimes there will be multiple
* rules for a pair of node types but the from/to value in the json is flipped for some of them.
* @throws EdgeRuleNotFoundException if none found
@@ -140,36 +208,40 @@ public class EdgeIngestor {
if (found.isEmpty()) {
throw new EdgeRuleNotFoundException("No rules found for " + q.toString());
} else {
- for (EdgeRule rule : found.values()) {
- if (!q.getFromType().equals(rule.getFrom())) {
- /* To maintain backwards compatibility with old EdgeRules API,
- * where the direction of the returned EdgeRule would be
- * flipped (if necessary) to match the directionality of
- * the input params.
- * ie, If the rule is from=A,to=B,direction=OUT,
- * if the user asked (A,B) the direction would be OUT,
- * if they asked (B,A), it would be IN to match.
- */
- rule.flipDirection();
- }
- }
- return found;
+ Multimap<String, EdgeRule> copy = ArrayListMultimap.create();
+ found.entries().stream().forEach((entry) -> {
+ EdgeRule rule = new EdgeRule(entry.getValue());
+ if(!q.getFromType().equals(rule.getFrom())){
+ /* To maintain backwards compatibility with old EdgeRules API,
+ * where the direction of the returned EdgeRule would be
+ * flipped (if necessary) to match the directionality of
+ * the input params.
+ * ie, If the rule is from=A,to=B,direction=OUT,
+ * if the user asked (A,B) the direction would be OUT,
+ * if they asked (B,A), it would be IN to match.
+ */
+ rule.flipDirection();
+ }
+ copy.put(entry.getKey(), rule);
+ });
+
+ return copy;
}
}
-
+
/**
* Gets the rule satisfying the given filter criteria. If there are more than one
- * that match, return the default rule. If there is no clear default to return, or
+ * that match, return the default rule. If there is no clear default to return, or
* no rules match at all, error.
- *
+ *
* @param q - EdgeRuleQuery with filter criteria set
* @return EdgeRule satisfying given criteria
* @throws EdgeRuleNotFoundException if none found that match
* @throws AmbiguousRuleChoiceException if multiple match but no way to choice one from them
- * Specifically, if multiple node type pairs come back (ie bar|foo and asdf|foo,
+ * Specifically, if multiple node type pairs come back (ie bar|foo and asdf|foo,
* no way to know which is appropriate over the others),
* or if there is a mix of Tree and Cousin edges because again there is no way to
- * know which is "defaulter" than the other.
+ * know which is "defaulter" than the other.
* The default property only clarifies among multiple cousin edges of the same node pair,
* ex: which l-interface|logical-link rule to default to.
*/
@@ -184,7 +256,7 @@ public class EdgeIngestor {
if (found.isEmpty()) {
throw new EdgeRuleNotFoundException("No rule found for " + q.toString() + ".");
}
-
+
EdgeRule rule = null;
if (found.keys().size() == 1) { //only one found, cool we're done
for (Entry<String, EdgeRule> e : found.entries()) {
@@ -193,10 +265,12 @@ public class EdgeIngestor {
} else {
rule = getDefaultRule(found);
}
-
+
+
if (rule == null) { //should never get here though
throw new EdgeRuleNotFoundException("No rule found for " + q.toString() + ".");
} else {
+ rule = new EdgeRule(rule);
if (!q.getFromType().equals(rule.getFrom())) {
/* To maintain backwards compatibility with old EdgeRules API,
* where the direction of the returned EdgeRule would be
@@ -211,7 +285,9 @@ public class EdgeIngestor {
return rule;
}
}
-
+
+
+
private EdgeRule getDefaultRule(Multimap<String, EdgeRule> found) throws AmbiguousRuleChoiceException {
if (found.keySet().size() > 1) { //ie multiple node pairs (a|c and b|c not just all a|c) case
StringBuilder sb = new StringBuilder();
@@ -220,7 +296,7 @@ public class EdgeIngestor {
}
throw new AmbiguousRuleChoiceException("No way to select single rule from these pairs: " + sb.toString() + ".");
}
-
+
int defaultCount = 0;
EdgeRule defRule = null;
for (Entry<String, EdgeRule> e : found.entries()) {
@@ -235,13 +311,13 @@ public class EdgeIngestor {
} else if (defaultCount == 0) {
throw new AmbiguousRuleChoiceException("No default found.");
}
-
+
return defRule;
}
-
+
/**
* Checks if there exists any rule that satisfies the given filter criteria.
- *
+ *
* @param q - EdgeRuleQuery with filter criteria set
* @return boolean
*/
@@ -252,42 +328,59 @@ public class EdgeIngestor {
return !extractRules(q.getFilter(), schemaVersions.getDefaultVersion()).isEmpty();
}
}
-
+
/**
* Gets all cousin rules for the given node type in the latest schema version.
- *
+ *
* @param nodeType
- * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
+ * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
* {alphabetically first nodetype}|{alphabetically second nodetype}. Map will be empty if
* no rules are found.
* ex: buildAlphabetizedKey("l-interface", "logical-link") -> "l-interface|logical-link"
* buildAlphabetizedKey("logical-link", "l-interface") -> "l-interface|logical-link"
- *
+ *
* This is alphabetical order to normalize the keys, as sometimes there will be multiple
* rules for a pair of node types but the from/to value in the json is flipped for some of them.
*/
public Multimap<String, EdgeRule> getCousinRules(String nodeType) {
return getCousinRules(nodeType, schemaVersions.getDefaultVersion()); //default to latest
}
-
+
+
+ public String[] retrieveCousinLabels(String nodeType){
+
+ Multimap<String, EdgeRule> cousinRules = getCousinRules(nodeType);
+ String[] cousinLabels = new String[cousinRules.size()];
+
+ return cousinRules.entries()
+ .stream()
+ .map((entry) -> entry.getValue().getLabel())
+ .collect(Collectors.toList())
+ .toArray(cousinLabels);
+ }
+
+ public String[] retrieveCachedCousinLabels(String nodeType) throws ExecutionException {
+ return cousinLabelStore.get(nodeType);
+ }
+
/**
* Gets all cousin rules for the given node type in the given schema version.
- *
+ *
* @param nodeType
* @param v - the version of the edge rules to query
- * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
+ * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
* {alphabetically first nodetype}|{alphabetically second nodetype}. Map will be empty if
* no rules are found.
* ex: buildAlphabetizedKey("l-interface", "logical-link") -> "l-interface|logical-link"
* buildAlphabetizedKey("logical-link", "l-interface") -> "l-interface|logical-link"
- *
+ *
* This is alphabetical order to normalize the keys, as sometimes there will be multiple
- * rules for a pair of node types but the from/to value in the json is flipped for some of them.
+ * rules for a pair of node types but the from/to value in the json is flipped for some of them.
*/
public Multimap<String, EdgeRule> getCousinRules(String nodeType, SchemaVersion v) {
return extractRules(new EdgeRuleQuery.Builder(nodeType).edgeType(EdgeType.COUSIN).build().getFilter(), v);
}
-
+
/**
* Returns if the given node type has any cousin relationships in the current version.
* @param nodeType
@@ -296,7 +389,7 @@ public class EdgeIngestor {
public boolean hasCousinRule(String nodeType) {
return hasCousinRule(nodeType, schemaVersions.getDefaultVersion());
}
-
+
/**
* Returns if the given node type has any cousin relationships in the given version.
* @param nodeType
@@ -305,45 +398,45 @@ public class EdgeIngestor {
public boolean hasCousinRule(String nodeType, SchemaVersion v) {
return !getCousinRules(nodeType, v).isEmpty();
}
-
+
/**
* Gets all rules where "{given nodeType} contains {otherType}" in the latest schema version.
- *
+ *
* @param nodeType - node type that is the container in the returned relationships
- * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
+ * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
* {alphabetically first nodetype}|{alphabetically second nodetype}. Map will be empty if
* no rules are found.
* ex: buildAlphabetizedKey("l-interface", "logical-link") -> "l-interface|logical-link"
* buildAlphabetizedKey("logical-link", "l-interface") -> "l-interface|logical-link"
- *
+ *
* This is alphabetical order to normalize the keys, as sometimes there will be multiple
- * rules for a pair of node types but the from/to value in the json is flipped for some of them.
+ * rules for a pair of node types but the from/to value in the json is flipped for some of them.
*/
public Multimap<String, EdgeRule> getChildRules(String nodeType) {
return getChildRules(nodeType, schemaVersions.getDefaultVersion());
}
-
+
/**
* Gets all rules where "{given nodeType} contains {otherType}" in the given schema version.
- *
+ *
* @param nodeType - node type that is the container in the returned relationships
- * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
+ * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
* {alphabetically first nodetype}|{alphabetically second nodetype}. Map will be empty if
* no rules are found.
* ex: buildAlphabetizedKey("l-interface", "logical-link") -> "l-interface|logical-link"
* buildAlphabetizedKey("logical-link", "l-interface") -> "l-interface|logical-link"
- *
+ *
* This is alphabetical order to normalize the keys, as sometimes there will be multiple
- * rules for a pair of node types but the from/to value in the json is flipped for some of them.
+ * rules for a pair of node types but the from/to value in the json is flipped for some of them.
*/
public Multimap<String, EdgeRule> getChildRules(String nodeType, SchemaVersion v) {
Filter from = assembleFilterSegments(where(EdgeField.FROM.toString()).is(nodeType), getSameDirectionContainmentCriteria());
Filter to = assembleFilterSegments(where(EdgeField.TO.toString()).is(nodeType), getOppositeDirectionContainmentCriteria());
Filter total = from.or(to);
-
+
return extractRules(total, v);
}
-
+
/**
* Returns if the given node type has any child relationships (ie it contains another node type) in the current version.
* @param nodeType
@@ -352,7 +445,7 @@ public class EdgeIngestor {
public boolean hasChildRule(String nodeType) {
return hasChildRule(nodeType, schemaVersions.getDefaultVersion());
}
-
+
/**
* Returns if the given node type has any child relationships (ie it contains another node type) in the given version.
* @param nodeType
@@ -361,45 +454,45 @@ public class EdgeIngestor {
public boolean hasChildRule(String nodeType, SchemaVersion v) {
return !getChildRules(nodeType, v).isEmpty();
}
-
+
/**
* Gets all rules where "{given nodeType} is contained by {otherType}" in the latest schema version.
- *
+ *
* @param nodeType - node type that is the containee in the returned relationships
- * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
+ * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
* {alphabetically first nodetype}|{alphabetically second nodetype}. Map will be empty if
* no rules are found.
* ex: buildAlphabetizedKey("l-interface", "logical-link") -> "l-interface|logical-link"
* buildAlphabetizedKey("logical-link", "l-interface") -> "l-interface|logical-link"
- *
+ *
* This is alphabetical order to normalize the keys, as sometimes there will be multiple
* rules for a pair of node types but the from/to value in the json is flipped for some of them.
*/
public Multimap<String, EdgeRule> getParentRules(String nodeType) {
return getParentRules(nodeType, schemaVersions.getDefaultVersion());
}
-
+
/**
* Gets all rules where "{given nodeType} is contained by {otherType}" in the given schema version.
- *
+ *
* @param nodeType - node type that is the containee in the returned relationships
- * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
+ * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
* {alphabetically first nodetype}|{alphabetically second nodetype}. Map will be empty if
* no rules are found.
* ex: buildAlphabetizedKey("l-interface", "logical-link") -> "l-interface|logical-link"
* buildAlphabetizedKey("logical-link", "l-interface") -> "l-interface|logical-link"
- *
+ *
* This is alphabetical order to normalize the keys, as sometimes there will be multiple
- * rules for a pair of node types but the from/to value in the json is flipped for some of them.
+ * rules for a pair of node types but the from/to value in the json is flipped for some of them.
*/
public Multimap<String, EdgeRule> getParentRules(String nodeType, SchemaVersion v) {
Filter from = assembleFilterSegments(where(EdgeField.FROM.toString()).is(nodeType), getOppositeDirectionContainmentCriteria());
Filter to = assembleFilterSegments(where(EdgeField.TO.toString()).is(nodeType), getSameDirectionContainmentCriteria());
Filter total = from.or(to);
-
+
return extractRules(total, v);
}
-
+
/**
* Returns if the given node type has any parent relationships (ie it is contained by another node type) in the current version.
* @param nodeType
@@ -408,7 +501,7 @@ public class EdgeIngestor {
public boolean hasParentRule(String nodeType) {
return hasParentRule(nodeType, schemaVersions.getDefaultVersion());
}
-
+
/**
* Returns if the given node type has any parent relationships (ie it is contained by another node type) in the given version.
* @param nodeType
@@ -417,47 +510,57 @@ public class EdgeIngestor {
public boolean hasParentRule(String nodeType, SchemaVersion v) {
return !getParentRules(nodeType, v).isEmpty();
}
-
+
/**
* Applies the given filter to the DocumentContext(s) for the given version to extract
* edge rules, and converts this extracted information into the Multimap form
- *
+ *
* @param filter - JsonPath filter to read the DocumentContexts with. May be null
* to denote no filter, ie get all.
* @param v - The schema version to extract from
- * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
+ * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
* {alphabetically first nodetype}|{alphabetically second nodetype}. Map will be empty if
* no rules are found.
* ex: buildAlphabetizedKey("l-interface", "logical-link") -> "l-interface|logical-link"
* buildAlphabetizedKey("logical-link", "l-interface") -> "l-interface|logical-link"
- *
+ *
* This is alphabetical order to normalize the keys, as sometimes there will be multiple
- * rules for a pair of node types but the from/to value in the json is flipped for some of them.
+ * rules for a pair of node types but the from/to value in the json is flipped for some of them.
*/
private Multimap<String, EdgeRule> extractRules(Filter filter, SchemaVersion v) {
- List<Map<String, String>> foundRules = new ArrayList<>();
- List<DocumentContext> docs = versionJsonFilesMap.get(v);
- if (docs != null) {
- for (DocumentContext doc : docs) {
- if (filter == null) {
- foundRules.addAll(doc.read(READ_ALL_START));
- } else {
- foundRules.addAll(doc.read(READ_START, filter));
- }
- }
- }
-
- return convertToEdgeRules(foundRules);
- }
-
+ SchemaFilter schemaFilter = new SchemaFilter(filter, v);
+ try {
+ return cacheFilterStore.get(schemaFilter);
+ } catch (ExecutionException e) {
+ LOG.info("Encountered exception during the retrieval of the rules");
+ return ArrayListMultimap.create();
+ }
+ }
+
+ public Multimap<String, EdgeRule> extractRules(SchemaFilter schemaFilter){
+ List<Map<String, String>> foundRules = new ArrayList<>();
+ List<DocumentContext> docs = versionJsonFilesMap.get(schemaFilter.getSchemaVersion());
+ if (docs != null) {
+ for (DocumentContext doc : docs) {
+ if (schemaFilter.getFilter() == null) {
+ foundRules.addAll(doc.read(READ_ALL_START));
+ } else {
+ foundRules.addAll(doc.read(READ_START, Filter.parse(schemaFilter.getFilter())));
+ }
+ }
+ }
+
+ return convertToEdgeRules(foundRules);
+ }
+
//-----filter building helpers-----//
/**
* ANDs together the given start criteria with each criteria in the pieces list, and
* then ORs together these segments into one filter.
- *
+ *
* JsonPath doesn't have an OR method on Criteria, only on Filters, so assembling
* a complete filter requires this sort of roundabout construction.
- *
+ *
* @param start - Criteria of the form where(from/to).is(nodeType)
* (ie the start of any A&AI edge rule query)
* @param pieces - Other Criteria to be applied
@@ -474,91 +577,91 @@ public class EdgeIngestor {
}
return assembled;
}
-
+
/**
* Builds the sub-Criteria for a containment edge rule query where the direction
* and containment fields must match.
- *
+ *
* Used for getChildRules() where the container node type is in the "from" position and
* for getParentRules() where the containee type is in the "to" position.
- *
+ *
* @return List<Criteria> covering property permutations defined with either notation or explicit direction
*/
private List<Criteria> getSameDirectionContainmentCriteria() {
List<Criteria> crits = new ArrayList<>();
-
+
crits.add(where(EdgeField.CONTAINS.toString()).is(DirectionNotation.DIRECTION.toString()));
-
+
crits.add(where(EdgeField.DIRECTION.toString()).is(Direction.OUT.toString())
.and(EdgeField.CONTAINS.toString()).is(Direction.OUT.toString()));
-
+
crits.add(where(EdgeField.DIRECTION.toString()).is(Direction.IN.toString())
.and(EdgeField.CONTAINS.toString()).is(Direction.IN.toString()));
-
+
return crits;
}
-
+
/**
* Builds the sub-Criteria for a containment edge rule query where the direction
* and containment fields must not match.
- *
+ *
* Used for getChildRules() where the container node type is in the "to" position and
* for getParentRules() where the containee type is in the "from" position.
- *
+ *
* @return List<Criteria> covering property permutations defined with either notation or explicit direction
*/
private List<Criteria> getOppositeDirectionContainmentCriteria() {
List<Criteria> crits = new ArrayList<>();
-
+
crits.add(where(EdgeField.CONTAINS.toString()).is(DirectionNotation.OPPOSITE.toString()));
-
+
crits.add(where(EdgeField.DIRECTION.toString()).is(Direction.OUT.toString())
.and(EdgeField.CONTAINS.toString()).is(Direction.IN.toString()));
-
+
crits.add(where(EdgeField.DIRECTION.toString()).is(Direction.IN.toString())
.and(EdgeField.CONTAINS.toString()).is(Direction.OUT.toString()));
-
+
return crits;
}
-
+
//-----rule packaging helpers-----//
/**
* Converts the raw output from reading the json file to the Multimap<String key, EdgeRule> format
- *
+ *
* @param allFound - raw edge rule output read from json file(s)
* (could be empty if none found)
- * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
+ * @return Multimap<String, EdgeRule> of node names keys to the EdgeRules where the key takes the form of
* {alphabetically first nodetype}|{alphabetically second nodetype}. Will be empty if input
* was empty.
* ex: buildAlphabetizedKey("l-interface", "logical-link") -> "l-interface|logical-link"
* buildAlphabetizedKey("logical-link", "l-interface") -> "l-interface|logical-link"
- *
+ *
* This is alphabetical order to normalize the keys, as sometimes there will be multiple
- * rules for a pair of node types but the from/to value in the json is flipped for some of them.
+ * rules for a pair of node types but the from/to value in the json is flipped for some of them.
*/
private Multimap<String, EdgeRule> convertToEdgeRules(List<Map<String, String>> allFound) {
Multimap<String, EdgeRule> rules = ArrayListMultimap.create();
-
+
TypeAlphabetizer alpher = new TypeAlphabetizer();
-
+
for (Map<String, String> raw : allFound) {
EdgeRule converted = new EdgeRule(raw);
if (converted.getFrom().equals(converted.getTo())) {
- /* the way the code worked in the past was with outs and
- * when we switched it to in the same-node-type to
- * same-node-type parent child edges were failing because all
- * of the calling code would pass the parent as the left argument,
- * so it was either in that method swap the parent/child,
- * flip the edge rule or make all callers swap. the last seemed
- * like a bad idea. and felt like the edge flip was the better
+ /* the way the code worked in the past was with outs and
+ * when we switched it to in the same-node-type to
+ * same-node-type parent child edges were failing because all
+ * of the calling code would pass the parent as the left argument,
+ * so it was either in that method swap the parent/child,
+ * flip the edge rule or make all callers swap. the last seemed
+ * like a bad idea. and felt like the edge flip was the better
* of the remaining 2 */
converted.flipDirection();
}
String alphabetizedKey = alpher.buildAlphabetizedKey(raw.get(EdgeField.FROM.toString()), raw.get(EdgeField.TO.toString()));
rules.put(alphabetizedKey, converted);
}
-
+
return rules;
}
-
+
}
diff --git a/aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeRule.java b/aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeRule.java
index e1cb240e..f914f6cb 100644
--- a/aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeRule.java
+++ b/aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeRule.java
@@ -26,7 +26,9 @@ import org.onap.aai.edges.enums.EdgeField;
import org.onap.aai.edges.enums.EdgeProperty;
import org.onap.aai.edges.enums.MultiplicityRule;
+import java.util.Collections;
import java.util.EnumMap;
+import java.util.HashMap;
import java.util.Map;
/**
@@ -43,16 +45,16 @@ public class EdgeRule {
private String description;
private boolean isPrivateEdge = false;
- /**
+ /**
* Instantiates a new edge rule.
- *
+ *
* @param fieldVals - Map<String, String> where first string is
- * an EdgeField value and second string is the
+ * an EdgeField value and second string is the
* value of that field
*/
public EdgeRule(Map<String, String> fieldVals) {
edgeFields = new EnumMap<>(EdgeProperty.class);
-
+
from = fieldVals.get(EdgeField.FROM.toString());
to = fieldVals.get(EdgeField.TO.toString());
label = fieldVals.get(EdgeField.LABEL.toString());
@@ -63,19 +65,32 @@ public class EdgeRule {
String rawVal = fieldVals.get(prop.toString());
edgeFields.put(prop, convertNotation(direction, rawVal));
}
-
+
isDefaultEdge = Boolean.valueOf(fieldVals.get(EdgeField.DEFAULT.toString()));
-
+
description = fieldVals.get(EdgeField.DESCRIPTION.toString());
if (description == null) { //bc description is optional and not in v12 and earlier
description = "";
}
}
+ // Copy Constructor
+ public EdgeRule(EdgeRule edgeRule){
+ this.from = edgeRule.from;
+ this.to = edgeRule.to;
+ this.label = edgeRule.label;
+ this.direction = Direction.valueOf(edgeRule.direction.toString());
+ this.multiplicityRule = MultiplicityRule.valueOf(edgeRule.multiplicityRule.toString());
+ this.edgeFields = new HashMap<>(edgeRule.edgeFields);
+ this.isDefaultEdge = edgeRule.isDefaultEdge;
+ this.description = edgeRule.description;
+ this.isPrivateEdge = edgeRule.isPrivateEdge;
+ }
+
/**
* Converts whatever string was in the json for an edge property value into
* the appropriate AAIDirection
- *
+ *
* @param Direction dir - the edge direction
* @param String rawVal - property value from the json, may be
* IN, OUT, BOTH, NONE, ${direction}, or !${direction}
@@ -92,7 +107,7 @@ public class EdgeRule {
} else if (AAIDirection.IN.toString().equalsIgnoreCase(rawVal)) {
return AAIDirection.IN;
}
-
+
DirectionNotation rawDN = DirectionNotation.getValue(rawVal);
if (DirectionNotation.DIRECTION.equals(rawDN)) {
return AAIDirection.getValue(dir);
@@ -100,7 +115,7 @@ public class EdgeRule {
return AAIDirection.getValue(dir.opposite());
}
}
-
+
/**
* Gets the name of the node type in the "from" field
* @return String nodetype
@@ -125,7 +140,7 @@ public class EdgeRule {
public String getLabel() {
return label;
}
-
+
/**
* Gets the multiplicity rule.
*
@@ -134,7 +149,7 @@ public class EdgeRule {
public MultiplicityRule getMultiplicityRule() {
return multiplicityRule;
}
-
+
/**
* Gets the edge direction
*
@@ -143,7 +158,7 @@ public class EdgeRule {
public Direction getDirection() {
return direction;
}
-
+
/**
* Gets the value of contains-other-v
*
@@ -152,7 +167,7 @@ public class EdgeRule {
public String getContains() {
return edgeFields.get(EdgeProperty.CONTAINS).toString();
}
-
+
/**
* Gets the value of delete-other-v
*
@@ -161,10 +176,10 @@ public class EdgeRule {
public String getDeleteOtherV() {
return edgeFields.get(EdgeProperty.DELETE_OTHER_V).toString();
}
-
+
/**
* Gets the value of the prevent-delete property
- *
+ *
* @return String prevent-delete property value
*/
public String getPreventDelete() {
@@ -173,13 +188,13 @@ public class EdgeRule {
/**
* Returns if this rule is a default or not
- *
+ *
* @return boolean
*/
public boolean isDefault() {
return isDefaultEdge;
}
-
+
/**
* Gets the description on the edge rule (if there is one)
* @return String description
@@ -187,7 +202,7 @@ public class EdgeRule {
public String getDescription() {
return this.description;
}
-
+
/**
* Flips the direction value
* IN -> OUT
diff --git a/aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeRuleQuery.java b/aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeRuleQuery.java
index 5801e816..58c8c546 100644
--- a/aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeRuleQuery.java
+++ b/aai-schema-ingest/src/main/java/org/onap/aai/edges/EdgeRuleQuery.java
@@ -1,4 +1,4 @@
-/**
+/**
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
@@ -36,6 +36,7 @@ import static com.jayway.jsonpath.Filter.filter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.Optional;
import static com.jayway.jsonpath.Criteria.where;
@@ -90,6 +91,12 @@ public class EdgeRuleQuery {
private String getSecondNodeType() {
return nodeB;
}
+
+ public Builder to(String nodeB){
+ this.nodeB = nodeB;
+ return this;
+ }
+
public Builder toOnly() {
//Allows this to be used with single parameter constructor Builder(String nodeA)
if(StringUtils.isEmpty(this.nodeB) && StringUtils.isNotEmpty(this.nodeA) ) {
@@ -312,6 +319,30 @@ public class EdgeRuleQuery {
}
return sb.toString();
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ EdgeRuleQuery ruleQuery = (EdgeRuleQuery) o;
+ return isPrivate == ruleQuery.isPrivate &&
+ Objects.equals(v, ruleQuery.v) &&
+ Objects.equals(nodeA, ruleQuery.nodeA) &&
+ Objects.equals(nodeB, ruleQuery.nodeB) &&
+ Objects.equals(label, ruleQuery.label) &&
+ direction == ruleQuery.direction &&
+ type == ruleQuery.type;
+ }
+
+ @Override
+ public int hashCode() {
+ if(v.isPresent()){
+ return Objects.hash(v.get(), nodeA, nodeB, label, direction, type, isPrivate);
+ } else {
+ return Objects.hash(nodeA, nodeB, label, direction, type, isPrivate);
+ }
+ }
+
}
diff --git a/aai-schema-ingest/src/main/java/org/onap/aai/edges/SchemaFilter.java b/aai-schema-ingest/src/main/java/org/onap/aai/edges/SchemaFilter.java
new file mode 100644
index 00000000..792e3c51
--- /dev/null
+++ b/aai-schema-ingest/src/main/java/org/onap/aai/edges/SchemaFilter.java
@@ -0,0 +1,69 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-18 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.edges;
+
+import com.jayway.jsonpath.Filter;
+import org.onap.aai.setup.SchemaVersion;
+
+import java.util.Objects;
+
+public class SchemaFilter {
+
+ private String filter;
+
+ private SchemaVersion schemaVersion;
+
+ public SchemaFilter(Filter filter, SchemaVersion schemaVersion){
+ if(filter != null){
+ this.filter = filter.toString();
+ }
+ this.schemaVersion = schemaVersion;
+ }
+
+ public SchemaVersion getSchemaVersion() {
+ return schemaVersion;
+ }
+
+ public String getFilter() {
+ return filter;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SchemaFilter that = (SchemaFilter) o;
+ return Objects.equals(filter, that.filter) &&
+ Objects.equals(schemaVersion, that.schemaVersion);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(filter, schemaVersion);
+ }
+
+ @Override
+ public String toString() {
+ return "SchemaFilter{" +
+ "filter='" + filter + '\'' +
+ ", schemaVersion=" + schemaVersion +
+ '}';
+ }
+}
diff --git a/aai-schema-ingest/src/main/java/org/onap/aai/edges/exceptions/AmbiguousRuleChoiceException.java b/aai-schema-ingest/src/main/java/org/onap/aai/edges/exceptions/AmbiguousRuleChoiceException.java
index b218cecd..3ddced9a 100644
--- a/aai-schema-ingest/src/main/java/org/onap/aai/edges/exceptions/AmbiguousRuleChoiceException.java
+++ b/aai-schema-ingest/src/main/java/org/onap/aai/edges/exceptions/AmbiguousRuleChoiceException.java
@@ -1,4 +1,4 @@
-/**
+/**
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
@@ -24,4 +24,8 @@ public class AmbiguousRuleChoiceException extends Exception {
public AmbiguousRuleChoiceException(String msg) {
super(msg);
}
+
+ public AmbiguousRuleChoiceException(Throwable throwable){
+ super(throwable);
+ }
}
diff --git a/aai-schema-ingest/src/main/java/org/onap/aai/edges/exceptions/EdgeRuleNotFoundException.java b/aai-schema-ingest/src/main/java/org/onap/aai/edges/exceptions/EdgeRuleNotFoundException.java
index 4d339de2..de022bc5 100644
--- a/aai-schema-ingest/src/main/java/org/onap/aai/edges/exceptions/EdgeRuleNotFoundException.java
+++ b/aai-schema-ingest/src/main/java/org/onap/aai/edges/exceptions/EdgeRuleNotFoundException.java
@@ -1,4 +1,4 @@
-/**
+/**
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
@@ -24,4 +24,8 @@ public class EdgeRuleNotFoundException extends Exception {
public EdgeRuleNotFoundException(String msg) {
super(msg);
}
+
+ public EdgeRuleNotFoundException(Throwable throwable){
+ super(throwable);
+ }
}
diff --git a/aai-schema/src/main/resources/onap/oxm/v15/aai_oxm_v15.xml b/aai-schema/src/main/resources/onap/oxm/v15/aai_oxm_v15.xml
index f068b009..ce7f2d52 100644
--- a/aai-schema/src/main/resources/onap/oxm/v15/aai_oxm_v15.xml
+++ b/aai-schema/src/main/resources/onap/oxm/v15/aai_oxm_v15.xml
@@ -5704,8 +5704,8 @@
<java-type name="ReservedPropNames">
<xml-properties>
<xml-property name="description" value="Internal map to define some reserved properties of a vertex"/>
- <xml-property name="uniqueProps" value="aai-unique-key"/>
- <xml-property name="indexedProps" value="aai-unique-key,source-of-truth,aai-node-type,aai-uri"/>
+ <xml-property name="uniqueProps" value="aai-unique-key,aai-uri,aai-uuid"/>
+ <xml-property name="indexedProps" value="aai-unique-key,source-of-truth,aai-node-type,aai-uri,aai-uuid"/>
</xml-properties>
<xml-root-element name="reserved-prop-names"/>
<java-attributes>