aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaMont, William (wl2432) <wl2432@us.att.com>2018-08-31 10:56:17 -0400
committerLaMont, William (wl2432) <wl2432@us.att.com>2018-08-31 11:10:32 -0400
commit571d6f65cf5e0e5334956dbe11730fd47820b947 (patch)
treeca23e0f64ca2968b4a933cb6a0bb0b4781bc24e8
parent6ed92ea7526678f245a9123d2ee97a6a9e2c3bf1 (diff)
initial code for cacher
Issue-ID: AAI-1473 Change-Id: I8babe91e79f5c1e6e97b0f5b6dc827b8c5caec80 Signed-off-by: LaMont, William (wl2432) <wl2432@att.com>
-rw-r--r--.gitignore10
-rw-r--r--LICENSE.TXT17
-rw-r--r--README.md38
-rw-r--r--pom.xml691
-rw-r--r--set-debug-port.bat1
-rw-r--r--src/main/assembly/descriptor.xml32
-rw-r--r--src/main/docker/Dockerfile22
-rw-r--r--src/main/docker/aai.sh44
-rw-r--r--src/main/docker/docker-entrypoint.sh125
-rw-r--r--src/main/java/org/onap/aai/cacher/Application.java85
-rw-r--r--src/main/java/org/onap/aai/cacher/Profiles.java31
-rw-r--r--src/main/java/org/onap/aai/cacher/common/CacheKeyConfig.java62
-rw-r--r--src/main/java/org/onap/aai/cacher/common/MongoConfig.java104
-rw-r--r--src/main/java/org/onap/aai/cacher/common/MongoHelperSingleton.java312
-rw-r--r--src/main/java/org/onap/aai/cacher/config/JettyPasswordDecoder.java33
-rw-r--r--src/main/java/org/onap/aai/cacher/config/PasswordDecoder.java25
-rw-r--r--src/main/java/org/onap/aai/cacher/config/PropertyPasswordConfiguration.java80
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessor.java175
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIEventConsumer.java34
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIParentEventConsumer.java237
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/ClientConsumer.java31
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapConsumerSingleton.java77
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapProcessor.java32
-rw-r--r--src/main/java/org/onap/aai/cacher/dmaap/consumer/RestDmaapClientConsumer.java80
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactory.java35
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactoryConfiguration.java36
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterService.java43
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/strategy/AAIResourceGetAllPayloadPrinterStrategy.java49
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/strategy/NonePayloadPrinterStrategy.java42
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterStrategy.java28
-rw-r--r--src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterType.java46
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/AAIResourcesUriTemplates.java208
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactory.java35
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactoryConfiguration.java36
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserService.java71
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategy.java470
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceGetAllPayloadParserStrategy.java85
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/strategy/NonePayloadParserStrategy.java48
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserStrategy.java31
-rw-r--r--src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserType.java45
-rw-r--r--src/main/java/org/onap/aai/cacher/model/CacheEntry.java206
-rw-r--r--src/main/java/org/onap/aai/cacher/model/CacheKey.java220
-rw-r--r--src/main/java/org/onap/aai/cacher/model/DBAction.java24
-rw-r--r--src/main/java/org/onap/aai/cacher/service/AuthorizationService.java109
-rw-r--r--src/main/java/org/onap/aai/cacher/service/helper/CacheHelperService.java545
-rw-r--r--src/main/java/org/onap/aai/cacher/service/helper/RestClientHelperService.java76
-rw-r--r--src/main/java/org/onap/aai/cacher/service/rest/CacheInteractionService.java88
-rw-r--r--src/main/java/org/onap/aai/cacher/service/rest/CacheKeyService.java200
-rw-r--r--src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidation.java66
-rw-r--r--src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidationType.java26
-rw-r--r--src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTaskConfig.java74
-rw-r--r--src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTasks.java148
-rw-r--r--src/main/java/org/onap/aai/cacher/util/AAIConstants.java51
-rw-r--r--src/main/java/org/onap/aai/cacher/util/RestClient.java157
-rw-r--r--src/main/java/org/onap/aai/cacher/web/JerseyConfiguration.java132
-rw-r--r--src/main/java/org/onap/aai/cacher/web/LocalHostAccessLog.java58
-rw-r--r--src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java41
-rw-r--r--src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java40
-rw-r--r--src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java40
-rw-r--r--src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java118
-rw-r--r--src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java38
-rw-r--r--src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java87
-rw-r--r--src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java79
-rw-r--r--src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java60
-rw-r--r--src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java131
-rw-r--r--src/main/java/org/onap/aai/interceptors/pre/SetLoggingContext.java70
-rw-r--r--src/main/jenkins/Jenkinsfile31
-rw-r--r--src/main/jenkins/build.groovy14
-rw-r--r--src/main/jenkins/checkout.groovy14
-rw-r--r--src/main/jenkins/deploy.groovy15
-rw-r--r--src/main/resources/application.properties57
-rw-r--r--src/main/resources/etc/appprops/aai-resources-uri-templates.properties95
-rw-r--r--src/main/resources/etc/appprops/aaiDmaaPEventConsumer.properties23
-rw-r--r--src/main/resources/etc/appprops/aaiconfig.properties5
-rw-r--r--src/main/resources/etc/appprops/error.properties173
-rw-r--r--src/main/resources/etc/appprops/initialcachekeyconfig.json41
-rw-r--r--src/main/resources/etc/appprops/preferredRoute.txt1
-rw-r--r--src/main/resources/etc/auth/aai-client-cert.p12bin0 -> 7954 bytes
-rw-r--r--src/main/resources/etc/auth/aai_keystorebin0 -> 4928 bytes
-rw-r--r--src/main/resources/etc/auth/realm.properties12
-rw-r--r--src/main/resources/localhost-access-logback.xml62
-rw-r--r--src/main/resources/logback.xml243
-rw-r--r--src/test/java/org/onap/aai/cacher/common/MongoHelperSingletonNoFakeTest.java490
-rw-r--r--src/test/java/org/onap/aai/cacher/common/MongoHelperSingletonTest.java417
-rw-r--r--src/test/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessorScenariosTest.java496
-rw-r--r--src/test/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessorTest.java80
-rw-r--r--src/test/java/org/onap/aai/cacher/dmaap/consumer/AAIEventConsumerTest.java185
-rw-r--r--src/test/java/org/onap/aai/cacher/dmaap/consumer/DmaapConsumerSingletonTest.java39
-rw-r--r--src/test/java/org/onap/aai/cacher/egestion/printer/EgestionTestComponent.java35
-rw-r--r--src/test/java/org/onap/aai/cacher/injestion/parser/AAIResourcesUriTemplatesTest.java137
-rw-r--r--src/test/java/org/onap/aai/cacher/injestion/parser/InjestionTestComponent.java35
-rw-r--r--src/test/java/org/onap/aai/cacher/injestion/parser/PayloadParserServiceTest.java148
-rw-r--r--src/test/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategyTest.java429
-rw-r--r--src/test/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategyTestConstants.java372
-rw-r--r--src/test/java/org/onap/aai/cacher/model/CacheKeyTest.java169
-rw-r--r--src/test/java/org/onap/aai/cacher/service/helper/CacheHelperServiceScenariosTest.java232
-rw-r--r--src/test/java/org/onap/aai/cacher/service/helper/CacheHelperServiceTest.java88
-rw-r--r--src/test/java/org/onap/aai/cacher/service/helper/CrudOperationsTest.java409
-rw-r--r--src/test/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidationTest.java90
-rw-r--r--src/test/resources/application-test.properties14
-rw-r--r--src/test/resources/test/payloads/dmaap-pserver-create.json100
-rw-r--r--src/test/resources/test/payloads/dmaapEvents/address-list.json47
-rw-r--r--src/test/resources/test/payloads/dmaapEvents/deleteRelationship/1-create-logical-link.json20
-rw-r--r--src/test/resources/test/payloads/dmaapEvents/deleteRelationship/2-create-generic-vnf.json32
-rw-r--r--src/test/resources/test/payloads/dmaapEvents/deleteRelationship/3-create-rel-generic-vnf-vlan-to-logical-link.json45
-rw-r--r--src/test/resources/test/payloads/dmaapEvents/deleteRelationship/4-delete-rel-to-generic-vnf-vlan-from-logical-link.json20
-rw-r--r--src/test/resources/test/payloads/dmaapEvents/large-pserver.json2088
-rw-r--r--src/test/resources/test/payloads/dmaapEvents/nos.json96
-rw-r--r--src/test/resources/test/payloads/dmaapEvents/vce.json81
-rw-r--r--startSpring.bat4
110 files changed, 13754 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..baed00b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+target/
+.classpath
+.project
+.settings/
+**/logs/
+/.pydevproject
+/bin/
+**/.idea/
+*/.idea
+*.iml \ No newline at end of file
diff --git a/LICENSE.TXT b/LICENSE.TXT
new file mode 100644
index 0000000..3455862
--- /dev/null
+++ b/LICENSE.TXT
@@ -0,0 +1,17 @@
+============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=========================================================
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d2e6d4c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,38 @@
+# Cacher Microservice
+
+
+Build and test
+````bash
+ mvn clean install
+````
+
+Run spring boot
+```bash
+ mvn spring-boot:run
+```
+
+if on Windows the startSpring.bat file can be used to start the mS with the debug port configured
+
+The purpose of this microservice is to provide the ability to store and force update cached responses as well as for particular cases update the cached data from consuming dmaap events.
+
+##Cache Key Inventory API endpoints
+
+localhost:8444/aai/cacheKey/get
+
+localhost:8444/aai/cacheKey/delete
+
+localhost:8444/aai/cacheKey/add
+
+localhost:8444/aai/cacheKey/update
+
+##Cache API endpoints
+
+localhost:8444/aai/cache/delete
+
+localhost:8444/aai/cache/sync
+
+localhost:8444/aai/cache/get
+
+
+
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..4850a39
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,691 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ ============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 xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.onap.aai</groupId>
+ <artifactId>aai-cacher</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+
+ <parent>
+ <groupId>org.onap.oparent</groupId>
+ <artifactId>oparent</artifactId>
+ <version>1.1.0</version>
+ </parent>
+
+ <properties>
+ <icd.file>service.json</icd.file>
+ <icd.package>org.onap.aai.cacher.service.rest</icd.package>
+ <!-- Start of Compiler Related Properties -->
+ <java.version>1.8</java.version>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <!-- End of Compiler Related Properties -->
+
+ <!-- Start of Test Related Properties -->
+ <skip.unit.tests>false</skip.unit.tests>
+ <skip.integration.tests>true</skip.integration.tests>
+ <!-- End of Test Related Properties -->
+
+ <spring.boot.version>1.5.15.RELEASE</spring.boot.version>
+
+ <eclipse.jetty.version>9.4.1.v20170120</eclipse.jetty.version>
+
+ <docker.registry>docker.io</docker.registry>
+ <build.number>local</build.number>
+ <service.account>aai-svc-account</service.account>
+ <docker.namespace>openecomp</docker.namespace>
+
+ <license.goal.type>check</license.goal.type>
+
+ <start-class>org.onap.aai.cacher.Application</start-class>
+
+ <aai-core.version>1.3.0-SNAPSHOT</aai-core.version>
+
+ <!-- Start of the jacoco plugin 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>
+ <!-- End of the jacoco plugin properties -->
+
+ <json.version>20090211</json.version>
+ <logback.version>1.1.7</logback.version>
+ <eelf.core.version>1.0.0</eelf.core.version>
+ <mockito.version>1.10.19</mockito.version>
+ <json.assert.version>1.5.0</json.assert.version>
+ <spring.security.version>1.0.3.RELEASE</spring.security.version>
+ <common.logging.version>1.2.2</common.logging.version>
+ <dmaap.client.version>0.2.12</dmaap.client.version>
+ <dme2.version>2.8.5</dme2.version>
+ <commons.configuration.version>1.9</commons.configuration.version>
+
+ <docker.fabric.version>0.23.0</docker.fabric.version>
+ <!-- Default docker registry that maven fabric plugin will try to pull from -->
+ <docker.registry>docker.io</docker.registry>
+ <!-- Specifying the docker push registry where the image should be pushed -->
+ <!-- This value should be overwritten at runtime to wherever need to be pushed to -->
+ <docker.push.registry>localhost:5000</docker.push.registry>
+
+ <aai.docker.version>1.0.0</aai.docker.version>
+ <!--
+ Location where assembly of our scripts, resources and main jar will be held
+ Check the aai-cacher/src/main/assembly/descriptor.xml for more info
+ -->
+ <aai.build.directory>${project.build.directory}/${project.artifactId}-${project.version}-build/</aai.build.directory>
+ <aai.docker.namespace>openecomp</aai.docker.namespace>
+
+ <maven.skip.tests>true</maven.skip.tests>
+
+ <jacoco.line.coverage.limit>.001</jacoco.line.coverage.limit>
+ </properties>
+
+ <developers>
+ <developer>
+ <id>${userId}</id>
+ </developer>
+ </developers>
+
+ <profiles>
+ <profile>
+ <id>docker</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <version>${docker.fabric.version}</version>
+ <configuration>
+ <verbose>true</verbose>
+ <apiVersion>1.23</apiVersion>
+ <images>
+ <image>
+ <name>${docker.push.registry}/${aai.docker.namespace}/aai-cacher:%l</name>
+ <build>
+ <filter>@</filter>
+ <tags>
+ <tag>latest</tag>
+ <tag>${aai.docker.version}</tag>
+ </tags>
+ <cleanup>try</cleanup>
+ <dockerFileDir>${project.basedir}/src/main/docker</dockerFileDir>
+ <assembly>
+ <inline>
+ <fileSets>
+ <fileSet>
+ <directory>${aai.build.directory}</directory>
+ <outputDirectory>/${project.artifactId}</outputDirectory>
+ </fileSet>
+ </fileSets>
+ </inline>
+ </assembly>
+ </build>
+ </image>
+ </images>
+ </configuration>
+ <executions>
+ <execution>
+ <id>clean-images</id>
+ <phase>pre-clean</phase>
+ <goals>
+ <goal>remove</goal>
+ </goals>
+ <configuration>
+ <removeAll>true</removeAll>
+ </configuration>
+ </execution>
+ <execution>
+ <id>generate-images</id>
+ <phase>package</phase>
+ <goals>
+ <goal>build</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>push-images</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>build</goal>
+ <goal>push</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>runAjsc</id>
+ <properties>
+ <skipTests>${maven.skip.tests}</skipTests>
+ </properties>
+ <build>
+ <defaultGoal>pre-integration-test</defaultGoal>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.6.0</version>
+ <executions>
+ <execution>
+ <id>run-spring-boot</id>
+ <phase>package</phase>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <mainClass>${start-class}</mainClass>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-parent</artifactId>
+ <version>${spring.boot.version}</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.7</version>
+ </dependency>
+ <dependency>
+ <groupId>de.flapdoodle.embed</groupId>
+ <artifactId>de.flapdoodle.embed.mongo</artifactId>
+ <version>2.0.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mongodb</groupId>
+ <artifactId>mongodb-driver</artifactId>
+ <version>3.6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-mongodb</artifactId>
+ </dependency>
+ <!--
+ Explicitly stating the security spring framework and
+ exclude the bouncy castle since that is somehow overwriting
+ our p12 file decryption that's built into java security
+ This will cause the password is incorrect
+ This needs to be added back if org.bouncy castle dependency
+ sneaks backs in and causing issues with the two way ssl
+ -->
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-rsa</artifactId>
+ <version>${spring.security.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-tomcat</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-jetty</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-jersey</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.reflections</groupId>
+ <artifactId>reflections</artifactId>
+ <version>0.9.10</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>2.24</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-common</artifactId>
+ <version>2.24</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>apache-log4j-extras</artifactId>
+ <version>1.2.17</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>log4j</artifactId>
+ <groupId>log4j</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>${json.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <version>2.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.aai.aai-common</groupId>
+ <artifactId>aai-core</artifactId>
+ <version>${aai-core.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-core</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>commons-configuration</groupId>
+ <artifactId>commons-configuration</artifactId>
+ <version>${commons.configuration.version}</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>commons-lang</artifactId>
+ <groupId>commons-lang</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>com.att.eelf</groupId>
+ <artifactId>eelf-core</artifactId>
+ <version>${eelf.core.version}</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>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>${mockito.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.skyscreamer</groupId>
+ <artifactId>jsonassert</artifactId>
+ <version>${json.assert.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.fakemongo</groupId>
+ <artifactId>fongo</artifactId>
+ <version>2.2.0-RC2</version>
+ <scope>test</scope>
+ </dependency>
+ <!--
+ Note - Use of this dme2 dependency is itself a harm to spring boot as this
+ dependency will crash the application without this exclusion
+ since the dme2 dependency does shading so we need exclude the javax servlet
+
+ <dependency>
+ <groupId>com.att.aft</groupId>
+ <artifactId>dme2</artifactId>
+ <version>${dme2.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ -->
+ <dependency>
+ <groupId>com.att.nsa</groupId>
+ <artifactId>dmaapClient</artifactId>
+ <version>${dmaap.client.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.att.aft</groupId>
+ <artifactId>dme2</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>commons-net</groupId>
+ <artifactId>commons-net</artifactId>
+ <version>3.6</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>exec-maven-plugin</artifactId>
+ <groupId>org.codehaus.mojo</groupId>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>${start-class}</mainClass>
+ <layout>ZIP</layout>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/descriptor.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id> <!-- this is used for inheritance merges -->
+ <phase>package</phase> <!-- bind to the packaging phase -->
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>com.github.kongchen</groupId>
+ <artifactId>swagger-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <additionalparam>-Xdoclint:none</additionalparam>
+ </configuration>
+ </plugin>
+ <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>src/main/resources</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>
+ <!-- implementation is needed only for Maven 2 -->
+ <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>
+ <groupId>com.mycila</groupId>
+ <artifactId>license-maven-plugin</artifactId>
+ <version>3.0</version>
+ <configuration>
+ <header>LICENSE.TXT</header>
+ <includes>
+ <include>src/main/java/**</include>
+ <include>src/test/java/**</include>
+ <include>pom.xml</include>
+ </includes>
+ <skipExistingHeaders>false</skipExistingHeaders>
+ <skip>false</skip>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <!-- Set goal to "format" to auto update license headers -->
+ <goal>${license.goal.type}</goal>
+ </goals>
+ <phase>process-sources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <!-- mention the logback.xml location through system property or environment
+ variable to edit logback.xml at run time -->
+ <resources>
+ <resource>
+ <directory>${project.basedir}/src/main/swm</directory>
+ <targetPath>${project.build.directory}/swm</targetPath>
+ <filtering>false</filtering>
+ </resource>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <includes>
+ <include>application.properties</include>
+ <include>logback.xml</include>
+ <include>localhost-access-logback.xml</include>
+ </includes>
+ <targetPath>${project.build.directory}/swm/package/nix/dist_files/opt/app/aai-cacher/appconfig</targetPath>
+ <filtering>false</filtering>
+ </resource>
+ <resource>
+ <directory>${project.basedir}/src/main/resources/etc/auth/</directory>
+ <includes>
+ <include>aai-client-cert.p12</include>
+ <include>tomcat_keystore</include>
+ </includes>
+ <targetPath>${project.build.directory}/swm/package/nix/dist_files/opt/app/aai-cacher/appconfig</targetPath>
+ <filtering>true</filtering>
+ </resource>
+ <resource>
+ <directory>${project.basedir}/src/main/docker</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <targetPath>${aai.build.directory}</targetPath>
+ <filtering>true</filtering>
+ </resource>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </build>
+ <!-- Start of ONAP Specific Repositories -->
+ <repositories>
+ <repository>
+ <id>AJSC</id>
+ <name>AJSC repository</name>
+ <url>https://mvnrepository.com/artifact/com.att.ajsc</url>
+ </repository>
+ <repository>
+ <id>restlet</id>
+ <name>maven reslet</name>
+ <url>https://maven.restlet.com/</url>
+ </repository>
+
+ <repository>
+ <id>central</id>
+ <name>Maven 2 repository 2</name>
+ <url>http://repo2.maven.org/maven2/</url>
+ </repository>
+ <repository>
+ <id>ecomp-releases</id>
+ <name>ECOMP Release Repository</name>
+ <url>${onap.nexus.url}/content/repositories/releases/</url>
+ </repository>
+ <repository>
+ <id>ecomp-staging</id>
+ <name>ECOMP Staging Repository</name>
+ <url>${onap.nexus.url}/content/repositories/staging/</url>
+ </repository>
+ <repository>
+ <id>ecomp-snapshots</id>
+ <name>ECOMP Snapshot Repository</name>
+ <url>${onap.nexus.url}/content/repositories/snapshots/</url>
+ </repository>
+ </repositories>
+ <!-- End of ONAP Specific Repositories -->
+</project>
diff --git a/set-debug-port.bat b/set-debug-port.bat
new file mode 100644
index 0000000..9ed0132
--- /dev/null
+++ b/set-debug-port.bat
@@ -0,0 +1 @@
+SET MAVEN_OPTS=-Xms2048m -Xmx2048m -Xdebug -Xnoagent -Djava.compile=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9444 \ No newline at end of file
diff --git a/src/main/assembly/descriptor.xml b/src/main/assembly/descriptor.xml
new file mode 100644
index 0000000..094d8fb
--- /dev/null
+++ b/src/main/assembly/descriptor.xml
@@ -0,0 +1,32 @@
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+ <id>build</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>dir</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <outputDirectory>/resources</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>${project.basedir}/src/main/scripts</directory>
+ <outputDirectory>/bin</outputDirectory>
+ <includes>
+ <include>*</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>${project.build.directory}</directory>
+ <outputDirectory>/lib</outputDirectory>
+ <includes>
+ <include>${project.artifactId}-${project.version}.jar</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/src/main/docker/Dockerfile b/src/main/docker/Dockerfile
new file mode 100644
index 0000000..eb49a7d
--- /dev/null
+++ b/src/main/docker/Dockerfile
@@ -0,0 +1,22 @@
+FROM aaionap/aai-common:1.3.0
+
+# Add the proper files into the docker image from your build
+WORKDIR /opt/app/aai-cacher
+
+# Expose the ports for outside linux to use
+# 8444 is the important one to be used
+EXPOSE 8444
+
+HEALTHCHECK --interval=40s --timeout=10s --retries=3 CMD nc -z -v localhost 8444 || exit 1
+
+ENTRYPOINT ["/bin/bash", "/opt/app/aai-cacher/docker-entrypoint.sh"]
+
+RUN mkdir -p /opt/aaihome/aaiadmin /opt/aai/logroot/AAI-CACHER
+
+VOLUME /opt/aai/logroot/AAI-CACHER
+VOLUME /opt/aaihome
+VOLUME /opt/aaihome/aaiadmin
+
+COPY /maven/aai-cacher/ .
+
+ENV AAI_BUILD_VERSION @aai.docker.version@ \ No newline at end of file
diff --git a/src/main/docker/aai.sh b/src/main/docker/aai.sh
new file mode 100644
index 0000000..cd496f1
--- /dev/null
+++ b/src/main/docker/aai.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+#
+# ============LICENSE_START=======================================================
+# org.onap.aai
+# ================================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+PROJECT_HOME=/opt/app/aai-cacher
+export PROJECT_HOME
+
+JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
+export JAVA_HOME
+
+AAIENV=dev
+export AAIENV
+
+PATH=/usr/lib/jvm/java-8-openjdk-amd64:$PATH
+
+PROJECT_OWNER=aaiadmin
+PROJECT_GROUP=aaiadmin
+PROJECT_UNIXHOMEROOT=/opt/aaihome
+export PROJECT_OWNER PROJECT_GROUP PROJECT_UNIXHOMEROOT
+umask 0022
+
+export idns_api_url=
+export idnscred=
+export idnstenant=
+
diff --git a/src/main/docker/docker-entrypoint.sh b/src/main/docker/docker-entrypoint.sh
new file mode 100644
index 0000000..06fd7f4
--- /dev/null
+++ b/src/main/docker/docker-entrypoint.sh
@@ -0,0 +1,125 @@
+#!/bin/bash
+
+APP_HOME=$(pwd);
+RESOURCES_HOME=${APP_HOME}/resources/;
+
+export CHEF_CONFIG_REPO=${CHEF_CONFIG_REPO:-aai-config};
+export CHEF_GIT_URL=${CHEF_GIT_URL:-http://gerrit.onap.org/r/aai};
+export CHEF_CONFIG_GIT_URL=${CHEF_CONFIG_GIT_URL:-$CHEF_GIT_URL};
+export CHEF_DATA_GIT_URL=${CHEF_DATA_GIT_URL:-$CHEF_GIT_URL};
+
+export SERVER_PORT=${SERVER_PORT:-8444};
+
+USER_ID=${LOCAL_USER_ID:-9001}
+GROUP_ID=${LOCAL_GROUP_ID:-9001}
+
+# need to override this in docker compose template to use proxy
+PROXY_HOST=${LOCAL_PROXY_HOST:-}
+
+echo "APPHOME is $APP_HOME";
+
+if [ $(cat /etc/passwd | grep aaiadmin | wc -l) -eq 0 ]; then
+ groupadd aaiadmin -g ${GROUP_ID} || {
+ echo "Unable to create the group id for ${GROUP_ID}";
+ exit 1;
+ }
+ useradd --shell=/bin/bash -u ${USER_ID} -g ${GROUP_ID} -o -c "" -m aaiadmin || {
+ echo "Unable to create the user id for ${USER_ID}";
+ exit 1;
+ }
+fi;
+
+chown -R aaiadmin:aaiadmin /opt/app /opt/aai/logroot /var/chef
+find /opt/app/ -name "*.sh" -exec chmod +x {} +
+
+gosu aaiadmin ln -s bin scripts
+gosu aaiadmin ln -s /opt/aai/logroot/AAI-CACHER logs
+mkdir -p /opt/app/aai-cacher/logs/gc
+chown -R aaiadmin:aaiadmin /opt/app/aai-cacher/logs
+
+if [ -f ${APP_HOME}/aai.sh ]; then
+ mv ${APP_HOME}/aai.sh /etc/profile.d/aai.sh
+ chmod 755 /etc/profile.d/aai.sh
+
+ scriptName=$1;
+
+ if [ ! -z $scriptName ]; then
+
+ if [ -f ${APP_HOME}/bin/${scriptName} ]; then
+ shift 1;
+ gosu aaiadmin ${APP_HOME}/bin/${scriptName} "$@" || {
+ echo "Failed to run the ${scriptName}";
+ exit 1;
+ }
+ else
+ echo "Unable to find the script ${scriptName} in ${APP_HOME}/bin";
+ exit 1;
+ fi;
+
+ exit 0;
+ fi;
+fi;
+
+if [ -f ${APP_HOME}/scripts/install/cacher-swm-vars.sh ]; then
+ source ${APP_HOME}/scripts/install/cacher-swm-vars.sh;
+fi;
+
+MIN_HEAP_SIZE=${MIN_HEAP_SIZE:-512m};
+MAX_HEAP_SIZE=${MAX_HEAP_SIZE:-1024m};
+MAX_PERM_SIZE=${MAX_PERM_SIZE:-512m};
+PERM_SIZE=${PERM_SIZE:-512m};
+
+JAVA_CMD="exec gosu aaiadmin java";
+
+JVM_OPTS="${PRE_JVM_ARGS} -Xloggc:/opt/app/aai-cacher/logs/gc/aai_gc.log";
+JVM_OPTS="${JVM_OPTS} -XX:HeapDumpPath=/opt/app/aai-cacher/logs/ajsc-jetty/heap-dump";
+JVM_OPTS="${JVM_OPTS} -Xms${MIN_HEAP_SIZE}";
+JVM_OPTS="${JVM_OPTS} -Xmx${MAX_HEAP_SIZE}";
+
+JVM_OPTS="${JVM_OPTS} -XX:+PrintGCDetails";
+JVM_OPTS="${JVM_OPTS} -XX:+PrintGCTimeStamps";
+JVM_OPTS="${JVM_OPTS} -XX:MaxPermSize=${MAX_PERM_SIZE}";
+JVM_OPTS="${JVM_OPTS} -XX:PermSize=${PERM_SIZE}";
+
+JVM_OPTS="${JVM_OPTS} -server";
+JVM_OPTS="${JVM_OPTS} -XX:NewSize=512m";
+JVM_OPTS="${JVM_OPTS} -XX:MaxNewSize=512m";
+JVM_OPTS="${JVM_OPTS} -XX:SurvivorRatio=8";
+JVM_OPTS="${JVM_OPTS} -XX:+DisableExplicitGC";
+JVM_OPTS="${JVM_OPTS} -verbose:gc";
+JVM_OPTS="${JVM_OPTS} -XX:+UseParNewGC";
+JVM_OPTS="${JVM_OPTS} -XX:+CMSParallelRemarkEnabled";
+JVM_OPTS="${JVM_OPTS} -XX:+CMSClassUnloadingEnabled";
+JVM_OPTS="${JVM_OPTS} -XX:+UseConcMarkSweepGC";
+JVM_OPTS="${JVM_OPTS} -XX:-UseBiasedLocking";
+JVM_OPTS="${JVM_OPTS} -XX:ParallelGCThreads=4";
+JVM_OPTS="${JVM_OPTS} -XX:LargePageSizeInBytes=128m";
+JVM_OPTS="${JVM_OPTS} -XX:+PrintGCDetails";
+JVM_OPTS="${JVM_OPTS} -XX:+PrintGCTimeStamps";
+JVM_OPTS="${JVM_OPTS} -Dsun.net.inetaddr.ttl=180";
+JVM_OPTS="${JVM_OPTS} -XX:+HeapDumpOnOutOfMemoryError";
+JVM_OPTS="${JVM_OPTS} ${POST_JVM_ARGS}";
+JVM_OPTS="${JVM_OPTS} -Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true";
+
+JAVA_OPTS="${JAVA_OPTS} -DAJSC_HOME=$APP_HOME";
+if [ -f ${INTROSCOPE_LIB}/Agent.jar ] && [ -f ${INTROSCOPE_AGENTPROFILE} ]; then
+ JAVA_OPTS="${JAVA_OPTS} -javaagent:${INTROSCOPE_LIB}/Agent.jar -noverify -Dcom.wily.introscope.agentProfile=${INTROSCOPE_AGENTPROFILE} -Dintroscope.agent.agentName=cacher"
+fi
+JAVA_OPTS="${JAVA_OPTS} -Dserver.port=${SERVER_PORT}";
+JAVA_OPTS="${JAVA_OPTS} -DBUNDLECONFIG_DIR=./resources";
+JAVA_OPTS="${JAVA_OPTS} -Dserver.local.startpath=${RESOURCES_HOME}";
+JAVA_OPTS="${JAVA_OPTS} -DAAI_CHEF_ENV=${AAI_CHEF_ENV}";
+JAVA_OPTS="${JAVA_OPTS} -DSCLD_ENV=${SCLD_ENV}";
+JAVA_OPTS="${JAVA_OPTS} -DAFT_ENVIRONMENT=${AFT_ENVIRONMENT}";
+JAVA_OPTS="${JAVA_OPTS} -DAAI_BUILD_VERSION=${AAI_BUILD_VERSION}";
+JAVA_OPTS="${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom";
+JAVA_OPTS="${JAVA_OPTS} -Dlogback.configurationFile=./resources/logback.xml";
+JAVA_OPTS="${JAVA_OPTS} -Dloader.path=$APP_HOME/resources";
+if [ ! -z ${PROXY_HOST} ]; then
+ JAVA_OPTS="${JAVA_OPTS} -DproxySet=true -DproxyHost=${PROXY_HOST} -DproxyPort=8080";
+fi
+JAVA_OPTS="${JAVA_OPTS} ${POST_JAVA_OPTS}";
+
+JAVA_MAIN_JAR=$(ls lib/aai-cacher*.jar);
+
+${JAVA_CMD} ${JVM_OPTS} ${JAVA_OPTS} -jar ${JAVA_MAIN_JAR}; \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/Application.java b/src/main/java/org/onap/aai/cacher/Application.java
new file mode 100644
index 0000000..9382f4b
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/Application.java
@@ -0,0 +1,85 @@
+/**
+ * ============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.cacher;
+
+import org.onap.aai.cacher.config.PropertyPasswordConfiguration;
+import org.onap.aai.logging.LoggingContext;
+import org.onap.aai.logging.LoggingContext.StatusCode;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+import java.util.UUID;
+
+@SpringBootApplication
+@EnableScheduling
+@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
+@ComponentScan(basePackages = { "org.onap.aai.cacher", "com" })
+@PropertySource("classpath:application.properties")
+public class Application extends SpringBootServletInitializer {
+ private static final String APP_NAME = "cacher";
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(Application.class);
+ }
+
+ public static void main(String[] args) throws Exception {
+ setDefaultProps();
+
+ LoggingContext.save();
+ LoggingContext.component("init");
+ LoggingContext.partnerName("NA");
+ LoggingContext.targetEntity(APP_NAME);
+ LoggingContext.requestId(UUID.randomUUID().toString());
+ LoggingContext.serviceName(APP_NAME);
+ LoggingContext.targetServiceName("contextInitialized");
+ LoggingContext.statusCode(StatusCode.COMPLETE);
+
+ SpringApplication app = new SpringApplication(Application.class);
+ app.setLogStartupInfo(false);
+ app.setRegisterShutdownHook(true);
+ app.addInitializers(new PropertyPasswordConfiguration());
+ app.run(args);
+
+ }
+
+ public static void setDefaultProps() {
+
+ if (System.getProperty("file.separator") == null) {
+ System.setProperty("file.separator", "/");
+ }
+
+ if (System.getProperty("AJSC_HOME") == null) {
+ System.setProperty("AJSC_HOME", ".");
+ }
+
+ if (System.getProperty("BUNDLECONFIG_DIR") == null) {
+ System.setProperty("BUNDLECONFIG_DIR", "src/main/resources");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/Profiles.java b/src/main/java/org/onap/aai/cacher/Profiles.java
new file mode 100644
index 0000000..05c3559
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/Profiles.java
@@ -0,0 +1,31 @@
+/**
+ * ============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.cacher;
+
+public final class Profiles {
+
+ public static final String DMAAP = "dmaap";
+ public static final String DME2 = "dme2";
+
+ public static final String ONE_WAY_SSL = "one-way-ssl";
+ public static final String TWO_WAY_SSL = "two-way-ssl";
+
+ private Profiles(){}
+}
diff --git a/src/main/java/org/onap/aai/cacher/common/CacheKeyConfig.java b/src/main/java/org/onap/aai/cacher/common/CacheKeyConfig.java
new file mode 100644
index 0000000..e02ea81
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/common/CacheKeyConfig.java
@@ -0,0 +1,62 @@
+/**
+ * ============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.cacher.common;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.onap.aai.cacher.model.CacheKey;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CacheKeyConfig {
+ private JsonArray cachekeys = null;
+
+ private static final String CACHEKEYS = "cachekeys";
+
+ public CacheKeyConfig(String json) {
+ init(json);
+ }
+
+ private void init(String json) {
+ JsonParser parser = new JsonParser();
+ JsonObject queriesObject = parser.parse(json).getAsJsonObject();
+ if (queriesObject.has(CACHEKEYS)) {
+ cachekeys = queriesObject.getAsJsonArray(CACHEKEYS);
+ }
+ }
+
+ public List<CacheKey> populateCacheKeyList() {
+ List<CacheKey> ckList = new ArrayList<>();
+ for (JsonElement cacheKeyElement : cachekeys) {
+ if (cacheKeyElement.isJsonObject()) {
+ JsonObject cacheJsonObj = cacheKeyElement.getAsJsonObject();
+ if (cacheJsonObj != null) {
+ CacheKey cacheKey = CacheKey.fromJson(cacheJsonObj);
+ ckList.add(cacheKey);
+ }
+ }
+ }
+ return ckList;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/common/MongoConfig.java b/src/main/java/org/onap/aai/cacher/common/MongoConfig.java
new file mode 100644
index 0000000..d08930b
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/common/MongoConfig.java
@@ -0,0 +1,104 @@
+/**
+ * ============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.cacher.common;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoDatabase;
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodProcess;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.IMongodConfig;
+import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Net;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.process.runtime.Network;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+
+@Configuration
+public class MongoConfig {
+
+ private final static EELFLogger EELF_LOGGER = EELFManager.getInstance().getLogger(MongoConfig.class);
+
+ @Value("${mongodb.host}")
+ private String MONGO_DB_HOST;
+ @Value("${mongodb.dbName}")
+ private String MONGO_DB_NAME;
+ @Value("${mongodb.port}")
+ private int MONGO_DB_PORT;
+
+ @Bean
+ public MongoClient mongoClient() {
+ try {
+ // To connect to mongodb server
+ MongoClient mongoC = new MongoClient(MONGO_DB_HOST, MONGO_DB_PORT);
+
+ // Now connect to your databases
+ EELF_LOGGER.info("Connect to database successfully");
+
+ return mongoC;
+
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000");
+ ErrorLogHelper.logException(aaiException);
+ }
+
+ return null;
+ }
+
+ @Bean
+ public DB db(MongoClient mongoClient) {
+ return mongoClient.getDB(MONGO_DB_NAME);
+ }
+
+ @Bean
+ public MongoDatabase mongoDatabase(MongoClient mongoClient) {
+ return mongoClient.getDatabase(MONGO_DB_NAME);
+ }
+
+ @Bean
+ @PostConstruct
+ public MongodProcess mongoEmbedded() throws IOException, InterruptedException {
+
+ MongodStarter starter = MongodStarter.getDefaultInstance();
+
+ String bindIp = MONGO_DB_HOST;
+ int port = MONGO_DB_PORT;
+ IMongodConfig mongodConfig = new MongodConfigBuilder().version(Version.Main.PRODUCTION)
+ .net(new Net(port, Network.localhostIsIPv6())).configServer(false).build();
+
+ MongodExecutable mongodExecutable = starter.prepare(mongodConfig);
+ // Thread.sleep(20000L);
+ MongodProcess mongod = mongodExecutable.start();
+ if (mongod.isProcessRunning()) {
+ System.out.println("RUNNING");
+ }
+ return mongod;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/common/MongoHelperSingleton.java b/src/main/java/org/onap/aai/cacher/common/MongoHelperSingleton.java
new file mode 100644
index 0000000..63638f1
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/common/MongoHelperSingleton.java
@@ -0,0 +1,312 @@
+/**
+ * ============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.cacher.common;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.common.collect.Lists;
+import com.google.gson.JsonObject;
+import com.mongodb.*;
+import com.mongodb.client.AggregateIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.DBCollectionUpdateOptions;
+import com.mongodb.client.model.FindOneAndUpdateOptions;
+import com.mongodb.client.model.UpdateOptions;
+import com.mongodb.client.result.DeleteResult;
+import com.mongodb.client.result.UpdateResult;
+import org.apache.commons.lang3.StringUtils;
+import org.bson.Document;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Creates and returns a mongo instance
+ */
+
+@Component
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class MongoHelperSingleton {
+
+ private final static EELFLogger EELF_LOGGER = EELFManager.getInstance().getLogger(MongoHelperSingleton.class);
+
+ private DB db;
+
+ private MongoDatabase mongoDatabase;
+
+ @Autowired
+ public MongoHelperSingleton(DB db, MongoDatabase mongoDatabase) {
+ this.mongoDatabase = mongoDatabase;
+ this.db = db;
+ }
+
+ public DB getDb() {
+ return db;
+ }
+
+ public void createCollection(String name) {
+ try {
+ db.getCollection(name);
+ EELF_LOGGER.info("Collection " + name + " created successfully");
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000");
+ ErrorLogHelper.logException(aaiException);
+ }
+ }
+
+ public boolean addToMongo(String collectionName, Object document) {
+ try {
+ DBCollection collection = db.getCollection(collectionName);
+ WriteResult result;
+ if (document instanceof List) {
+ result = collection.insert((List<BasicDBObject>) document);
+ return result.wasAcknowledged();
+ } else if (document instanceof BasicDBObject) {
+ result = collection.insert((BasicDBObject) document);
+ return result.wasAcknowledged();
+ } else {
+ EELF_LOGGER.error("The cachekey object to add was of unknown type");
+ return false;
+ }
+ } catch (MongoException ex) {
+ AAIException aaiException = new AAIException("AAI_5105");
+ ErrorLogHelper.logException(aaiException);
+ return false;
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000");
+ ErrorLogHelper.logException(aaiException);
+ return false;
+ }
+ }
+
+ public boolean updateInMongo(String collectionName, BasicDBObject searchQuery, Object document,
+ DBCollectionUpdateOptions updateOptions) {
+ try {
+ DBCollection collection = db.getCollection(collectionName);
+ WriteResult result;
+ result = collection.update(searchQuery, (BasicDBObject) document, updateOptions);
+ return result.wasAcknowledged();
+ } catch (MongoException ex) {
+ AAIException aaiException = new AAIException("AAI_5105");
+ ErrorLogHelper.logException(aaiException);
+ return false;
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000");
+ ErrorLogHelper.logException(aaiException);
+ return false;
+ }
+ }
+
+ public String deleteFromMongo(String collectionName, Map<String, String> whereClause) {
+ DBCollection collection = db.getCollection(collectionName);
+ DBObject searchQuery = new BasicDBObject();
+ for (Map.Entry<String, String> entry : whereClause.entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ searchQuery.put(key, value);
+ }
+ try {
+ WriteResult result = collection.remove(searchQuery);
+ if (result.getN() > 0) {
+ return "DELETED";
+ } else {
+ return "NOT_FOUND";
+ }
+ } catch (MongoException ex) {
+ AAIException aaiException = new AAIException("AAI_5105");
+ ErrorLogHelper.logException(aaiException);
+ return "EXCEPTION_THROWN";
+ }
+ }
+
+ public void dropCollection(String collectionName) {
+ db.getCollection(collectionName).drop();
+ }
+
+ public Response buildResponse(Status status, String result) {
+ return Response.status(status).type(MediaType.APPLICATION_JSON).entity(result).build();
+ }
+
+ public Response buildExceptionResponse(AAIException aaiException) {
+ ErrorLogHelper.logException(aaiException);
+ return Response.status(aaiException.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(
+ Lists.newArrayList(MediaType.APPLICATION_JSON_TYPE), aaiException, new ArrayList<>()))
+ .build();
+ }
+
+ public boolean insertReplace(CacheEntry cacheEntry) {
+ MongoCollection<Document> collection = mongoDatabase.getCollection(cacheEntry.getCollection());
+
+ Document findQuery = Document.parse(cacheEntry.getFindQuery().toString());
+ Document payload = Document.parse(cacheEntry.getPayload().toString());
+
+ if (!cacheEntry.isNested()) {
+ UpdateResult updateResult = collection.replaceOne(findQuery, payload, new UpdateOptions().upsert(true));
+
+ return updateResult.wasAcknowledged();
+ } else {
+ CacheEntry localCacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry().deepCopy(cacheEntry).build();
+ Document nestedFind = Document.parse(localCacheEntry.getNestedFind().toString());
+
+ // if exists remove
+ if (collection.count(nestedFind) > 0L) {
+ mongoPull(localCacheEntry, collection, nestedFind);
+ }
+
+ ArrayList<Document> filters = this.getFiltersAndUpdateNestedField(localCacheEntry);
+ Document doc = new Document();
+ doc.put(localCacheEntry.getNestedField(), payload);
+ Document push = new Document();
+ push.put("$push", doc);
+
+ collection.findOneAndUpdate(findQuery, push,
+ new FindOneAndUpdateOptions().arrayFilters(filters).upsert(true));
+
+ return collection.count(nestedFind) > 0L;
+ }
+ }
+
+ public boolean delete(CacheEntry cacheEntry) {
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(cacheEntry.getCollection());
+
+ Document findQuery = Document.parse(cacheEntry.getFindQuery().toString());
+
+ if (!cacheEntry.isNested()) {
+ if (collection.count(findQuery) == 0L) {
+ return true;
+ }
+ DeleteResult deleteResult = collection.deleteOne(findQuery);
+ return deleteResult.wasAcknowledged();
+
+ } else {
+ Document nestedFind = Document.parse(cacheEntry.getNestedFind().toString());
+ if (collection.count(nestedFind) == 0L) {
+ return true;
+ }
+
+ mongoPull(cacheEntry, collection, nestedFind);
+ return collection.count(nestedFind) == 0L;
+
+ }
+ }
+
+ public Optional<Document> getObject(CacheEntry cacheEntry) {
+ MongoCollection<Document> collection = mongoDatabase.getCollection(cacheEntry.getCollection());
+ Document resultingObject;
+
+ if (!cacheEntry.isNested()) {
+ resultingObject = collection.find(Document.parse(cacheEntry.getFindQuery().toString())).first();
+ } else {
+ List<Document> aggregate = getAggregateFromFind(cacheEntry.getNestedFind());
+ AggregateIterable<Document> aggregateResult = collection.aggregate(aggregate);
+ resultingObject = aggregateResult.first();
+ if (resultingObject != null) {
+ resultingObject = (Document) (resultingObject.get("output"));
+ }
+ }
+
+ return Optional.ofNullable(resultingObject);
+ }
+
+ private List<Document> getAggregateFromFind(JsonObject nestedFind) {
+ Document nestedFindDocument = Document.parse(nestedFind.toString());
+ List<Document> aggregate = new ArrayList<>();
+ List<String> keys = new ArrayList<>(nestedFindDocument.keySet());
+ for (int i = 0; i < keys.size(); i++) {
+ if (!keys.get(i).contains(".")) {
+ aggregate.add(new Document("$match", new Document(keys.get(i), nestedFindDocument.get(keys.get(i)))));
+ } else {
+ aggregate.add(new Document("$unwind", "$" + keys.get(i).substring(0, keys.get(i).lastIndexOf('.'))));
+ aggregate.add(new Document("$match", new Document(keys.get(i), nestedFindDocument.get(keys.get(i)))));
+ }
+ if (i == keys.size() - 1) {
+ aggregate.add(new Document("$project", new Document("_id", 0).append("output",
+ "$" + keys.get(i).substring(0, keys.get(i).lastIndexOf('.')))));
+ }
+ }
+ return aggregate;
+ }
+
+ protected void mongoPull(CacheEntry cacheEntry, MongoCollection<Document> collection, Document nestedFind) {
+ CacheEntry localCacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry().deepCopy(cacheEntry).build();
+ ArrayList<Document> filters = this.getFiltersAndUpdateNestedField(localCacheEntry);
+
+ Document pullObj = new Document();
+ pullObj.put(localCacheEntry.getNestedField(),
+ Document.parse(localCacheEntry.getNestedFieldIdentifierObj().toString()));
+ Document pull = new Document();
+ pull.put("$pull", pullObj);
+ collection.findOneAndUpdate(nestedFind, pull, new FindOneAndUpdateOptions().arrayFilters(filters).upsert(true));
+ // TODO remove wrapping if there are no entries in array.
+
+ }
+
+ private ArrayList<Document> getFiltersAndUpdateNestedField(CacheEntry cacheEntry) {
+
+ if (StringUtils.countMatches(cacheEntry.getNestedField(), ".$.") < 2) {
+ return new ArrayList<>();
+ }
+
+ ArrayList<Document> filters = new ArrayList<>();
+ List<String> keys = cacheEntry.getNestedFind().entrySet().stream().map(Map.Entry::getKey)
+ .filter(s -> !s.equals("_id")).sorted((s, t1) -> {
+ if (StringUtils.countMatches(s, ".") > StringUtils.countMatches(t1, ".")) {
+ return 1;
+ }
+ return s.compareTo(t1);
+ }).collect(Collectors.toList());
+ String filterKey;
+ String filterValue;
+ String key;
+ char filterIndex = 'a';
+ StringBuilder newNestedField = new StringBuilder();
+ List<String> fieldSplit = Arrays.asList(cacheEntry.getNestedField().split("\\.\\$"));
+ for (int i = 0; i < fieldSplit.size(); i++) {
+ final String subSplit = StringUtils.join(fieldSplit.subList(0, i + 1), "");
+ key = keys.stream().filter(s -> s.startsWith(subSplit)).findFirst().get();
+ filterIndex += i;
+ filterKey = filterIndex + "." + key.substring(key.lastIndexOf(".") + 1);
+ filterValue = cacheEntry.getNestedFind().get(key).getAsString();
+ newNestedField.append(fieldSplit.get(i));
+ if (i + 1 != fieldSplit.size()) {
+ newNestedField.append(".$[").append(filterIndex).append("]");
+ filters.add(new Document().append(filterKey, filterValue));
+ }
+
+ }
+ cacheEntry.setNestedField(newNestedField.toString());
+
+ return filters;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/config/JettyPasswordDecoder.java b/src/main/java/org/onap/aai/cacher/config/JettyPasswordDecoder.java
new file mode 100644
index 0000000..ef18883
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/config/JettyPasswordDecoder.java
@@ -0,0 +1,33 @@
+/**
+ * ============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.cacher.config;
+
+import org.eclipse.jetty.util.security.Password;
+
+public class JettyPasswordDecoder implements PasswordDecoder {
+
+ @Override
+ public String decode(String input) {
+ if (input.startsWith("OBF:")) {
+ return Password.deobfuscate(input);
+ }
+ return Password.deobfuscate("OBF:" + input);
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/config/PasswordDecoder.java b/src/main/java/org/onap/aai/cacher/config/PasswordDecoder.java
new file mode 100644
index 0000000..053e3e8
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/config/PasswordDecoder.java
@@ -0,0 +1,25 @@
+/**
+ * ============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.cacher.config;
+
+public interface PasswordDecoder {
+
+ String decode(String input);
+}
diff --git a/src/main/java/org/onap/aai/cacher/config/PropertyPasswordConfiguration.java b/src/main/java/org/onap/aai/cacher/config/PropertyPasswordConfiguration.java
new file mode 100644
index 0000000..27a43e2
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/config/PropertyPasswordConfiguration.java
@@ -0,0 +1,80 @@
+/**
+ * ============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.cacher.config;
+
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.EnumerablePropertySource;
+import org.springframework.core.env.MapPropertySource;
+import org.springframework.core.env.PropertySource;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class PropertyPasswordConfiguration implements ApplicationContextInitializer<ConfigurableApplicationContext> {
+
+ private static final Pattern decodePasswordPattern = Pattern.compile("password\\((.*?)\\)");
+
+ private PasswordDecoder passwordDecoder = new JettyPasswordDecoder();
+
+ @Override
+ public void initialize(ConfigurableApplicationContext applicationContext) {
+ ConfigurableEnvironment environment = applicationContext.getEnvironment();
+ for (PropertySource<?> propertySource : environment.getPropertySources()) {
+ Map<String, Object> propertyOverrides = new LinkedHashMap<>();
+ decodePasswords(propertySource, propertyOverrides);
+ if (!propertyOverrides.isEmpty()) {
+ PropertySource<?> decodedProperties = new MapPropertySource("decoded " + propertySource.getName(),
+ propertyOverrides);
+ environment.getPropertySources().addBefore(propertySource.getName(), decodedProperties);
+ }
+ }
+ }
+
+ private void decodePasswords(PropertySource<?> source, Map<String, Object> propertyOverrides) {
+ if (source instanceof EnumerablePropertySource) {
+ EnumerablePropertySource<?> enumerablePropertySource = (EnumerablePropertySource<?>) source;
+ for (String key : enumerablePropertySource.getPropertyNames()) {
+ Object rawValue = source.getProperty(key);
+ if (rawValue instanceof String) {
+ String decodedValue = decodePasswordsInString((String) rawValue);
+ propertyOverrides.put(key, decodedValue);
+ }
+ }
+ }
+ }
+
+ private String decodePasswordsInString(String input) {
+ if (input == null)
+ return null;
+ StringBuffer output = new StringBuffer();
+ Matcher matcher = decodePasswordPattern.matcher(input);
+ while (matcher.find()) {
+ String replacement = passwordDecoder.decode(matcher.group(1));
+ matcher.appendReplacement(output, replacement);
+ }
+ matcher.appendTail(output);
+ return output.toString();
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessor.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessor.java
new file mode 100644
index 0000000..5c684a2
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessor.java
@@ -0,0 +1,175 @@
+/**
+ * ============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.cacher.dmaap.consumer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.mongodb.MongoCommandException;
+import org.bson.Document;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.aai.cacher.common.MongoHelperSingleton;
+import org.onap.aai.cacher.injestion.parser.PayloadParserService;
+import org.onap.aai.cacher.injestion.parser.strategy.PayloadParserType;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class AAIDmaapEventProcessor implements DmaapProcessor {
+
+ private static EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIEventConsumer.class);
+
+ private final JsonParser parser = new JsonParser();
+
+ private JSONObject event;
+ private JSONObject eventHeader;
+ private JSONObject eventBody;
+
+ private MongoHelperSingleton mongoHelper;
+ private PayloadParserService payloadParserService;
+
+ @Autowired
+ public AAIDmaapEventProcessor(MongoHelperSingleton mongoHelper, PayloadParserService payloadParserService) {
+ this.mongoHelper = mongoHelper;
+ this.payloadParserService = payloadParserService;
+ }
+
+ public AAIDmaapEventProcessor() {
+ }
+
+ /**
+ *
+ * @param eventMessage
+ * @return
+ */
+ public void process(String eventMessage) throws Exception {
+ this.event = null;
+ this.eventHeader = null;
+ this.eventBody = null;
+
+ try {
+ LOGGER.debug("Processing event: " + eventMessage);
+ this.event = new JSONObject(eventMessage);
+ } catch (JSONException je) {
+ LOGGER.error("ERROR: Event is not valid JSON [" + eventMessage + "].");
+ ErrorLogHelper.logException(new AAIException("AAI_4000", je));
+ throw je;
+ }
+
+ try {
+ LOGGER.debug("Validating event header.");
+ this.validateEventHeader(this.event);
+ } catch (JSONException je) {
+ LOGGER.error("ERROR: Event header is not valid [" + eventMessage + "].");
+ ErrorLogHelper.logException(new AAIException("AAI_4000", je));
+ throw je;
+ }
+
+ try {
+ LOGGER.debug("Processing entity.");
+ eventBody = this.event.getJSONObject("entity");
+ } catch (JSONException je) {
+ LOGGER.error("ERROR: Event body is not valid JSON [" + eventMessage + "].");
+ ErrorLogHelper.logException(new AAIException("AAI_4000", je));
+ throw je;
+ }
+
+ List<CacheEntry> dmaapCacheEntries = payloadParserService.doParse("aai-dmaap",
+ parser.parse(eventMessage).getAsJsonObject(), PayloadParserType.AAI_RESOURCE_DMAAP);
+
+ // Get existing object if is update
+ Optional<Document> existingObj = Optional.empty();
+ if (this.eventHeader != null && "UPDATE".equals(eventHeader.getString("action"))) {
+ existingObj = mongoHelper.getObject(dmaapCacheEntries.get(0));
+ }
+
+ // Add existing object to payload to be parsed by AAI_RESOURCE_DMAAP parser
+ if (existingObj.isPresent()) {
+ JsonObject eventMessageObj = parser.parse(eventMessage).getAsJsonObject();
+ eventMessageObj.add("existing-obj", parser.parse(existingObj.get().toJson()).getAsJsonObject());
+ eventMessage = eventMessageObj.toString();
+ dmaapCacheEntries = payloadParserService.doParse("aai-dmaap", parser.parse(eventMessage).getAsJsonObject(),
+ PayloadParserType.AAI_RESOURCE_DMAAP);
+ }
+
+ for (CacheEntry cacheEntry : dmaapCacheEntries) {
+ try {
+ switch (cacheEntry.getDbAction()) {
+ case DELETE:
+ mongoHelper.delete(cacheEntry);
+ break;
+ case UPDATE:
+ mongoHelper.insertReplace(cacheEntry);
+ break;
+ case INSERT_REPLACE:
+ mongoHelper.insertReplace(cacheEntry);
+ break;
+ }
+ } catch (MongoCommandException exception) {
+ LOGGER.warn("Attempted to update nested that does not exist in cache.", exception);
+ }
+ }
+
+ LOGGER.debug("Event processed successfully.");
+
+ }
+
+ /**
+ * Validates that the event header has the id and source name for processing.
+ * (needed for status response msg)
+ *
+ * @param event
+ * @throws JSONException
+ */
+ private void validateEventHeader(JSONObject event) throws JSONException {
+ eventHeader = event.getJSONObject("event-header");
+ if (this.eventHeader.getString("id") == null || this.eventHeader.getString("id").isEmpty()) {
+ throw new JSONException("Event header id missing.");
+ } else if (this.eventHeader.getString("source-name") == null
+ || this.eventHeader.getString("source-name").isEmpty()) {
+ throw new JSONException("Event header source-name missing.");
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ public JSONObject getEventHeader() {
+ return eventHeader;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public JSONObject getEventBody() {
+ return eventBody;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIEventConsumer.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIEventConsumer.java
new file mode 100644
index 0000000..cb1c77a
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIEventConsumer.java
@@ -0,0 +1,34 @@
+/**
+ * ============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.cacher.dmaap.consumer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+public class AAIEventConsumer extends AAIParentEventConsumer {
+
+ private static EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIEventConsumer.class);
+
+ public AAIEventConsumer(String consumerPropFile, boolean injestConsumer) throws Exception {
+ super(consumerPropFile, injestConsumer);
+ LOGGER.debug("Initialization completed.");
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIParentEventConsumer.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIParentEventConsumer.java
new file mode 100644
index 0000000..8d64116
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/AAIParentEventConsumer.java
@@ -0,0 +1,237 @@
+/**
+ * ============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.cacher.dmaap.consumer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.att.nsa.mr.client.MRClientFactory;
+import com.att.nsa.mr.client.MRConsumer;
+import org.apache.commons.configuration.ConfigurationException;
+import org.eclipse.jetty.util.security.Password;
+import org.onap.aai.cacher.util.AAIConstants;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.onap.aai.util.AAIConfig;
+
+import java.io.*;
+import java.util.Properties;
+import java.util.UUID;
+import java.util.logging.Level;
+
+public class AAIParentEventConsumer {
+
+ protected String fromAppId = "AAIEventConsumerScheduledTask";
+ protected String COMPONENT = "DMAAP-AAI-EVENT";
+ private static EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIParentEventConsumer.class);
+
+ protected String preferredRouterFilePath;
+ protected String aaiDmaapEventConsumerPropertiesFile;
+
+ protected String dmaapPropertyHome = "";
+ protected String dmaapConusmerId = "";
+ protected String transId = "";
+
+ protected Properties aaiDmaapEventConsumerProperties = new Properties();
+
+ protected MRConsumer aaiDmaapEventConsumer;
+
+ protected DmaapConsumerSingleton dmaapConsumerSingleton;
+
+ /*
+ * Change the client consumer implementation from RestDmaapClientConsumer to
+ * DmaapClientConsumer when the bug that is making dme2 connections in dev,
+ * testINT, testEXT is fixed
+ */
+ protected ClientConsumer clientConsumer;
+
+ public AAIParentEventConsumer(String consumerPropFile, boolean injestConsumer) throws Exception {
+ this.transId = UUID.randomUUID().toString();
+ LOGGER.debug("Initalize the AAIParentEventConsumer");
+
+ DmaapConsumerSingleton dmaapConsumerSingleton = DmaapConsumerSingleton.getInstance();
+
+ this.dmaapPropertyHome = AAIConstants.AAI_HOME_ETC_APP_PROPERTIES;
+
+ if (dmaapConsumerSingleton.getDmaapConsumerId() == null) {
+ dmaapConsumerSingleton.setDmaapConsumerId(UUID.randomUUID().toString());
+ }
+ this.dmaapConusmerId = dmaapConsumerSingleton.getDmaapConsumerId();
+
+ processPropertyFiles(consumerPropFile);
+ if (!injestConsumer) {
+ this.aaiDmaapEventConsumer = MRClientFactory.createConsumer(this.aaiDmaapEventConsumerProperties.toString());
+ setConsumer(aaiDmaapEventConsumer);
+ }
+ LOGGER.debug("Initialization completed.");
+
+ }
+
+ public void setConsumer(MRConsumer aaiDmaapEventConsumer) {
+ this.aaiDmaapEventConsumer = aaiDmaapEventConsumer;
+ this.clientConsumer = new RestDmaapClientConsumer(this.aaiDmaapEventConsumer,
+ this.aaiDmaapEventConsumerProperties);
+ }
+
+ public Properties getDmaapEventConsumerProperties() {
+ return aaiDmaapEventConsumerProperties;
+ }
+
+ private void processPropertyFiles(String consumerPropFile) throws IOException, ConfigurationException {
+
+ this.preferredRouterFilePath = this.dmaapPropertyHome + "preferredRoute.txt";
+ this.aaiDmaapEventConsumerPropertiesFile = this.dmaapPropertyHome + consumerPropFile;
+
+ LOGGER.debug("Preferred router file path: " + this.preferredRouterFilePath);
+ LOGGER.debug("AAI Dmaap Event Consumer Properties path: " + this.aaiDmaapEventConsumerPropertiesFile);
+
+ File fo = new File(this.preferredRouterFilePath);
+ if (!fo.exists()) {
+ FileNotFoundException ex = new FileNotFoundException(
+ "Dmaap Route file " + preferredRouterFilePath + " does not exist");
+ ErrorLogHelper.logException(new AAIException("AAI_4000", ex));
+ throw ex;
+ }
+
+ fo = new File(this.aaiDmaapEventConsumerPropertiesFile);
+ if (!fo.exists()) {
+ FileNotFoundException ex = new FileNotFoundException(
+ "Dmaap consumer property file " + aaiDmaapEventConsumerPropertiesFile + " does not exist.");
+ ErrorLogHelper.logException(new AAIException("AAI_4000", ex));
+ throw ex;
+ }
+
+ modifyProperties();
+
+ }
+
+ private void modifyProperties() throws ConfigurationException, IOException {
+
+ try (Reader reader = new FileReader(new File(this.aaiDmaapEventConsumerPropertiesFile))) {
+ this.aaiDmaapEventConsumerProperties.load(reader);
+ }
+
+ aaiDmaapEventConsumerProperties.setProperty("id", this.dmaapConusmerId);
+ LOGGER.debug("Updated " + this.aaiDmaapEventConsumerPropertiesFile + " id " + this.dmaapConusmerId);
+
+ aaiDmaapEventConsumerProperties.setProperty("DME2preferredRouterFilePath", this.preferredRouterFilePath);
+ if (aaiDmaapEventConsumerProperties.getProperty("password") != null
+ && aaiDmaapEventConsumerProperties.getProperty("password").startsWith("OBF:")) {
+ aaiDmaapEventConsumerProperties.setProperty("password",
+ Password.deobfuscate(aaiDmaapEventConsumerProperties.getProperty("password")));
+ }
+ LOGGER.debug("Updated " + this.aaiDmaapEventConsumerPropertiesFile + " DME2preferredRouterFilePath property to "
+ + this.preferredRouterFilePath);
+
+ if (getIsInitialCheck()) {
+ aaiDmaapEventConsumerProperties.setProperty("limit", "1");
+ }
+ LOGGER.debug("Using limit " + aaiDmaapEventConsumerProperties.getProperty("limit"));
+ LOGGER.debug("Using filter " + aaiDmaapEventConsumerProperties.getProperty("filter"));
+ }
+
+ public void startProcessing(DmaapProcessor dmaapProcessor) throws Exception {
+ int fetchFailCounter = 0;
+
+ while (AAIConfig.get("aai.cacher.dmaap.consumer.enableEventProcessing").equals("true")) {
+ try {
+ LOGGER.debug("processEvents=" + dmaapConsumerSingleton.getProcessEvents() + " isInitialized="
+ + dmaapConsumerSingleton.getIsInitialized());
+ if (dmaapConsumerSingleton.getProcessEvents() || !dmaapConsumerSingleton.getIsInitialized()) {
+ Iterable<String> eventMessages = clientConsumer.process();
+ if (dmaapConsumerSingleton.getFirstEventMessage() != null) {
+ String firstMessage = getFirstMessage();
+ if (firstMessage != null) {
+ LOGGER.debug("Processing held dmaap message from the aaiDmaapEvent topic." + transId);
+ LOGGER.debug("Processing held dmaap message from the aaiDmaapEvent topic: " + firstMessage);
+ dmaapProcessor.process(firstMessage);
+ }
+ }
+ for (String eventMessage : eventMessages) {
+ if (!dmaapConsumerSingleton.getProcessEvents()) {
+ // hold message until app is ready for dmaap processing
+ setFirstMessage(eventMessage);
+ LOGGER.debug("Holding new dmaap message from the aaiDmaapEvent topic: " + eventMessage);
+ dmaapConsumerSingleton.setIsInitialized(true);
+ continue;
+ }
+ LOGGER.debug("Processing held dmaap message from the aaiDmaapEvent topic: " + eventMessage);
+ dmaapProcessor.process(eventMessage);
+ }
+ fetchFailCounter = 0;
+ } else {
+ // not processing events
+ this.aaiDmaapEventConsumer.close();
+ return;
+ }
+ break;
+ } catch (IOException e) {
+ fetchFailCounter++;
+ if (fetchFailCounter > 10) {
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ this.aaiDmaapEventConsumer.close();
+ throw e;
+ }
+ LOGGER.info("ignoring IOException, count is at." + fetchFailCounter);
+ } catch (Exception e) {
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+
+ e.printStackTrace();
+ this.aaiDmaapEventConsumer.close();
+ e.printStackTrace();
+ throw e;
+ }
+ }
+ this.aaiDmaapEventConsumer.close();
+ }
+
+ /**
+ * checks on processing events flag
+ *
+ * @return
+ */
+ private boolean getIsInitialCheck() {
+ dmaapConsumerSingleton = DmaapConsumerSingleton.getInstance();
+ if (dmaapConsumerSingleton.getProcessEvents()) {
+ return false;
+ }
+ return !dmaapConsumerSingleton.getIsInitialized();
+ }
+
+ /**
+ * used to hold the first event message received before the app is ready to
+ * process
+ */
+
+ private void setFirstMessage(String message) {
+ dmaapConsumerSingleton.setFirstEventMessage(message);
+ }
+
+ /**
+ * used to get the first event message being held before the app is ready to
+ * process
+ */
+
+ private String getFirstMessage() {
+ String message = dmaapConsumerSingleton.getFirstEventMessage();
+ dmaapConsumerSingleton.setFirstEventMessage(null);
+ return message;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/ClientConsumer.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/ClientConsumer.java
new file mode 100644
index 0000000..eaa341b
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/ClientConsumer.java
@@ -0,0 +1,31 @@
+/**
+ * ============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.cacher.dmaap.consumer;
+
+/**
+ * Interface that encapsulates the MRConsumer to switch between using just
+ * MRConsumer or to use MRConsumer with RestClient for environments where dme2
+ * is having problems
+ */
+public interface ClientConsumer {
+
+ Iterable<String> process() throws Exception;
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapConsumerSingleton.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapConsumerSingleton.java
new file mode 100644
index 0000000..5c2faa3
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapConsumerSingleton.java
@@ -0,0 +1,77 @@
+/**
+ * ============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.cacher.dmaap.consumer;
+
+public class DmaapConsumerSingleton {
+
+ private boolean processEvents;
+ private boolean isInitialized;
+
+ private String dmaapConsumerId;
+
+ private String firstEventMessage;
+
+ private static class Helper {
+ private static final DmaapConsumerSingleton INSTANCE = new DmaapConsumerSingleton();
+ }
+
+ public static DmaapConsumerSingleton getInstance() {
+ return Helper.INSTANCE;
+ }
+
+ private DmaapConsumerSingleton() {
+ processEvents = false;
+ isInitialized = false;
+ firstEventMessage = null;
+ dmaapConsumerId = null;
+ }
+
+ public void setProcessEvents(boolean processEvents) {
+ this.processEvents = processEvents;
+ }
+
+ public boolean getProcessEvents() {
+ return processEvents;
+ }
+
+ public void setIsInitialized(boolean isInitialized) {
+ this.isInitialized = isInitialized;
+ }
+
+ public boolean getIsInitialized() {
+ return isInitialized;
+ }
+
+ public void setFirstEventMessage(String firstEventMessage) {
+ this.firstEventMessage = firstEventMessage;
+ }
+
+ public String getFirstEventMessage() {
+ return firstEventMessage;
+ }
+
+ public void setDmaapConsumerId(String dmaapConsumerId) {
+ this.dmaapConsumerId = dmaapConsumerId;
+ }
+
+ public String getDmaapConsumerId() {
+ return dmaapConsumerId;
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapProcessor.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapProcessor.java
new file mode 100644
index 0000000..6cb4b82
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/DmaapProcessor.java
@@ -0,0 +1,32 @@
+/**
+ * ============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.cacher.dmaap.consumer;
+
+/**
+ * <b>DmaapProcessor</b> is the interface to use to process dmaap consumer
+ * events
+ *
+ * Any new topic that needs to be subscribed should implement this interface to
+ * process the events received by the dmaap publisher
+ */
+public interface DmaapProcessor {
+
+ void process(String eventMessage) throws Exception;
+}
diff --git a/src/main/java/org/onap/aai/cacher/dmaap/consumer/RestDmaapClientConsumer.java b/src/main/java/org/onap/aai/cacher/dmaap/consumer/RestDmaapClientConsumer.java
new file mode 100644
index 0000000..5839934
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/dmaap/consumer/RestDmaapClientConsumer.java
@@ -0,0 +1,80 @@
+/**
+ * ============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.cacher.dmaap.consumer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.att.nsa.mr.client.MRConsumer;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.util.Base64;
+import java.util.Properties;
+
+/**
+ * Encapsulates the MRConsumer and invokes it only if the environment is dev,
+ * testINT, testEXT If its one of those environments, uses the RestClient
+ */
+public class RestDmaapClientConsumer implements ClientConsumer {
+
+ private MRConsumer aaiDmaapEventConsumer;
+
+ private static final Base64.Encoder base64Encoder = Base64.getEncoder();
+
+ private HttpHeaders httpHeaders;
+ private RestTemplate restTemplate;
+
+ private String env;
+ // private String url;
+ private UriComponentsBuilder builder;
+
+ private Properties consumerProperties;
+
+ private static EELFLogger LOGGER = EELFManager.getInstance().getLogger(RestDmaapClientConsumer.class);
+
+ public RestDmaapClientConsumer(MRConsumer consumer, Properties aaiDmaapEventConsumerProperties) {
+
+ env = System.getProperty("lrmRO");
+
+ this.aaiDmaapEventConsumer = consumer;
+ this.consumerProperties = aaiDmaapEventConsumerProperties;
+
+ }
+
+ /**
+ * Checks if the environment is null or if the environment starts with dev,
+ * testEXT, or testINT and then if that is the case, it makes a request to the
+ * url to subscribe to that topic to retrieve all messages there If it is not
+ * one of those environments, then it will call the default fetch of messages
+ * from the MR Consumer
+ *
+ * @return a list of messages from the topic
+ * @throws Exception
+ */
+ @Override
+ public Iterable<String> process() throws Exception {
+
+ Iterable<String> messages = aaiDmaapEventConsumer.fetch();
+
+ LOGGER.debug("Finished the consumption of messages from dmaap");
+ return messages;
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactory.java b/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactory.java
new file mode 100644
index 0000000..af6384f
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactory.java
@@ -0,0 +1,35 @@
+/**
+ * ============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.cacher.egestion.printer;
+
+import org.onap.aai.cacher.egestion.printer.strategy.PayloadPrinterStrategy;
+import org.onap.aai.cacher.egestion.printer.strategy.PayloadPrinterType;
+
+/**
+ * Factory to get parser strategy based on parser type.
+ */
+public interface PayloadPrinterFactory {
+ /**
+ *
+ * @param payloadParserType payload parser strategy type to use
+ * @return
+ */
+ PayloadPrinterStrategy getPayloadPrinterStrategy(PayloadPrinterType payloadParserType);
+}
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactoryConfiguration.java b/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactoryConfiguration.java
new file mode 100644
index 0000000..abbc30a
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterFactoryConfiguration.java
@@ -0,0 +1,36 @@
+/**
+ * ============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.cacher.egestion.printer;
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.config.ServiceLocatorFactoryBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class PayloadPrinterFactoryConfiguration {
+
+ @Bean
+ public FactoryBean locatorFactoryBean() {
+ ServiceLocatorFactoryBean bean = new ServiceLocatorFactoryBean();
+ bean.setServiceLocatorInterface(PayloadPrinterFactory.class);
+ return bean;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterService.java b/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterService.java
new file mode 100644
index 0000000..6acea02
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/PayloadPrinterService.java
@@ -0,0 +1,43 @@
+/**
+ * ============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.cacher.egestion.printer;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import org.onap.aai.cacher.egestion.printer.strategy.PayloadPrinterStrategy;
+import org.onap.aai.cacher.egestion.printer.strategy.PayloadPrinterType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class PayloadPrinterService {
+ @Autowired
+ private PayloadPrinterFactory payloadPrinterFactory;
+
+ public JsonObject createJson(String collectionName, JsonArray jsonArray, PayloadPrinterType payloadParserType) {
+ PayloadPrinterStrategy printer = payloadPrinterFactory.getPayloadPrinterStrategy(payloadParserType);
+ return printer.createJson(collectionName, jsonArray);
+ }
+
+ public JsonObject createJson(String collectionName, JsonArray jsonArray, String parserStrategy) {
+ return createJson(collectionName, jsonArray, PayloadPrinterType.fromString(parserStrategy + "-printer"));
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/AAIResourceGetAllPayloadPrinterStrategy.java b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/AAIResourceGetAllPayloadPrinterStrategy.java
new file mode 100644
index 0000000..8dfeb0b
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/AAIResourceGetAllPayloadPrinterStrategy.java
@@ -0,0 +1,49 @@
+/**
+ * ============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.cacher.egestion.printer.strategy;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Component(value = "aai-resource-get-all-printer")
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class AAIResourceGetAllPayloadPrinterStrategy implements PayloadPrinterStrategy {
+
+ /**
+ * Create a jsonObject from the jsonArray for a specific collection
+ *
+ * @param collectionName
+ * @param jsonArray
+ * @return
+ */
+ @Override
+ public JsonObject createJson(String collectionName, JsonArray jsonArray) {
+ if (jsonArray != null && jsonArray.size() > 0) {
+ JsonObject jsonObj = new JsonObject();
+ jsonObj.add(collectionName, jsonArray);
+ return jsonObj;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/NonePayloadPrinterStrategy.java b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/NonePayloadPrinterStrategy.java
new file mode 100644
index 0000000..3aecfe8
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/NonePayloadPrinterStrategy.java
@@ -0,0 +1,42 @@
+/**
+ * ============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.cacher.egestion.printer.strategy;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+/**
+ * Default parser strategy that dont not manipulate the payload.
+ */
+@Component(value = "none-printer")
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class NonePayloadPrinterStrategy implements PayloadPrinterStrategy {
+ @Override
+ public JsonObject createJson(String collectionName, JsonArray jsonArray) {
+ if (jsonArray != null && jsonArray.size() > 0) {
+ return jsonArray.get(0).getAsJsonObject();
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterStrategy.java b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterStrategy.java
new file mode 100644
index 0000000..b6d3f08
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterStrategy.java
@@ -0,0 +1,28 @@
+/**
+ * ============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.cacher.egestion.printer.strategy;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+
+public interface PayloadPrinterStrategy {
+
+ JsonObject createJson(String collectionName, JsonArray jsonArray);
+}
diff --git a/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterType.java b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterType.java
new file mode 100644
index 0000000..d83d622
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/egestion/printer/strategy/PayloadPrinterType.java
@@ -0,0 +1,46 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.egestion.printer.strategy;
+
+import java.util.Arrays;
+
+public enum PayloadPrinterType {
+
+ NONE_PRINTER("none-printer"), AAI_RESOURCE_GET_ALL_PRINTER("aai-resource-get-all-printer");
+
+ private final String value;
+
+ PayloadPrinterType(String input) {
+ this.value = input;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ return this.value;
+ }
+
+ public static PayloadPrinterType fromString(String text) {
+ return Arrays.stream(values()).filter(bl -> bl.getValue().equalsIgnoreCase(text)).findFirst().orElse(null);
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/AAIResourcesUriTemplates.java b/src/main/java/org/onap/aai/cacher/injestion/parser/AAIResourcesUriTemplates.java
new file mode 100644
index 0000000..0885851
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/AAIResourcesUriTemplates.java
@@ -0,0 +1,208 @@
+/**
+ * ============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.cacher.injestion.parser;
+
+import com.google.gson.JsonObject;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.aai.cacher.util.AAIConstants;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+import org.springframework.web.util.UriTemplate;
+import org.springframework.web.util.UriUtils;
+
+import javax.ws.rs.core.UriBuilder;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.*;
+
+@Component
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class AAIResourcesUriTemplates {
+
+ private final Map<String, String> typeToUriTemplate;
+
+ public AAIResourcesUriTemplates() throws IOException {
+ InputStream inputStream = new FileInputStream(AAIConstants.AAI_RESOURCES_URI_TEMPLATES);
+ Properties prop = new Properties();
+ prop.load(inputStream);
+
+ typeToUriTemplate = new HashMap<>(prop.size() + 1);
+ for (final String type : prop.stringPropertyNames()) {
+ typeToUriTemplate.put(type, prop.getProperty(type));
+ if (!typeToUriTemplate.containsKey("relationship")) {
+ typeToUriTemplate.put("relationship", "/relationship-list/relationship/{related-link}");
+ }
+ }
+ }
+
+ /**
+ * Get templated aai uri segment by type.
+ *
+ * @param type
+ * @return
+ */
+ public String getUriTemplateByType(String type) {
+ return typeToUriTemplate.get(type);
+ }
+
+ public Map<String, String> getUriTemplateMappings(String uri, String template) {
+
+ UriTemplate uriTemplate = new UriTemplate(template);
+ Map<String, String> mappings = uriTemplate.match(uri);
+
+ mappings.replaceAll((k, v) -> this.decodeProp(v));
+
+ return mappings;
+ }
+
+ /**
+ * For a given uri get an ordered list of templates.
+ *
+ * @param uri
+ * @return
+ */
+ public List<String> uriToTemplates(String uri) {
+ List<String> uriTemplateList = new ArrayList<>();
+ String template = "";
+ String truncatedUri = uri;
+
+ while (truncatedUri.contains("/")) {
+ template = this.getMatchingStartingTemplate(truncatedUri).get();
+ uriTemplateList.add(template);
+ int count = StringUtils.countMatches(template, "/");
+ if (count < StringUtils.countMatches(truncatedUri, "/")) {
+ truncatedUri = StringUtils.substring(truncatedUri,
+ StringUtils.ordinalIndexOf(truncatedUri, "/", count + 1));
+ } else {
+ truncatedUri = "";
+ }
+ }
+
+ return uriTemplateList;
+ }
+
+ /**
+ * For a given uri get an ordered list of templates.
+ *
+ * @param uri
+ * @return
+ */
+ public List<String> uriToSegments(String uri) {
+ List<String> uriList = new ArrayList<>();
+ String template = "";
+ String truncatedUri = uri;
+
+ while (truncatedUri.contains("/")) {
+ template = this.getMatchingStartingTemplate(truncatedUri).get();
+ int count = StringUtils.countMatches(template, "/");
+ int cutIndex = truncatedUri.length();
+ if (count != StringUtils.countMatches(truncatedUri, "/")) {
+ cutIndex = StringUtils.ordinalIndexOf(truncatedUri, "/", count + 1);
+ }
+ uriList.add(StringUtils.substring(truncatedUri, 0, cutIndex));
+ truncatedUri = StringUtils.substring(truncatedUri, cutIndex);
+ }
+
+ return uriList;
+ }
+
+ /**
+ * returns the template matching the start of the uri.
+ *
+ * @param uri
+ * @return @see java.util.Optional
+ */
+ public Optional<String> getMatchingStartingTemplate(String uri) {
+ return typeToUriTemplate.values().stream().filter(s -> uri.startsWith(s.split("/\\{")[0])).findFirst();
+ }
+
+ /**
+ * Given aai type and json object generate the uri for it.
+ *
+ * @param type
+ * @param jo
+ * @return
+ */
+ public String getUri(String type, JsonObject jo) {
+ String uriTemplate = getUriTemplateByType(type);
+ UriBuilder uriBuilder = UriBuilder.fromPath(uriTemplate);
+ List<String> keys = getUriKeys(uriTemplate);
+ Map<String, String> mapping = getEncodedMapping(keys, jo);
+
+ return uriBuilder.buildFromEncodedMap(mapping).toString();
+ }
+
+ /**
+ * Get encoded values from json object for each key in keys
+ *
+ * @param keys
+ * @param jo
+ * @return
+ */
+ private Map<String, String> getEncodedMapping(List<String> keys, JsonObject jo) {
+ final Map<String, String> mapping = new HashMap<>();
+ keys.forEach(key -> mapping.put(key, encodeProp(jo.get(key).getAsString())));
+
+ return mapping;
+ }
+
+ /**
+ * extract uri keys from the templated uri
+ *
+ * @param template
+ * @return
+ */
+ private List<String> getUriKeys(String template) {
+
+ UriTemplate uriTemplate = new UriTemplate(template);
+ return uriTemplate.getVariableNames();
+ }
+
+ /**
+ * UTF-8 encoding of @param string
+ *
+ * @param string string to be encoded
+ * @return
+ */
+ public String encodeProp(String string) {
+ try {
+ return UriUtils.encode(string, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ return "";
+ }
+ }
+
+ /**
+ * UTF-8 decoding of @param string
+ *
+ * @param string string to be encoded
+ * @return
+ */
+ public String decodeProp(String string) {
+ try {
+ return UriUtils.decode(string, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ return "";
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactory.java b/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactory.java
new file mode 100644
index 0000000..bd36e8f
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactory.java
@@ -0,0 +1,35 @@
+/**
+ * ============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.cacher.injestion.parser;
+
+import org.onap.aai.cacher.injestion.parser.strategy.PayloadParserStrategy;
+import org.onap.aai.cacher.injestion.parser.strategy.PayloadParserType;
+
+/**
+ * Factory to get parser strategy based on parser type.
+ */
+public interface PayloadParserFactory {
+ /**
+ *
+ * @param ppse payload parser strategy type to use
+ * @return
+ */
+ PayloadParserStrategy getPayloadParserStrategy(PayloadParserType ppse);
+}
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactoryConfiguration.java b/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactoryConfiguration.java
new file mode 100644
index 0000000..28424cb
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserFactoryConfiguration.java
@@ -0,0 +1,36 @@
+/**
+ * ============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.cacher.injestion.parser;
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.config.ServiceLocatorFactoryBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class PayloadParserFactoryConfiguration {
+
+ @Bean
+ public FactoryBean serviceLocatorFactoryBean() {
+ ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean();
+ factoryBean.setServiceLocatorInterface(PayloadParserFactory.class);
+ return factoryBean;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserService.java b/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserService.java
new file mode 100644
index 0000000..1d7b38c
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/PayloadParserService.java
@@ -0,0 +1,71 @@
+/**
+ * ============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.cacher.injestion.parser;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.onap.aai.cacher.injestion.parser.strategy.PayloadParserStrategy;
+import org.onap.aai.cacher.injestion.parser.strategy.PayloadParserType;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * Service to be use to interact with parsers.
+ */
+@Service
+public class PayloadParserService {
+
+ private PayloadParserFactory payloadParserFactory;
+
+ @Autowired
+ public PayloadParserService(PayloadParserFactory payloadParserFactory) {
+ this.payloadParserFactory = payloadParserFactory;
+ }
+
+ public List<CacheEntry> doParse(String cacheKey, JsonObject jo, PayloadParserType payloadParserType) {
+
+ PayloadParserStrategy parser = payloadParserFactory.getPayloadParserStrategy(payloadParserType);
+ return parser.process(cacheKey, jo);
+ }
+
+ public List<CacheEntry> doParse(String cacheKey, JsonObject jo, String payloadParserTypeStr) {
+ return doParse(cacheKey, jo, PayloadParserType.fromString(payloadParserTypeStr));
+ }
+
+ public List<CacheEntry> doParse(String cacheKey, JsonObject jo) {
+ return this.doParse(cacheKey, jo, PayloadParserType.NONE);
+ }
+
+ public List<CacheEntry> doParse(String cacheKey, String jo, PayloadParserType payloadParserType) {
+ JsonParser jsonParser = new JsonParser();
+ return doParse(cacheKey, jsonParser.parse(jo).getAsJsonObject(), payloadParserType);
+ }
+
+ public List<CacheEntry> doParse(String cacheKey, String jo, String payloadParserTypeStr) {
+ return doParse(cacheKey, jo, PayloadParserType.fromString(payloadParserTypeStr));
+ }
+
+ public List<CacheEntry> doParse(String cacheKey, String jo) {
+ return this.doParse(cacheKey, jo, PayloadParserType.NONE);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategy.java b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategy.java
new file mode 100644
index 0000000..6de0585
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategy.java
@@ -0,0 +1,470 @@
+/**
+ * ============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.cacher.injestion.parser.strategy;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.aai.cacher.injestion.parser.AAIResourcesUriTemplates;
+import org.onap.aai.cacher.injestion.parser.PayloadParserService;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.cacher.model.DBAction;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * AAI resource get all parser strategy
+ */
+@Component(value = "aai-resource-dmaap")
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class AAIResourceDmaapParserStrategy implements PayloadParserStrategy {
+
+ protected AAIResourcesUriTemplates aaiResourcesUriTemplates;
+
+ private PayloadParserService payloadParserService;
+
+ private DmaapAction actionType;
+
+ @Autowired
+ public AAIResourceDmaapParserStrategy(AAIResourcesUriTemplates aaiResourcesUriTemplates,
+ PayloadParserService payloadParserService) {
+ this.aaiResourcesUriTemplates = aaiResourcesUriTemplates;
+ this.payloadParserService = payloadParserService;
+ }
+
+ /**
+ * Parses aai resources specific payloads generating the details for caching.
+ *
+ * @param originalKey
+ * @param jsonObject
+ * @return
+ */
+ @Override
+ public List<CacheEntry> process(String originalKey, JsonObject jsonObject) {
+ final List<CacheEntry> cacheEntries = new ArrayList<>();
+
+ JsonObject header = jsonObject.getAsJsonObject("event-header");
+ JsonObject entity = jsonObject.getAsJsonObject("entity");
+ String topEntity = header.get("top-entity-type").getAsString();
+
+ actionType = DmaapAction.valueOf(header.get("action").getAsString());
+ boolean isTopLevel = topEntity.equals(header.get("entity-type").getAsString());
+ String fullUri = getFullUri(header);
+
+ CacheEntry cacheEntry = generateCacheEntry(entity, actionType, isTopLevel, fullUri);
+
+ cacheEntries.add(cacheEntry);
+
+ // determine relationships on the other end that need to be modified.
+ MultiValueMap<String, AAIResourceDmaapParserStrategy.AAIRelatedToDetails> relationships;
+ if (isTopLevel) {
+ relationships = getFromRelationshipFullUriToRelationshipObj(entity, fullUri);
+ } else {
+ relationships = getFromRelationshipFullUriToRelationshipObj(entity, getBaseUri(fullUri));
+ }
+ if (jsonObject.has("existing-obj")) {
+ adjustRelationshipsBasedOnExisting(jsonObject, fullUri, relationships);
+ }
+
+ JsonObject relatedToObj;
+ for (Map.Entry<String, List<AAIResourceDmaapParserStrategy.AAIRelatedToDetails>> relationship : relationships
+ .entrySet()) {
+ for (AAIResourceDmaapParserStrategy.AAIRelatedToDetails aaiRelatedToDetails : relationship.getValue()) {
+ relatedToObj = fullUriToRelationshipObj(relationship.getKey(), aaiRelatedToDetails.getLabel());
+ cacheEntries.add(generateCacheEntry(relatedToObj, aaiRelatedToDetails.getActionType(), false,
+ aaiRelatedToDetails.getFullUri() + "/relationship-list/relationship/"
+ + aaiResourcesUriTemplates.encodeProp(relationship.getKey())));
+ }
+ }
+
+ return cacheEntries;
+ }
+
+ private String getBaseUri(String fullUri) {
+ String uri = getUri(fullUri);
+ List<AAIUriSegment> uriSegmentList = getAaiUriSegments(uri);
+ return uriSegmentList.get(0).getSegment();
+ }
+
+ protected String getFullUriPrefix(String fullUri) {
+ return StringUtils.substring(fullUri, 0, StringUtils.ordinalIndexOf(fullUri, "/", 3));
+ }
+
+ protected CacheEntry generateCacheEntry(JsonObject entity, DmaapAction actionType, boolean isTopLevel,
+ String fullUri) {
+ String uri = getUri(fullUri);
+ List<AAIUriSegment> uriSegmentList = getAaiUriSegments(uri);
+ String id = uriSegmentList.get(0).getSegment();
+ String collection = uriSegmentList.get(0).getSegmentSingular();
+ JsonObject entityBody = getEntityBody(entity, uriSegmentList);
+ JsonObject findQuery = getFindQuery(uriSegmentList);
+ JsonObject nestedFindQuery = getNestedFindQuery(uriSegmentList);
+ String nestedField = getNestedField(uriSegmentList);
+ JsonObject nestedIdentifier = getNestedIdentifier(uriSegmentList);
+ DBAction dbAction = getDBAction(actionType);
+
+ return CacheEntry.CacheEntryBuilder.createCacheEntry().inCollection(collection).withDbAction(dbAction)
+ .withId(id).isNested(!isTopLevel).withPayload(entityBody).withFindQuery(findQuery)
+ .withNestedFind(nestedFindQuery).withNestedField(nestedField)
+ .withNestedFieldIdentifierObj(nestedIdentifier).build();
+ }
+
+ protected DBAction getDBAction(DmaapAction actionType) {
+ DBAction dbAction = DBAction.INSERT_REPLACE;
+ switch (actionType) {
+ case CREATE:
+ dbAction = DBAction.INSERT_REPLACE;
+ break;
+ case DELETE:
+ dbAction = DBAction.DELETE;
+ break;
+ case UPDATE:
+ dbAction = DBAction.UPDATE;
+ break;
+ }
+ return dbAction;
+ }
+
+ protected JsonObject getNestedIdentifier(List<AAIUriSegment> uriSegmentList) {
+ final JsonObject nestedIdentifier = new JsonObject();
+ if (uriSegmentList.size() > 1) {
+ AAIUriSegment lastSegment = uriSegmentList.get(uriSegmentList.size() - 1);
+ lastSegment.getSegmentKeyValues().forEach(nestedIdentifier::addProperty);
+ }
+ return nestedIdentifier;
+ }
+
+ protected String getNestedField(List<AAIUriSegment> uriSegmentList) {
+ StringBuilder nestedField = new StringBuilder();
+
+ if (uriSegmentList.size() > 1) {
+ if (uriSegmentList.get(1).getSegmentPlural().isPresent()) {
+ nestedField.append(uriSegmentList.get(1).getSegmentPlural().get()).append(".")
+ .append(uriSegmentList.get(1).getSegmentSingular());
+ } else {
+ nestedField.append(uriSegmentList.get(1).getSegmentSingular());
+ }
+
+ for (int i = 2; i < uriSegmentList.size(); i++) {
+ if (uriSegmentList.get(i).getSegmentPlural().isPresent()) {
+ nestedField.append(".$.").append(uriSegmentList.get(i).getSegmentPlural().get()).append(".")
+ .append(uriSegmentList.get(i).getSegmentSingular());
+ } else {
+ nestedField.append(".$.").append(uriSegmentList.get(i).getSegmentSingular());
+ }
+ }
+ }
+ return nestedField.toString();
+ }
+
+ protected JsonObject getNestedFindQuery(List<AAIUriSegment> uriSegmentList) {
+ return getFindQuery(uriSegmentList, true);
+ }
+
+ protected JsonObject getFindQuery(List<AAIUriSegment> uriSegmentList) {
+ return getFindQuery(uriSegmentList, false);
+ }
+
+ protected JsonObject getFindQuery(List<AAIUriSegment> uriSegmentList, boolean isNested) {
+ final JsonObject findQuery = new JsonObject();
+ if (uriSegmentList.isEmpty()) {
+ return findQuery;
+ }
+
+ AAIUriSegment aaiUriSegment = uriSegmentList.get(0);
+ findQuery.addProperty("_id", aaiUriSegment.getSegment());
+ aaiUriSegment.getSegmentKeyValues().forEach(findQuery::addProperty);
+
+ StringBuilder nestedField = new StringBuilder();
+ int segmentToProcess = uriSegmentList.size();
+ if (!isNested) {
+ segmentToProcess--;
+ }
+ for (int i = 1; i < segmentToProcess; i++) {
+ aaiUriSegment = uriSegmentList.get(i);
+ if (nestedField.length() != 0) {
+ nestedField.append(".");
+ }
+ if (aaiUriSegment.getSegmentPlural().isPresent()) {
+ nestedField.append(aaiUriSegment.getSegmentPlural().get()).append(".");
+ }
+ nestedField.append(aaiUriSegment.getSegmentSingular());
+ aaiUriSegment.getSegmentKeyValues()
+ .forEach((k, v) -> findQuery.addProperty(nestedField.toString() + "." + k, v));
+ }
+ return findQuery;
+ }
+
+ /**
+ * strips away the parent wrapping from the dmaap events entity payload
+ *
+ * @param entity
+ * @param uriSegmentList
+ * @return
+ */
+ protected JsonObject getEntityBody(JsonObject entity, List<AAIUriSegment> uriSegmentList) {
+
+ if (uriSegmentList.size() == 1) {
+ return entity;
+ }
+
+ JsonObject entityBody = entity.getAsJsonObject();
+
+ // if processing relationship no need to look for nested obj, entity is the obj
+ if (!"relationship".equals(uriSegmentList.get(uriSegmentList.size() - 1).getSegmentSingular())) {
+ for (int i = 1; i < uriSegmentList.size(); i++) {
+ if (uriSegmentList.get(i).getSegmentPlural().isPresent()) {
+ entityBody = entityBody.getAsJsonObject(uriSegmentList.get(i).getSegmentPlural().get())
+ .getAsJsonArray(uriSegmentList.get(i).getSegmentSingular()).get(0).getAsJsonObject();
+ } else {
+ entityBody = entityBody.getAsJsonArray(uriSegmentList.get(i).getSegmentSingular()).get(0)
+ .getAsJsonObject();
+ }
+
+ }
+ }
+
+ return entityBody;
+
+ }
+
+ protected List<AAIUriSegment> getAaiUriSegments(String uri) {
+ List<String> uriSegmentTemplates = aaiResourcesUriTemplates.uriToTemplates(uri);
+ List<String> uriSegments = aaiResourcesUriTemplates.uriToSegments(uri);
+
+ List<AAIUriSegment> uriSegmentList = new ArrayList<>(uriSegments.size());
+
+ AAIUriSegment aus;
+ for (int i = 0; i < uriSegments.size(); i++) {
+ aus = new AAIUriSegment(uriSegments.get(i), uriSegmentTemplates.get(i));
+ aus.setSegmentKeyValues(
+ aaiResourcesUriTemplates.getUriTemplateMappings(aus.getSegment(), aus.getSegmentTemplate()));
+ uriSegmentList.add(aus);
+ }
+ return uriSegmentList;
+ }
+
+ /**
+ * For update events with an existing obj available adjust the cache actions to
+ * be taken on relationship objects.
+ *
+ * @param jsonObject
+ * @param fullUri
+ * @param newObjectRelationships
+ */
+ private void adjustRelationshipsBasedOnExisting(JsonObject jsonObject, String fullUri,
+ MultiValueMap<String, AAIResourceDmaapParserStrategy.AAIRelatedToDetails> newObjectRelationships) {
+ JsonObject existingObj = jsonObject.getAsJsonObject("existing-obj");
+ MultiValueMap<String, AAIResourceDmaapParserStrategy.AAIRelatedToDetails> oldRelationships = getFromRelationshipFullUriToRelationshipObj(
+ existingObj, fullUri);
+ oldRelationships.forEach((k, v) -> {
+ if (newObjectRelationships.containsKey(k)) {
+ v.forEach(oldA -> {
+ int found = -1;
+ for (int i = 0; i < newObjectRelationships.get(k).size(); i++) {
+ if (newObjectRelationships.get(k).get(i).getFullUri().equals(oldA.getFullUri())) {
+ found = i;
+ break;
+ }
+ }
+ if (found != -1) {
+ newObjectRelationships.get(k).remove(newObjectRelationships.get(k).get(found));
+ } else {
+ oldA.setActionType(DmaapAction.DELETE);
+ newObjectRelationships.get(k).add(oldA);
+ }
+ });
+ } else {
+ v.forEach(aaiRelatedToDetails -> {
+ aaiRelatedToDetails.setActionType(DmaapAction.DELETE);
+ newObjectRelationships.add(k, aaiRelatedToDetails);
+ });
+ }
+ });
+ }
+
+ /**
+ * Given fullUri uri generate an aai relationship obj
+ *
+ * @param fullUri
+ * @return
+ */
+ protected JsonObject fullUriToRelationshipObj(String fullUri, String label) {
+ final JsonObject relObj = new JsonObject();
+ final JsonArray relData = new JsonArray();
+ String uri = getUri(fullUri);
+ List<AAIUriSegment> uriSegmentList = getAaiUriSegments(uri);
+
+ relObj.addProperty("related-to", uriSegmentList.get(uriSegmentList.size() - 1).getSegmentSingular());
+ if (label != null) {
+ relObj.addProperty("relationship-label", label);
+ }
+ relObj.addProperty("related-link", fullUri);
+
+ for (AAIUriSegment aaiUriSegment : uriSegmentList) {
+ aaiUriSegment.getSegmentKeyValues().forEach((k, v) -> {
+ JsonObject relDataEntry;
+ relDataEntry = new JsonObject();
+ relDataEntry.addProperty("relationship-key", aaiUriSegment.getSegmentSingular() + "." + k);
+ relDataEntry.addProperty("relationship-value", v);
+ relData.add(relDataEntry);
+ });
+ }
+ relObj.add("relationship-data", relData);
+
+ return relObj;
+ }
+
+ /**
+ *
+ * @param entity
+ * @param fullUri
+ * @return
+ */
+ protected MultiValueMap<String, AAIResourceDmaapParserStrategy.AAIRelatedToDetails> getFromRelationshipFullUriToRelationshipObj(
+ JsonObject entity, String fullUri) {
+ final MultiValueMap<String, AAIResourceDmaapParserStrategy.AAIRelatedToDetails> relationshipMapping = new LinkedMultiValueMap<>();
+ for (Map.Entry<String, JsonElement> e : entity.entrySet()) {
+ if (e.getKey().equals("relationship-list") && e.getValue().isJsonObject()) {
+ JsonArray relationships = e.getValue().getAsJsonObject().getAsJsonArray("relationship");
+ for (JsonElement relationship : relationships) {
+ relationshipMapping.add(fullUri, new AAIResourceDmaapParserStrategy.AAIRelatedToDetails(
+ relationship.getAsJsonObject().get("related-link").getAsString(),
+ relationship.getAsJsonObject().get("relationship-label").getAsString(), actionType));
+ }
+ } else if (e.getValue().isJsonObject() && e.getValue().getAsJsonObject().entrySet().size() == 1) {
+ Map.Entry<String, JsonElement> entry = e.getValue().getAsJsonObject().entrySet().iterator().next();
+ if (entry.getValue().isJsonArray()) {
+ String type = entry.getKey();
+ JsonArray children = entry.getValue().getAsJsonArray();
+ for (JsonElement child : children) {
+ relationshipMapping.putAll(getFromRelationshipFullUriToRelationshipObj(child.getAsJsonObject(),
+ fullUri + aaiResourcesUriTemplates.getUri(type, child.getAsJsonObject())));
+ }
+ }
+ }
+ }
+ return relationshipMapping;
+ }
+
+ protected String getUri(String fullUri) {
+ return fullUri.replaceAll("/aai/v\\d+", "");
+ }
+
+ protected String getFullUri(JsonObject header) {
+ return header.get("entity-link").getAsString();
+ }
+
+ protected enum DmaapAction {
+ DELETE, UPDATE, CREATE
+ }
+
+ class AAIUriSegment {
+
+ private String segment;
+ private String segmentTemplate;
+ private Optional<String> segmentPlural = Optional.empty();
+ private String segmentSingular;
+ private Map<String, String> segmentKeyValues;
+
+ AAIUriSegment(String segment, String template) {
+ this.segment = segment;
+ this.segmentTemplate = template;
+ String[] segmentSplit = segment.split("/");
+ String[] templateSplit = template.split("/");
+ for (int i = 0; i < templateSplit.length; i++) {
+ if (templateSplit[i].contains("{")) {
+ segmentSingular = segmentSplit[i - 1];
+ if (!"".equals(segmentSplit[i - 2])) {
+ segmentPlural = Optional.of(segmentSplit[i - 2]);
+ }
+ break;
+ }
+ }
+ }
+
+ String getSegment() {
+ return segment;
+ }
+
+ String getSegmentTemplate() {
+ return segmentTemplate;
+ }
+
+ Map<String, String> getSegmentKeyValues() {
+ return segmentKeyValues;
+ }
+
+ void setSegmentKeyValues(Map<String, String> segmentKeyValues) {
+ this.segmentKeyValues = segmentKeyValues;
+ }
+
+ Optional<String> getSegmentPlural() {
+ return segmentPlural;
+ }
+
+ String getSegmentSingular() {
+ return segmentSingular;
+ }
+ }
+
+ class AAIRelatedToDetails {
+ private String fullUri;
+ private String label;
+ private DmaapAction actionType;
+
+ public AAIRelatedToDetails(String fullUri, String label, DmaapAction actionType) {
+ this.fullUri = fullUri;
+ this.label = label;
+ this.actionType = actionType;
+ }
+
+ public String getFullUri() {
+ return fullUri;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public DmaapAction getActionType() {
+ return actionType;
+ }
+
+ public void setActionType(DmaapAction actionType) {
+ this.actionType = actionType;
+ }
+
+ @Override
+ public String toString() {
+ return fullUri + " : " + label;
+ }
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceGetAllPayloadParserStrategy.java b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceGetAllPayloadParserStrategy.java
new file mode 100644
index 0000000..1c2f6cf
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceGetAllPayloadParserStrategy.java
@@ -0,0 +1,85 @@
+/**
+ * ============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.cacher.injestion.parser.strategy;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import org.onap.aai.cacher.injestion.parser.AAIResourcesUriTemplates;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.cacher.model.DBAction;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AAI resource get all parser strategy
+ */
+@Component(value = "aai-resource-get-all")
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class AAIResourceGetAllPayloadParserStrategy implements PayloadParserStrategy {
+
+ AAIResourcesUriTemplates aaiResourcesUriTemplates;
+
+ @Autowired
+ public AAIResourceGetAllPayloadParserStrategy(AAIResourcesUriTemplates aaiResourcesUriTemplates) {
+ this.aaiResourcesUriTemplates = aaiResourcesUriTemplates;
+ }
+
+ /**
+ * Parses aai resources specific payloads generating the details for .
+ *
+ * @param originalKey
+ * @param jsonObject
+ * @return
+ */
+ @Override
+ public List<CacheEntry> process(String originalKey, JsonObject jsonObject) {
+ final List<CacheEntry> cacheEntries = new ArrayList<>();
+
+ String type = jsonObject.entrySet().iterator().next().getKey();
+
+ JsonArray ja = jsonObject.getAsJsonArray(type);
+ CacheEntry cacheEntry;
+ String uri;
+ JsonObject jo;
+ for (JsonElement jsonElement : ja) {
+ jo = jsonElement.getAsJsonObject();
+ uri = aaiResourcesUriTemplates.getUri(type, jo);
+ jsonObject.addProperty("_id", uri);
+ cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry().withId(uri).inCollection(originalKey)
+ .withFindQuery(getFindQuery(uri)).withPayload(jo).withDbAction(DBAction.INSERT_REPLACE).build();
+ cacheEntries.add(cacheEntry);
+ }
+
+ return cacheEntries;
+ }
+
+ protected JsonObject getFindQuery(String uri) {
+ JsonObject jo = new JsonObject();
+ jo.addProperty("_id", uri);
+ return jo;
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/NonePayloadParserStrategy.java b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/NonePayloadParserStrategy.java
new file mode 100644
index 0000000..9d468b9
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/NonePayloadParserStrategy.java
@@ -0,0 +1,48 @@
+/**
+ * ============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.cacher.injestion.parser.strategy;
+
+import com.google.gson.JsonObject;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.cacher.model.DBAction;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Default parser strategy that dont not manipulate the payload.
+ */
+@Component(value = "none")
+@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
+public class NonePayloadParserStrategy implements PayloadParserStrategy {
+
+ @Override
+ public List<CacheEntry> process(String originalKey, JsonObject jsonObject) {
+ JsonObject find = new JsonObject();
+ jsonObject.addProperty("_id", originalKey);
+ return Collections.singletonList(
+ CacheEntry.CacheEntryBuilder.createCacheEntry().withId(originalKey).inCollection(originalKey)
+ .withFindQuery(find).withPayload(jsonObject).withDbAction(DBAction.INSERT_REPLACE).build());
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserStrategy.java b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserStrategy.java
new file mode 100644
index 0000000..a8f66b6
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserStrategy.java
@@ -0,0 +1,31 @@
+/**
+ * ============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.cacher.injestion.parser.strategy;
+
+import com.google.gson.JsonObject;
+import org.onap.aai.cacher.model.CacheEntry;
+
+import java.util.List;
+
+public interface PayloadParserStrategy {
+
+ List<CacheEntry> process(String originalKey, JsonObject jsonObject);
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserType.java b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserType.java
new file mode 100644
index 0000000..b497a8c
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/injestion/parser/strategy/PayloadParserType.java
@@ -0,0 +1,45 @@
+/**
+ * ============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.cacher.injestion.parser.strategy;
+
+import java.util.Arrays;
+
+public enum PayloadParserType {
+
+ NONE("none"), AAI_RESOURCE_GET_ALL("aai-resource-get-all"), AAI_RESOURCE_DMAAP("aai-resource-dmaap");
+ private final String value;
+
+ PayloadParserType(String input) {
+ this.value = input;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ return this.value;
+ }
+
+ public static PayloadParserType fromString(String text) {
+ return Arrays.stream(values()).filter(bl -> bl.getValue().equalsIgnoreCase(text)).findFirst().orElse(null);
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/model/CacheEntry.java b/src/main/java/org/onap/aai/cacher/model/CacheEntry.java
new file mode 100644
index 0000000..ed6715e
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/model/CacheEntry.java
@@ -0,0 +1,206 @@
+/**
+ * ============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.cacher.model;
+
+import com.google.gson.JsonObject;
+
+/**
+ * Captures the details of a cache entry to be inserted onto the database
+ */
+public class CacheEntry {
+
+ protected DBAction dbAction;
+
+ protected String id;
+ protected String collection;
+ protected JsonObject payload;
+ protected JsonObject findQuery;
+
+ protected boolean isNested = false;
+ protected String nestedField;
+ protected JsonObject nestedFind;
+ protected JsonObject nestedFieldIdentifierObj;
+
+ private CacheEntry() {
+ }
+
+ public DBAction getDbAction() {
+ return dbAction;
+ }
+
+ public void setDbAction(DBAction dbAction) {
+ this.dbAction = dbAction;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getCollection() {
+ return collection;
+ }
+
+ public void setCollection(String collection) {
+ this.collection = collection;
+ }
+
+ public JsonObject getPayload() {
+ return payload;
+ }
+
+ public void setPayload(JsonObject payload) {
+ this.payload = payload;
+ }
+
+ public JsonObject getFindQuery() {
+ return findQuery;
+ }
+
+ public void setFindQuery(JsonObject findQuery) {
+ this.findQuery = findQuery;
+ }
+
+ public boolean isNested() {
+ return isNested;
+ }
+
+ public void setNested(boolean nested) {
+ isNested = nested;
+ }
+
+ public String getNestedField() {
+ return nestedField;
+ }
+
+ public void setNestedField(String nestedField) {
+ this.nestedField = nestedField;
+ }
+
+ public JsonObject getNestedFind() {
+ return nestedFind;
+ }
+
+ public void setNestedFind(JsonObject nestedFind) {
+ this.nestedFind = nestedFind;
+ }
+
+ public JsonObject getNestedFieldIdentifierObj() {
+ return nestedFieldIdentifierObj;
+ }
+
+ public void setNestedFieldIdentifierObj(JsonObject nestedFieldIdentifierObj) {
+ this.nestedFieldIdentifierObj = nestedFieldIdentifierObj;
+ }
+
+ public static final class CacheEntryBuilder {
+ protected DBAction dbAction;
+ protected String id;
+ protected String collection;
+ protected JsonObject payload;
+ protected JsonObject findQuery;
+ protected boolean isNested;
+ protected String nestedField;
+ protected JsonObject nestedFind;
+ protected JsonObject nestedFieldIdentifierObj;
+
+ private CacheEntryBuilder() {
+ }
+
+ public static CacheEntryBuilder createCacheEntry() {
+ return new CacheEntryBuilder();
+ }
+
+ public CacheEntryBuilder deepCopy(CacheEntry cacheEntry) {
+ dbAction = cacheEntry.getDbAction();
+ id = cacheEntry.getId();
+ collection = cacheEntry.getCollection();
+ payload = cacheEntry.getPayload();
+ findQuery = cacheEntry.getFindQuery();
+ isNested = cacheEntry.isNested();
+ nestedField = cacheEntry.getNestedField();
+ nestedFind = cacheEntry.getNestedFind();
+ nestedFieldIdentifierObj = cacheEntry.getNestedFieldIdentifierObj();
+ return this;
+ }
+
+ public CacheEntryBuilder withDbAction(DBAction dbAction) {
+ this.dbAction = dbAction;
+ return this;
+ }
+
+ public CacheEntryBuilder withId(String id) {
+ this.id = id;
+ return this;
+ }
+
+ public CacheEntryBuilder inCollection(String collection) {
+ this.collection = collection;
+ return this;
+ }
+
+ public CacheEntryBuilder withPayload(JsonObject payload) {
+ this.payload = payload;
+ return this;
+ }
+
+ public CacheEntryBuilder withFindQuery(JsonObject findQuery) {
+ this.findQuery = findQuery;
+ return this;
+ }
+
+ public CacheEntryBuilder isNested(boolean isNested) {
+ this.isNested = isNested;
+ return this;
+ }
+
+ public CacheEntryBuilder withNestedField(String nestedField) {
+ this.nestedField = nestedField;
+ return this;
+ }
+
+ public CacheEntryBuilder withNestedFind(JsonObject nestedFind) {
+ this.nestedFind = nestedFind;
+ return this;
+ }
+
+ public CacheEntryBuilder withNestedFieldIdentifierObj(JsonObject nestedFieldIdentifierObj) {
+ this.nestedFieldIdentifierObj = nestedFieldIdentifierObj;
+ return this;
+ }
+
+ public CacheEntry build() {
+ CacheEntry cacheEntry = new CacheEntry();
+ cacheEntry.setDbAction(dbAction);
+ cacheEntry.setId(id);
+ cacheEntry.setCollection(collection);
+ cacheEntry.setPayload(payload);
+ cacheEntry.setFindQuery(findQuery);
+ cacheEntry.setNestedField(nestedField);
+ cacheEntry.setNestedFind(nestedFind);
+ cacheEntry.setNestedFieldIdentifierObj(nestedFieldIdentifierObj);
+ cacheEntry.isNested = this.isNested;
+ return cacheEntry;
+ }
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/model/CacheKey.java b/src/main/java/org/onap/aai/cacher/model/CacheKey.java
new file mode 100644
index 0000000..e87f34a
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/model/CacheKey.java
@@ -0,0 +1,220 @@
+/**
+ * ============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.cacher.model;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.mongodb.BasicDBObject;
+
+public class CacheKey {
+
+ public static final String DEFAULT_VALUE = "-1";
+
+ public String cacheKey = DEFAULT_VALUE;
+ public String baseUrl = DEFAULT_VALUE;
+ public String module = DEFAULT_VALUE;
+ public String URI = DEFAULT_VALUE;
+ public String timingIndicator = DEFAULT_VALUE;
+
+ public String syncInterval = DEFAULT_VALUE;
+ public String lastSyncStartTime = DEFAULT_VALUE;
+ public String lastSyncSuccessTime = DEFAULT_VALUE;
+ public String lastSyncEndTime = DEFAULT_VALUE;
+ public String httpBody = DEFAULT_VALUE;
+ public String httpMethod = DEFAULT_VALUE;
+
+ public String parserStrategy = "none";
+
+ public CacheKey(String cacheKey) {
+ this.cacheKey = cacheKey;
+ }
+
+ public static CacheKey createCacheKeyDefault(JsonObject payload) {
+ Gson gson = new Gson();
+ CacheKey cacheKey = gson.fromJson(payload.toString(), CacheKey.class);
+
+ if (cacheKey.cacheKey == null) {
+ cacheKey.cacheKey = DEFAULT_VALUE;
+ if (payload.has("_id")) {
+ cacheKey.cacheKey = payload.get("_id").getAsString();
+ }
+ }
+ if (cacheKey.baseUrl == null) {
+ cacheKey.baseUrl = DEFAULT_VALUE;
+ }
+ if (cacheKey.module == null) {
+ cacheKey.module = DEFAULT_VALUE;
+ }
+ if (cacheKey.URI == null) {
+ cacheKey.URI = DEFAULT_VALUE;
+ }
+ if (cacheKey.syncInterval == null) {
+ cacheKey.syncInterval = DEFAULT_VALUE;
+ }
+ if (cacheKey.lastSyncStartTime == null) {
+ cacheKey.lastSyncStartTime = DEFAULT_VALUE;
+ }
+ if (cacheKey.lastSyncSuccessTime == null) {
+ cacheKey.lastSyncSuccessTime = DEFAULT_VALUE;
+ }
+ if (cacheKey.lastSyncEndTime == null) {
+ cacheKey.lastSyncEndTime = DEFAULT_VALUE;
+ }
+ if (cacheKey.httpBody == null) {
+ cacheKey.httpBody = DEFAULT_VALUE;
+ }
+ if (cacheKey.parserStrategy == null) {
+ cacheKey.parserStrategy = DEFAULT_VALUE;
+ }
+ if (cacheKey.timingIndicator == null) {
+ cacheKey.timingIndicator = DEFAULT_VALUE;
+ }
+ if (cacheKey.httpMethod == null) {
+ cacheKey.httpMethod = DEFAULT_VALUE;
+ }
+ return cacheKey;
+ }
+
+ public static CacheKey fromJson(JsonObject payload) {
+ CacheKey cacheKey = createCacheKeyDefault(payload);
+ if (DEFAULT_VALUE.equals(cacheKey.parserStrategy)) {
+ cacheKey.parserStrategy = "none";
+ }
+ if (DEFAULT_VALUE.equals(cacheKey.timingIndicator)) {
+ cacheKey.timingIndicator = "firstHit";
+ } else if (cacheKey.getTimingIndicator().equals("scheduled") && DEFAULT_VALUE.equals(cacheKey.syncInterval)) {
+ cacheKey.syncInterval = "1440";
+ }
+ if (DEFAULT_VALUE.equals(cacheKey.httpMethod)) {
+ cacheKey.httpMethod = "GET";
+ }
+ return cacheKey;
+ }
+
+ public BasicDBObject toDBObject() {
+ BasicDBObject document = new BasicDBObject();
+ document.put("_id", this.cacheKey);
+ document.put("baseUrl", this.baseUrl);
+ document.put("module", this.module);
+ document.put("URI", this.URI);
+ document.put("timingIndicator", this.timingIndicator);
+ document.put("syncInterval", this.syncInterval);
+ document.put("lastSyncStartTime", this.lastSyncStartTime);
+ document.put("lastSyncSuccessTime", this.lastSyncSuccessTime);
+ document.put("lastSyncEndTime", this.lastSyncEndTime);
+ document.put("httpBody", this.httpBody);
+ document.put("httpMethod", this.httpMethod);
+ document.put("parserStrategy", parserStrategy);
+ return document;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("cacheKey: " + cacheKey + "\n");
+ sb.append("Base URL: " + baseUrl + "\n");
+ sb.append("Module: " + module + "\n");
+ sb.append("URI: " + URI + "\n");
+ sb.append("timingIndicator: " + timingIndicator + "\n");
+ sb.append("syncInterval: " + syncInterval + "\n");
+ sb.append("lastSyncStartTime: " + lastSyncStartTime + "\n");
+ sb.append("lastSyncSuccessTime: " + lastSyncSuccessTime + "\n");
+ sb.append("lastSyncEndTime: " + lastSyncEndTime + "\n");
+ sb.append("httpMethod: " + httpMethod + "\n");
+ sb.append("httpBody: " + httpBody + "\n");
+ sb.append("parserStrategy: " + parserStrategy + "\n");
+
+ return sb.toString();
+ }
+
+ public String getCacheKey() {
+ return cacheKey;
+ }
+
+ public void setCacheKey(String cacheKey) {
+ this.cacheKey = cacheKey;
+ }
+
+ public String getBaseUrl() {
+ return baseUrl;
+ }
+
+ public String getModule() {
+ return module;
+ }
+
+ public String getURI() {
+ return URI;
+ }
+
+ public String getTimingIndicator() {
+ return timingIndicator;
+ }
+
+ public String getSyncInterval() {
+ return syncInterval;
+ }
+
+ public void setSyncInterval(String syncInterval) {
+ this.syncInterval = syncInterval;
+ }
+
+ public String getLastSyncStartTime() {
+ return lastSyncStartTime;
+ }
+
+ public void setLastSyncStartTime(String ls) {
+ this.lastSyncStartTime = ls;
+ }
+
+ public String getLastSyncSuccessTime() {
+ return lastSyncSuccessTime;
+ }
+
+ public void setLastSyncSuccessTime(String ls) {
+ this.lastSyncSuccessTime = ls;
+ }
+
+ public String getLastSyncEndTime() {
+ return lastSyncEndTime;
+ }
+
+ public void setLastSyncEndTime(String le) {
+ this.lastSyncEndTime = le;
+ }
+
+ public String getHttpBody() {
+ return httpBody;
+ }
+
+ public String getHttpMethod() {
+ return httpMethod;
+ }
+
+ public String getParserStrategy() {
+ return parserStrategy;
+ }
+
+ public void setParserStrategy(String parserStrategy) {
+ this.parserStrategy = parserStrategy;
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/model/DBAction.java b/src/main/java/org/onap/aai/cacher/model/DBAction.java
new file mode 100644
index 0000000..0d7fbd5
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/model/DBAction.java
@@ -0,0 +1,24 @@
+/**
+ * ============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.cacher.model;
+
+public enum DBAction {
+ DELETE, INSERT_REPLACE, UPDATE
+}
diff --git a/src/main/java/org/onap/aai/cacher/service/AuthorizationService.java b/src/main/java/org/onap/aai/cacher/service/AuthorizationService.java
new file mode 100644
index 0000000..369503a
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/AuthorizationService.java
@@ -0,0 +1,109 @@
+/**
+ * ============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.cacher.service;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.eclipse.jetty.util.security.Password;
+import org.onap.aai.cacher.Profiles;
+import org.onap.aai.util.AAIConstants;
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+@Profile(Profiles.ONE_WAY_SSL)
+@Service
+public class AuthorizationService {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(AuthorizationService.class);
+
+ private final Map<String, String> authorizedUsers = new HashMap<>();
+
+ private static final Base64.Encoder ENCODER = Base64.getEncoder();
+
+ @PostConstruct
+ public void init(){
+
+ String basicAuthFile = getBasicAuthFilePath();
+
+ try(Stream<String> stream = Files.lines(Paths.get(basicAuthFile))){
+ stream.filter(line -> !line.startsWith("#")).forEach(str -> {
+ byte [] bytes = null;
+
+ String usernamePassword = null;
+ String accessType = null;
+
+ try {
+ String [] userAccessType = str.split(",");
+
+ if(userAccessType == null || userAccessType.length != 2){
+ throw new RuntimeException("Please check the realm.properties file as it is not conforming to the basic auth");
+ }
+
+ usernamePassword = userAccessType[0];
+ accessType = userAccessType[1];
+
+ String[] usernamePasswordArray = usernamePassword.split(":");
+
+ if(usernamePasswordArray == null || usernamePasswordArray.length != 3){
+ throw new RuntimeException("Not a valid entry for the realm.properties entry: " + usernamePassword);
+ }
+
+ String username = usernamePasswordArray[0];
+ String password = null;
+
+ if(str.contains("OBF:")){
+ password = usernamePasswordArray[1] + ":" + usernamePasswordArray[2];
+ password = Password.deobfuscate(password);
+ }
+
+ bytes = ENCODER.encode((username + ":" + password).getBytes("UTF-8"));
+
+ authorizedUsers.put(new String(bytes), accessType);
+
+ } catch (UnsupportedEncodingException e)
+ {
+ logger.error("Unable to support the encoding of the file" + basicAuthFile);
+ }
+
+ authorizedUsers.put(new String(ENCODER.encode(bytes)), accessType);
+ });
+ } catch (IOException e) {
+ logger.error("IO Exception occurred during the reading of realm.properties", e);
+ }
+ }
+
+ public boolean checkIfUserAuthorized(String authorization){
+ return authorizedUsers.containsKey(authorization) && "admin".equals(authorizedUsers.get(authorization));
+ }
+
+ public String getBasicAuthFilePath(){
+ return AAIConstants.AAI_HOME_ETC_AUTH + AAIConstants.AAI_FILESEP + "realm.properties";
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/service/helper/CacheHelperService.java b/src/main/java/org/onap/aai/cacher/service/helper/CacheHelperService.java
new file mode 100644
index 0000000..8b85174
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/helper/CacheHelperService.java
@@ -0,0 +1,545 @@
+/**
+ * ============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.cacher.service.helper;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.common.collect.Lists;
+import com.google.gson.*;
+import com.mongodb.*;
+import org.onap.aai.cacher.common.MongoHelperSingleton;
+import org.onap.aai.cacher.egestion.printer.PayloadPrinterService;
+import org.onap.aai.cacher.injestion.parser.PayloadParserService;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.util.AAIConstants;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import java.lang.reflect.Field;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@Service
+public class CacheHelperService {
+
+ private final static EELFLogger EELF_LOGGER = EELFManager.getInstance().getLogger(CacheHelperService.class);
+ private Gson gson = new GsonBuilder().create();
+
+ @Autowired
+ private MongoHelperSingleton mongoHelper;
+
+ @Autowired
+ private RestClientHelperService rchs;
+
+ @Autowired
+ private PayloadParserService payloadParserService;
+
+ @Autowired
+ private PayloadPrinterService payloadPrinterService;
+
+ public void setMongoHelper(MongoHelperSingleton mongoHelper) {
+ this.mongoHelper = mongoHelper;
+ }
+
+ public void setRchs(RestClientHelperService rchs) {
+ this.rchs = rchs;
+ }
+
+ public void setPayloadParserService(PayloadParserService payloadParserService) {
+ this.payloadParserService = payloadParserService;
+ }
+
+ public void setPayloadPrinterService(PayloadPrinterService payloadPrinterService) {
+ this.payloadPrinterService = payloadPrinterService;
+ }
+
+ public CacheKey retrieveCacheKeyObject(CacheKey ck) {
+ String ckString = retrieveCollectionString(ck, AAIConstants.COLLECTION_CACHEKEY);
+ if (ckString.equals("")) {
+ EELF_LOGGER.error("Could not retrieve cache key");
+ return null;
+ }
+ JsonParser parser = new JsonParser();
+ JsonObject ckJson = (JsonObject) parser.parse(ckString);
+ return CacheKey.fromJson(ckJson);
+ }
+
+ public String retrieveCollectionString(CacheKey ck, String collectionName) {
+ StringBuilder result = new StringBuilder("");
+ try {
+ DBCollection collection = mongoHelper.getDb().getCollection(collectionName);
+ BasicDBObject whereQuery = new BasicDBObject();
+ whereQuery.put("_id", ck.getCacheKey());
+ DBCursor cursor = collection.find(whereQuery);
+ while (cursor.hasNext()) {
+ result.append(cursor.next());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ }
+ return result.toString();
+ }
+
+ public boolean isCollectionPresent(String collectionName) {
+ if (collectionName != null && !collectionName.isEmpty()) {
+ try {
+ DBCollection collection = mongoHelper.getDb().getCollection(collectionName);
+ DBCursor cursor = collection.find();
+ if (cursor.count() > 0) {
+ return true;
+ }
+ } catch (Exception e) {
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ }
+ }
+ return false;
+ }
+
+ public String retrieveCollectionString(CacheKey ck) {
+ JsonArray jsonArray = new JsonArray();
+ try {
+ DBCollection collection = mongoHelper.getDb().getCollection(ck.getCacheKey());
+ DBCursor cursor = collection.find();
+ if (cursor.count() > 0) {
+ while (cursor.hasNext()) {
+ // remove "_id" property from cache response
+ JsonParser parser = new JsonParser();
+ JsonObject jsonObj = (JsonObject) parser.parse(cursor.next().toString());
+ jsonObj.remove("_id");
+ jsonArray.add(jsonObj);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ }
+ JsonObject jsonObject = payloadPrinterService.createJson(ck.getCacheKey(), jsonArray, ck.getParserStrategy());
+ if (jsonObject != null) {
+ return jsonObject.toString();
+ }
+ return "";
+ }
+
+ public boolean isKeyPresent(CacheKey ck, String collectionName) {
+ return !retrieveCollectionString(ck, collectionName).equals("");
+ }
+
+ public boolean isCurrentlyRunning(CacheKey ck) {
+ CacheKey ckPopulated = retrieveCacheKeyObject(ck);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.SSSZ");
+ Long syncStartTimeInMillis = -1L;
+ Long syncLastEndInMillis = -1L;
+ if (ckPopulated != null && !ckPopulated.getLastSyncStartTime().equals("-1")) {
+ try {
+ syncStartTimeInMillis = sdf.parse(ckPopulated.getLastSyncStartTime()).getTime();
+ } catch (Exception e) {
+ // TODO handle exceptions
+ }
+ }
+ if (ckPopulated != null && !ckPopulated.getLastSyncEndTime().equals("-1")) {
+ try {
+ syncLastEndInMillis = sdf.parse(ckPopulated.getLastSyncEndTime()).getTime();
+ } catch (Exception e) {
+ // TODO handle exceptions
+ }
+ }
+ return ckPopulated != null && syncLastEndInMillis < syncStartTimeInMillis;
+ }
+
+ public Response getData(CacheKey ck) {
+ if (ck == null) {
+ AAIException aaiException = new AAIException("AAI_3014", "Cache key provided does not exist");
+ return buildExceptionResponse(aaiException);
+ } else if (isCurrentlyRunning(ck)) {
+ AAIException aaiException = new AAIException("AAI_4000", "Sync is currently running from another process.");
+ return buildExceptionResponse(aaiException);
+ } else if (isKeyPresent(ck, AAIConstants.COLLECTION_CACHEKEY)) {
+ if (isCollectionPresent(ck.getCacheKey())) {
+ return retrieveCollectionByKey(ck);
+ } else {
+ ResponseEntity resp = rchs.triggerRestCall(ck);
+ if (!resp.getStatusCode().is2xxSuccessful()) {
+ // TODO log/return accordingly
+ }
+ Response response = populateCache(ck, (String) resp.getBody());
+ if (response.getStatus() == 201) {
+ return retrieveCollectionByKey(ck);
+ } else {
+ AAIException aaiException = new AAIException("AAI_5105");
+ return buildExceptionResponse(aaiException);
+ }
+ }
+ } else {
+ AAIException aaiException = new AAIException("AAI_3014", "Cache key provided does not exist");
+ return buildExceptionResponse(aaiException);
+ }
+ }
+
+ public Response forceSync(CacheKey ck) {
+ if (isCurrentlyRunning(ck)) {
+ AAIException aaiException = new AAIException("AAI_4000", "Sync is currently running from another process.");
+ return buildExceptionResponse(aaiException);
+ } else if (isKeyPresent(ck, AAIConstants.COLLECTION_CACHEKEY)) {
+ // populate cache and return status on sync
+ ResponseEntity resp = rchs.triggerRestCall(ck);
+ if (!resp.getStatusCode().is2xxSuccessful()) {
+ // TODO unsure if this is correct behavior
+ return Response.noContent().build();
+ }
+ return populateCache(ck, (String) resp.getBody());
+ } else {
+ AAIException aaiException = new AAIException("AAI_3014", "Cache key provided does not exist");
+ return buildExceptionResponse(aaiException);
+ }
+ }
+
+ public Response retrieveCollectionByKey(CacheKey ck, String collection) {
+ Status status = Status.OK;
+ String result = "";
+ try {
+ result = this.retrieveCollectionString(ck, collection);
+
+ if (result.equals("")) {
+ status = Status.NOT_FOUND;
+ EELF_LOGGER.error("Cannot not found the cache key from mongodb");
+ }
+ return this.buildResponse(status, result);
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000", e);
+ return buildExceptionResponse(aaiException);
+
+ }
+ }
+
+ public Response retrieveCollectionByKey(CacheKey ck) {
+ Status status = Status.OK;
+ String result = "";
+ try {
+ result = this.retrieveCollectionString(ck);
+ if (result.equals("")) {
+ status = Status.NOT_FOUND;
+ EELF_LOGGER.error("Cannot not found the cache key from mongodb");
+ }
+ return this.buildResponse(status, result);
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000", e);
+ return buildExceptionResponse(aaiException);
+
+ }
+ }
+
+ public boolean addCacheKey(CacheKey ck) {
+ return mongoHelper.addToMongo(AAIConstants.COLLECTION_CACHEKEY, ck.toDBObject());
+ }
+
+ public Response getAllKeys() {
+ Status status = Status.OK;
+ StringBuilder result = new StringBuilder();
+ try {
+ DBCollection collection = mongoHelper.getDb().getCollection(AAIConstants.COLLECTION_CACHEKEY);
+ DBCursor cursor = collection.find();
+ if (cursor.count() > 1) {
+ result.append("[");
+ while (cursor.hasNext()) {
+ result.append(cursor.next());
+ if (cursor.numSeen() != cursor.count()) {
+ result.append(",");
+ }
+ }
+ result.append("]");
+
+ } else if (cursor.count() == 1) {
+ while (cursor.hasNext()) {
+ result.append(cursor.next());
+ }
+ } else {
+ status = Status.NOT_FOUND;
+ }
+ return buildResponse(status, result.toString());
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000", e);
+ return buildExceptionResponse(aaiException);
+ }
+ }
+
+ public Response updateCacheKey(CacheKey ck) {
+ DBCollection collection = mongoHelper.getDb().getCollection(AAIConstants.COLLECTION_CACHEKEY);
+ Status status;
+
+ BasicDBObject updateFields = new BasicDBObject();
+
+ for (Field field : ck.getClass().getDeclaredFields()) {
+ try {
+ String name = field.getName();
+ Object value = field.get(ck);
+ if (!name.equals(AAIConstants.COLLECTION_CACHEKEY) && !value.equals("-1")) {
+ updateFields.append(name, value);
+ }
+ } catch (Exception e) {
+ EELF_LOGGER.warn("Could not retrieve updatable field from the class", e);
+ }
+ }
+
+ BasicDBObject setQuery = new BasicDBObject();
+ setQuery.append("$set", updateFields);
+
+ BasicDBObject searchQuery = new BasicDBObject("_id", ck.getCacheKey());
+ try {
+ WriteResult result = collection.update(searchQuery, setQuery);
+ if (result.getN() > 0) {
+ status = Status.OK;
+ } else {
+ // TODO set proper status for no results updated meaning it didn't find the key
+ status = Status.NOT_FOUND;
+ }
+ return buildResponse(status, "{}");
+ } catch (MongoException ex) {
+ AAIException aaiException = new AAIException("AAI_5105", ex);
+ return buildExceptionResponse(aaiException);
+ }
+ }
+
+ public boolean bulkAddCacheKeys(List<CacheKey> ckList) {
+ try {
+ List<BasicDBObject> documents = new ArrayList<BasicDBObject>();
+ for (CacheKey ck : ckList) {
+ documents.add(ck.toDBObject());
+ }
+ return mongoHelper.addToMongo(AAIConstants.COLLECTION_CACHEKEY, documents);
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000", e);
+ ErrorLogHelper.logException(aaiException);
+ return false;
+ }
+ }
+
+ public Response deleteCacheKeyAndAssociatedCache(String id) {
+ String cacheDelete = deleteFromCollection(null, id);
+ dropCollection(id);
+ String cacheKeyDelete = deleteFromCollection(id, AAIConstants.COLLECTION_CACHEKEY);
+ Status status;
+ if (cacheKeyDelete.equals("DELETED") && (cacheDelete.equals("DELETED") || cacheDelete.equals("NOT_FOUND"))) {
+ status = Status.NO_CONTENT;
+ return buildResponse(status, "{}");
+ } else if (cacheKeyDelete.equals("NOT_FOUND")) {
+ status = Status.NOT_FOUND;
+ return buildResponse(status, "{}");
+ } else {
+ AAIException aaiException = new AAIException("AAI_5105");
+ return buildExceptionResponse(aaiException);
+ }
+ }
+
+ public Response deleteCache(String id, String collection) {
+ String cacheDelete = deleteFromCollection(id, collection);
+ Status status;
+ if (cacheDelete.equals("DELETED")) {
+ status = Status.NO_CONTENT;
+ return buildResponse(status, "{}");
+ } else if (cacheDelete.equals("NOT_FOUND")) {
+ status = Status.NOT_FOUND;
+ return buildResponse(status, "{}");
+ } else {
+ AAIException aaiException = new AAIException("AAI_5105");
+ return buildExceptionResponse(aaiException);
+ }
+ }
+
+ public String deleteFromCollection(String id, String collection) {
+ Map<String, String> whereClause = new HashMap<>();
+ if (id != null) {
+ whereClause.put("_id", id);
+ }
+ return mongoHelper.deleteFromMongo(collection, whereClause);
+ }
+
+ public void dropCollection(String collection) {
+ mongoHelper.dropCollection(collection);
+ }
+
+ public Response populateCache(CacheKey ck, String responseBody) {
+ // Check to see if the cache key object is fully populated or an empty
+ // identifier object
+ // if it's an empty identifier object pull the entire object
+ if (ck.getBaseUrl().equals("-1")) {
+ ck = retrieveCacheKeyObject(ck);
+ }
+ DateFormat formatter = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.SSSZ");
+
+ List<CacheEntry> cacheEntries = payloadParserService.doParse(ck.getCacheKey(), responseBody,
+ ck.getParserStrategy());
+ for (CacheEntry cacheEntry : cacheEntries) {
+ boolean success = false;
+
+ switch (cacheEntry.getDbAction()) {
+ case DELETE:
+ success = mongoHelper.delete(cacheEntry);
+ break;
+ case UPDATE:
+ success = mongoHelper.insertReplace(cacheEntry);
+ break;
+ case INSERT_REPLACE:
+ success = mongoHelper.insertReplace(cacheEntry);
+ break;
+ }
+
+ if (!success) {
+ ck.setLastSyncEndTime(formatter.format(System.currentTimeMillis()));
+ updateCacheKey(ck);
+ AAIException aaiException = new AAIException("AAI_4000", "Unable to populate the cache");
+ return buildExceptionResponse(aaiException);
+ }
+ }
+ ck.setLastSyncSuccessTime(formatter.format(System.currentTimeMillis()));
+ ck.setLastSyncEndTime(formatter.format(System.currentTimeMillis()));
+ updateCacheKey(ck);
+ return buildResponse(Status.CREATED, "{}");
+ }
+
+ public Response buildResponse(Status status, String result) {
+ return Response.status(status).type(MediaType.APPLICATION_JSON).entity(result).build();
+ }
+
+ public Response buildValidationResponse(List<String> issues) {
+ AAIException aaiException = new AAIException("AAI_3014");
+ ArrayList<String> templateVars = new ArrayList<>();
+
+ if (templateVars.isEmpty()) {
+ templateVars.add(issues.toString());
+ }
+ ErrorLogHelper.logException(aaiException);
+ return Response.status(aaiException.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(
+ Lists.newArrayList(MediaType.APPLICATION_JSON_TYPE), aaiException, templateVars))
+ .build();
+ }
+
+ public Response buildExceptionResponse(AAIException aaiException) {
+ ErrorLogHelper.logException(aaiException);
+ return Response.status(aaiException.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(
+ Lists.newArrayList(MediaType.APPLICATION_JSON_TYPE), aaiException, new ArrayList<>()))
+ .build();
+ }
+
+ public List<CacheKey> getScheduledCaches() {
+ List<CacheKey> cks = new ArrayList<>();
+ EELF_LOGGER.info("Retrieving scheduled cache keys");
+ DBCollection collection = mongoHelper.getDb().getCollection(AAIConstants.COLLECTION_CACHEKEY);
+ BasicDBObject whereQuery = new BasicDBObject();
+ whereQuery.put("timingIndicator", "scheduled");
+ DBCursor cursor = collection.find(whereQuery);
+ while (cursor.hasNext()) {
+ JsonObject ckJson = (JsonObject) new JsonParser().parse((cursor.next().toString()));
+ CacheKey ck = CacheKey.fromJson(ckJson);
+ cks.add(ck);
+ }
+ return cks;
+ }
+
+ public void checkAndInitTasks() {
+ List<CacheKey> ckList = this.getScheduledCaches();
+ int numOfThread = 10;
+ ExecutorService taskExecutor = Executors.newFixedThreadPool(numOfThread);
+ try {
+ List<Callable<Void>> tasks = new ArrayList<>();
+ for (CacheKey ck : ckList) {
+
+ boolean shouldTrigger = isShouldTrigger(ck);
+
+ if (shouldTrigger) {
+ Callable<Void> task = new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ long startTimeV = System.currentTimeMillis();
+ ResponseEntity respEntity = rchs.triggerRestCall(ck);
+ if (respEntity.getStatusCode().is2xxSuccessful()) {
+ populateCache(ck, (String) respEntity.getBody());
+ long endTimeV = System.currentTimeMillis();
+ EELF_LOGGER.info("Elapsed time in seconds: " + (endTimeV - startTimeV) / 1000);
+ } else {
+ // TODO: cache update failed
+ }
+ return null;
+ }
+ };
+ if (task != null) {
+ tasks.add(task);
+ }
+ }
+ }
+ if (!tasks.isEmpty()) {
+ taskExecutor.invokeAll(tasks);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ // TODO throw exception
+ } finally {
+ taskExecutor.shutdown();
+ }
+ }
+
+ protected boolean isShouldTrigger(CacheKey ck) {
+
+ // convert minutes to milliseconds for the interval
+ int interval = Integer.parseInt(ck.getSyncInterval()) * 60000;
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.SSSZ");
+ long syncStartTimeInMillis = Integer.MAX_VALUE;
+ long syncLastEndInMillis = Integer.MIN_VALUE;
+
+ if ("-1".equals(ck.getLastSyncStartTime())) {
+ return true;
+ } else {
+ try {
+ syncStartTimeInMillis = sdf.parse(ck.getLastSyncStartTime()).getTime();
+ } catch (Exception e) {
+ e.printStackTrace();
+ // TODO handle exceptions
+ }
+ }
+
+ if (!"-1".equals(ck.getLastSyncEndTime())) {
+ try {
+ syncLastEndInMillis = sdf.parse(ck.getLastSyncEndTime()).getTime();
+ } catch (Exception e) {
+ e.printStackTrace();
+ // TODO handle exceptions
+ }
+ }
+
+ return ((System.currentTimeMillis() - syncStartTimeInMillis) > interval)
+ && (syncStartTimeInMillis < syncLastEndInMillis);
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/service/helper/RestClientHelperService.java b/src/main/java/org/onap/aai/cacher/service/helper/RestClientHelperService.java
new file mode 100644
index 0000000..b72101f
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/helper/RestClientHelperService.java
@@ -0,0 +1,76 @@
+/**
+ * ============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.cacher.service.helper;
+
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.util.RestClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+@Component
+public class RestClientHelperService {
+
+ @Autowired
+ CacheHelperService chs;
+
+ private RestClient restClient = getRestClient();
+
+ public RestClient getRestClient() {
+ try {
+ return new RestClient();
+ } catch (Exception e) {
+ // TODO handle exceptions
+ return null;
+ }
+ }
+
+ /**
+ * Given a cacheKey trigger its corresponding rest call
+ *
+ * @param ck
+ * @return ResponseEntity to process
+ */
+ public ResponseEntity triggerRestCall(CacheKey ck) {
+ // populated cacheKey with mongo variables
+ CacheKey ckPopulated = chs.retrieveCacheKeyObject(ck);
+ ResponseEntity resp = null;
+ // Check to see if the cache key object is fully populated or an empty
+ // identifier object
+ // if it's an empty identifier object pull the entire object
+ if ("-1".equals(ck.getBaseUrl())) {
+ ck = chs.retrieveCacheKeyObject(ck);
+ }
+ DateFormat formatter = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.SSSZ");
+ String dateFormatted = formatter.format(System.currentTimeMillis());
+ ck.setLastSyncStartTime(dateFormatted);
+ chs.updateCacheKey(ck);
+ try {
+ resp = this.restClient.get(ckPopulated.getBaseUrl(), ckPopulated.getModule(), ckPopulated.getURI(),
+ "AAI-CACHER");
+ } catch (Exception e) {
+ // TODO log an exception
+ }
+ return resp;
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/service/rest/CacheInteractionService.java b/src/main/java/org/onap/aai/cacher/service/rest/CacheInteractionService.java
new file mode 100644
index 0000000..57bebdd
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/rest/CacheInteractionService.java
@@ -0,0 +1,88 @@
+/**
+ * ============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.cacher.service.rest;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonParser;
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.service.helper.CacheHelperService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Path("/cache/v1")
+@Produces({ MediaType.APPLICATION_JSON })
+public class CacheInteractionService {
+
+ private final static EELFLogger EELF_LOGGER = EELFManager.getInstance().getLogger(CacheKeyService.class);
+
+ @Autowired
+ protected CacheHelperService chs;
+
+ /**
+ * Delete the associated cache and handle responses
+ *
+ * @param payload, requires the cache key to delete the cache
+ */
+ @DELETE
+ @Path("/delete")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeDelete(String payload) {
+ CacheKey ck = CacheKey.fromJson(new JsonParser().parse(payload).getAsJsonObject());
+ Response resp = chs.deleteCache(null, ck.getCacheKey());
+ chs.dropCollection(ck.getCacheKey());
+ return resp;
+ }
+
+ /**
+ * Sync the cache from the provided cache key and handle responses
+ *
+ * @param payload, needs the cache key in the request payload to force sync the
+ * cache
+ */
+ @PUT
+ @Path("/sync")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeSync(String payload) {
+ CacheKey ck = CacheKey.fromJson(new JsonParser().parse(payload).getAsJsonObject());
+ return chs.forceSync(ck);
+ }
+
+ /**
+ * Execute to build and return the payload for the provided cache key
+ *
+ * @param cacheKey, needs the cacheKey to know which response payload to build
+ * and return
+ */
+ @GET
+ @Path("/get")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeGetSingle(@DefaultValue("-1") @QueryParam("cacheKey") String cacheKey) {
+ CacheKey ck = new CacheKey(cacheKey);
+ ck = chs.retrieveCacheKeyObject(ck);
+ return chs.getData(ck);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/service/rest/CacheKeyService.java b/src/main/java/org/onap/aai/cacher/service/rest/CacheKeyService.java
new file mode 100644
index 0000000..962be77
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/rest/CacheKeyService.java
@@ -0,0 +1,200 @@
+/**
+ * ============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.cacher.service.rest;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.service.helper.CacheHelperService;
+import org.onap.aai.cacher.service.rest.util.CacheKeyRequestValidation;
+import org.onap.aai.cacher.service.rest.util.CacheKeyRequestValidationType;
+import org.onap.aai.cacher.util.AAIConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import java.util.List;
+
+@Path("/cacheKey/v1")
+@Produces({ MediaType.APPLICATION_JSON })
+public class CacheKeyService {
+ private final static EELFLogger EELF_LOGGER = EELFManager.getInstance().getLogger(CacheKeyService.class);
+
+ @Autowired
+ protected CacheHelperService chs;
+
+ /**
+ * Store the cache key to Mongodb
+ *
+ * @param payload, the json payload needed to populate the cacheKey object and
+ * add to the database
+ */
+ @PUT
+ @Path("/add")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeAdd(String payload) {
+ EELF_LOGGER.info("Got the request to add cache key to mongodb");
+ CacheKeyRequestValidation ckrv = new CacheKeyRequestValidation(CacheKeyRequestValidationType.ADD);
+ JsonObject input = convertStringToJSON(payload);
+ List<String> issues = ckrv.validateCacheKeyRequest(input, chs);
+ Response response;
+ if (!issues.isEmpty()) {
+ response = chs.buildValidationResponse(issues);
+ } else {
+ CacheKey ck = CacheKey.fromJson(convertStringToJSON(payload));
+ boolean addSuccessful = chs.addCacheKey(ck);
+ // Since we are adding an onInit, we need to populate its cache
+ if (ck.getTimingIndicator().equals("onInit")) {
+ chs.forceSync(ck);
+ }
+ Status status;
+ if (addSuccessful) {
+ status = Status.CREATED;
+ } else {
+ EELF_LOGGER.error("Adding of cache key was not successfull");
+ status = Status.INTERNAL_SERVER_ERROR;
+ }
+ response = Response.status(status).type(MediaType.APPLICATION_JSON).build();
+ }
+ return response;
+ }
+
+ /**
+ * Update the stored cache key and handle responses
+ *
+ * @param payload, the json payload needed to populate the cacheKey object and
+ * update the entry in the database
+ */
+ @PUT
+ @Path("/update")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeUpdate(String payload) {
+ EELF_LOGGER.info("Got the request to update cache key in mongodb");
+ CacheKeyRequestValidation ckrv = new CacheKeyRequestValidation(CacheKeyRequestValidationType.UPDATE);
+ JsonObject input = convertStringToJSON(payload);
+ List<String> issues = ckrv.validateCacheKeyRequest(input, chs);
+ Response response;
+ if (!issues.isEmpty()) {
+ response = chs.buildValidationResponse(issues);
+ } else {
+ CacheKey ck = CacheKey.createCacheKeyDefault(input);
+ response = chs.updateCacheKey(ck);
+ }
+ return response;
+ }
+
+ /**
+ * Delete the cache key and associated cache and handle responses
+ *
+ * @param payload, the json payload needed to delete the cacheKey entry in the
+ * database
+ */
+ @DELETE
+ @Path("/delete")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeDelete(String payload) {
+ EELF_LOGGER.info("Got the request to delete cache key from mongodb");
+ CacheKeyRequestValidation ckrv = new CacheKeyRequestValidation(CacheKeyRequestValidationType.DELETE);
+ JsonObject input = convertStringToJSON(payload);
+ List<String> issues = ckrv.validateCacheKeyRequest(input, chs);
+ Response response;
+ if (!issues.isEmpty()) {
+ response = chs.buildValidationResponse(issues);
+ } else {
+ CacheKey ck = new CacheKey(getValueFromPayload(input, "cacheKey"));
+ response = chs.deleteCacheKeyAndAssociatedCache(ck.getCacheKey());
+ }
+ return response;
+ }
+
+ /**
+ * Get the cache key information given a provided cache key, or if no key is
+ * provided return all keys
+ *
+ * @param cacheKey, the string id to match against _id in mongodb as the unique
+ * cache key
+ */
+ @GET
+ @Path("/get")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response executeGet(@DefaultValue("-1") @QueryParam("cacheKey") String cacheKey) {
+ /*
+ * Method to get a single cache key entry
+ */
+ EELF_LOGGER.info("Got the request to get cache key from mongodb");
+ CacheKey ck;
+ Response response;
+ if (cacheKey.equals("-1")) {
+ response = chs.getAllKeys();
+ } else {
+ ck = new CacheKey(cacheKey);
+ response = chs.retrieveCollectionByKey(ck, AAIConstants.COLLECTION_CACHEKEY);
+ }
+ return response;
+ }
+
+ /**
+ * This method accepts a string converts it into a JsonObject
+ *
+ * @param payload, the string payload to convert to a JsonObject
+ */
+ public JsonObject convertStringToJSON(String payload) {
+ JsonParser parser = new JsonParser();
+ return (JsonObject) parser.parse(payload);
+ }
+
+ /**
+ * This method accepts a string payload and extracts the cacheKey
+ *
+ * @param payload, the string payload to convert to a JsonObject
+ */
+ public String getValueFromPayload(String payload, String key) {
+ JsonObject payloadJSON = convertStringToJSON(payload);
+ if (payloadJSON.has(key)) {
+ return ((payloadJSON.get(key)).toString()).replaceAll("\"", "");
+ } else {
+ EELF_LOGGER.error("Could not extract cachekey from the payload");
+ return null;
+ }
+ }
+
+ /**
+ * This method accepts a JsonObject input and extracts the cacheKey
+ *
+ * @param input, the string payload to convert to a JsonObject
+ */
+ public String getValueFromPayload(JsonObject input, String key) {
+ if (input.has(key)) {
+ return ((input.get(key)).toString()).replaceAll("\"", "");
+ } else {
+ EELF_LOGGER.error("Could not extract cachekey from the payload");
+ return null;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidation.java b/src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidation.java
new file mode 100644
index 0000000..4df1921
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidation.java
@@ -0,0 +1,66 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.service.rest.util;
+
+import com.google.gson.JsonObject;
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.service.helper.CacheHelperService;
+import org.onap.aai.cacher.util.AAIConstants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CacheKeyRequestValidation {
+ private CacheKeyRequestValidationType type;
+
+ public CacheKeyRequestValidation(CacheKeyRequestValidationType type) {
+ this.type = type;
+ }
+
+ public List<String> validateCacheKeyRequest(JsonObject input, CacheHelperService chs) {
+ ArrayList<String> results = new ArrayList<>();
+ if (input == null) {
+ results.add("Unsupported CacheKey request format, empty payload.");
+ return results;
+ }
+ CacheKey cacheKey = CacheKey.fromJson(input);
+ if ("-1".equals(cacheKey.getCacheKey())) {
+ results.add("Unsupported CacheKey request format, unspecified cacheKey.");
+ return results;
+ }
+ if (type.equals(CacheKeyRequestValidationType.DELETE)) {
+ return results;
+ }
+
+ Boolean keyExists = chs.isKeyPresent(cacheKey, AAIConstants.COLLECTION_CACHEKEY);
+ if (type.equals(CacheKeyRequestValidationType.ADD)) {
+ if (keyExists) {
+ results.add("Invalid request to add cacheKey " + cacheKey.getCacheKey() + ", cacheKey exists.");
+ }
+ } else if (type.equals(CacheKeyRequestValidationType.UPDATE)) {
+ if (!keyExists) {
+ results.add(
+ "Invalid request to update cacheKey " + cacheKey.getCacheKey() + ", cacheKey does not exist.");
+ }
+ }
+ return results;
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidationType.java b/src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidationType.java
new file mode 100644
index 0000000..932d246
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidationType.java
@@ -0,0 +1,26 @@
+/**
+ * ============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.cacher.service.rest.util;
+
+public enum CacheKeyRequestValidationType {
+
+ ADD, UPDATE, DELETE;
+
+}
diff --git a/src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTaskConfig.java b/src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTaskConfig.java
new file mode 100644
index 0000000..2a9a403
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTaskConfig.java
@@ -0,0 +1,74 @@
+/**
+ * ============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.cacher.service.tasks;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.onap.aai.cacher.service.helper.CacheHelperService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.TaskScheduler;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+import org.springframework.scheduling.config.IntervalTask;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@Configuration
+public class ScheduledTaskConfig {
+
+ private final static EELFLogger EELF_LOGGER = EELFManager.getInstance().getLogger(ScheduledTaskConfig.class);
+ private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
+ private final static int THREAD_POOL_SIZE = 10;
+ private final static String THREAD_POOL_PREFIX = "poolScheduler";
+ private final static int TASK_INTERVAL_TIME = 30000;
+ private final static int TASK_DELAY_TIME = 0;
+
+ @Configuration
+ static class RegisterTaskSchedulerViaSchedulingConfigurer implements SchedulingConfigurer {
+
+ @Autowired
+ protected CacheHelperService chs;
+
+ @Override
+ public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
+ taskRegistrar.setTaskScheduler(poolScheduler());
+ taskRegistrar.addFixedRateTask(new IntervalTask(new Runnable() {
+ @Override
+ public void run() {
+ EELF_LOGGER.info(
+ "Job @ fixed rate " + new Date() + ", Thread name is " + Thread.currentThread().getName());
+ chs.checkAndInitTasks();
+ }
+ }, TASK_INTERVAL_TIME, TASK_DELAY_TIME));
+ }
+
+ @Bean
+ public TaskScheduler poolScheduler() {
+ ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
+ scheduler.setThreadNamePrefix(THREAD_POOL_PREFIX);
+ scheduler.setPoolSize(THREAD_POOL_SIZE);
+ return scheduler;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTasks.java b/src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTasks.java
new file mode 100644
index 0000000..78c88c7
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/service/tasks/ScheduledTasks.java
@@ -0,0 +1,148 @@
+/**
+ * ============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.cacher.service.tasks;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.onap.aai.cacher.common.CacheKeyConfig;
+import org.onap.aai.cacher.dmaap.consumer.AAIDmaapEventProcessor;
+import org.onap.aai.cacher.dmaap.consumer.AAIEventConsumer;
+import org.onap.aai.cacher.dmaap.consumer.DmaapConsumerSingleton;
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.service.helper.CacheHelperService;
+import org.onap.aai.cacher.service.helper.RestClientHelperService;
+import org.onap.aai.cacher.util.AAIConstants;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.onap.aai.util.AAIConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+@Component
+public class ScheduledTasks {
+ private final static EELFLogger LOGGER = EELFManager.getInstance().getLogger(ScheduledTasks.class);
+ private final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
+
+ private int checkInterval = -1;
+ private boolean cacheLoaded = false;
+
+ @Autowired
+ AAIDmaapEventProcessor aaiDmaapEventProcessor;
+
+ @Autowired
+ CacheHelperService chs;
+
+ @Autowired
+ RestClientHelperService rchs;
+
+ /**
+ * Starts the aaiDmaapEventConsumer task bean init. Will restart 1 min after the
+ * previous one ended.
+ */
+ @Scheduled(fixedDelay = 60000, initialDelay = 0)
+ public void dmaapAAIDmaapEventProcessor() {
+ try {
+ dmaapAAIEventProcessorTask();
+ } catch (Exception e) {
+ LOGGER.error("ERROR: Exception in scheduled task [" + e.getMessage() + "].");
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ }
+ }
+
+ public void dmaapAAIEventProcessorTask() throws Exception {
+ String methodName = "dmaapAAIEventProcessorTask()";
+
+ LOGGER.info("Started fixed rate job dmaapAAIEventProcessor @ " + dateFormat.format(new Date()));
+ LOGGER.debug("started scheduled task for " + methodName + " checkInterval " + checkInterval);
+ try {
+ int delayCheck = Integer.parseInt(AAIConfig.get("aai.cacher.dmaap.consumer.delayCheck", "0"));
+ if (checkInterval > 0 && checkInterval++ < delayCheck) {
+ return;
+ }
+ checkInterval = 1;
+ if (AAIConfig.get("aai.cacher.dmaap.consumer.enableEventProcessing").equals("true")) {
+ LOGGER.info("aai.cacher.dmaap.consumer.enableEventProcessing set to true, starting AAIEventConsumer.");
+ AAIEventConsumer aec = new AAIEventConsumer("aaiDmaaPEventConsumer.properties", false);
+ aec.startProcessing(aaiDmaapEventProcessor);
+ } else {
+ LOGGER.info(
+ "aai.cacher.dmaap.consumer.enableEventProcessing set to false, not starting AAIDmaapEventConsumer.");
+ }
+ // initialize the cache
+ if (!cacheLoaded) {
+ LOGGER.info("Start loading cache @ " + dateFormat.format(new Date()));
+ init();
+ cacheLoaded = true;
+ }
+
+ } catch (Exception e) {
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ }
+ LOGGER.info("Completed fixed rate job dmaapAAIEventProcessor @ " + dateFormat.format(new Date()));
+ }
+
+ public void init() throws IOException {
+
+ Path path = Paths.get(AAIConstants.INITIAL_CACHEKEY_CONFIG_FILENAME);
+ String cacheKeyConfigJson = new String(Files.readAllBytes(path));
+ CacheKeyConfig cacheKeyConfig = new CacheKeyConfig(cacheKeyConfigJson);
+ List<CacheKey> cacheKeys = cacheKeyConfig.populateCacheKeyList();
+ chs.bulkAddCacheKeys(cacheKeys);
+
+ for (CacheKey cacheKey : cacheKeys) {
+ if ("onInit".equalsIgnoreCase(cacheKey.getTimingIndicator())) {
+ try {
+ ResponseEntity respEntity = rchs.triggerRestCall(cacheKey);
+ if (respEntity.getStatusCode().is2xxSuccessful()) {
+ Response resp = chs.populateCache(cacheKey, (String) respEntity.getBody());
+ if (resp != null) {
+ if (resp.getStatus() == Response.Status.CREATED.getStatusCode()) {
+ LOGGER.debug("cacheKey " + cacheKey.getCacheKey() + " loaded");
+ } else {
+ LOGGER.error("unexpected 2xx response status for cacheKey " + cacheKey.getCacheKey()
+ + " " + resp.getStatusInfo());
+ }
+ }
+ } else {
+ LOGGER.error("unexpected response status for cacheKey " + cacheKey.getCacheKey() + " "
+ + respEntity.getStatusCode());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ LOGGER.error("exception caught for cacheKey " + cacheKey.getCacheKey());
+ ErrorLogHelper.logException(new AAIException("AAI_4000", e));
+ }
+ }
+ }
+
+ DmaapConsumerSingleton.getInstance().setProcessEvents(true);
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/util/AAIConstants.java b/src/main/java/org/onap/aai/cacher/util/AAIConstants.java
new file mode 100644
index 0000000..b830ecb
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/util/AAIConstants.java
@@ -0,0 +1,51 @@
+/**
+ * ============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.cacher.util;
+
+public final class AAIConstants {
+ public static final String COLLECTION_CACHEKEY = "cacheKey";
+
+ /** Default to unix file separator if system property file.separator is null */
+ public static final String FILESEP = (System.getProperty("file.separator") == null) ? "/"
+ : System.getProperty("file.separator");
+
+ public static final String AAI_BUNDLECONFIG_NAME = (System.getProperty("BUNDLECONFIG_DIR") == null) ? "resources"
+ : System.getProperty("BUNDLECONFIG_DIR");
+ public static final String AAI_HOME_BUNDLECONFIG = (System.getProperty("AJSC_HOME") == null)
+ ? FILESEP + "opt" + FILESEP + "app" + FILESEP + "aai" + FILESEP + AAI_BUNDLECONFIG_NAME
+ : System.getProperty("AJSC_HOME") + FILESEP + AAI_BUNDLECONFIG_NAME;
+
+ public static final String AAI_HOME_ETC = AAI_HOME_BUNDLECONFIG + FILESEP + "etc" + FILESEP;
+ public static final String AAI_HOME_ETC_APP_PROPERTIES = AAI_HOME_ETC + "appprops" + FILESEP;
+ public static final String INITIAL_CACHEKEY_CONFIG_FILENAME = AAI_HOME_ETC_APP_PROPERTIES
+ + "initialcachekeyconfig.json";
+ public static final String AAI_RESOURCES_URI_TEMPLATES = AAI_HOME_ETC_APP_PROPERTIES
+ + "aai-resources-uri-templates.properties";
+ public static final String AAI_HOME_ETC_AUTH = AAI_HOME_ETC + "auth" + FILESEP;
+
+ public static final String AAI_TRUSTSTORE_FILENAME = "aai.truststore.filename";
+ public static final String AAI_TRUSTSTORE_PASSWD = "aai.truststore.passwd";
+ public static final String AAI_KEYSTORE_FILENAME = "aai.keystore.filename";
+ public static final String AAI_KEYSTORE_PASSWD = "aai.keystore.passwd";
+
+ private AAIConstants() {
+ // prevent instantiation
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/util/RestClient.java b/src/main/java/org/onap/aai/cacher/util/RestClient.java
new file mode 100644
index 0000000..0caffd3
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/util/RestClient.java
@@ -0,0 +1,157 @@
+/**
+ * ============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.cacher.util;
+
+import org.apache.commons.net.util.Base64;
+import org.apache.http.client.HttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.onap.aai.util.AAIConfig;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.env.Environment;
+import org.springframework.http.*;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.util.ResourceUtils;
+import org.springframework.web.client.ResponseErrorHandler;
+import org.springframework.web.client.RestTemplate;
+
+import javax.net.ssl.SSLContext;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.security.KeyStore;
+import java.util.Collections;
+
+//@Component
+public class RestClient {
+
+ private HttpClient restClient = null;
+
+ private Environment environment;
+
+ public RestClient() {
+ this.restClient = initClient();
+ }
+
+ public HttpClient getRestClient() {
+ return restClient;
+ }
+
+ /**
+ * @return initialized rest client
+ *
+ */
+ private HttpClient initClient() {
+ HttpClient rc;
+
+ try {
+ String truststore_path = AAIConstants.AAI_HOME_ETC_AUTH
+ + AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_FILENAME);
+ String truststore_password = AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_PASSWD);
+ SSLContextBuilder sslContextBuilder = SSLContextBuilder.create();
+
+ SSLContext sslContext = sslContextBuilder
+ .loadTrustMaterial(ResourceUtils.getFile(truststore_path), truststore_password.toCharArray())
+ .build();
+
+ rc = HttpClients.custom().setSSLContext(sslContext).setSSLHostnameVerifier((s, sslSession) -> true).build();
+ } catch (Exception e) {
+ // TODO Handle exceptions/logging
+ rc = null;
+ }
+ return rc;
+ }
+
+ private String getAuth(String baseUrl ) {
+ int startIndex = baseUrl.indexOf("://") + "://".length();
+ int ampersandIndex = baseUrl.indexOf('@');
+ if ( ampersandIndex >= 0 ) {
+ return baseUrl.substring(startIndex, ampersandIndex);
+ }
+ return null;
+ }
+
+ public ResponseEntity get(String baseUrl, String module, String restUri, String sourceName) throws Exception {
+ ResponseEntity responseEntity = null;
+ try {
+
+ RestTemplate restTemplate = restTemplate(new RestTemplateBuilder());
+ String endpoint;
+ if (!module.equals("-1")) {
+ endpoint = module + restUri;
+ } else {
+ endpoint = restUri;
+ }
+ HttpHeaders headers = new HttpHeaders();
+ headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ headers.add("X-FromAppId", "AAI-CACHER");
+ headers.add("X-TransactionId", "JUNIT");
+ String auth = getAuth(baseUrl);
+ String urlUpdate;
+ if ( auth != null ) {
+ byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")));
+ headers.add("Authorization", "Basic " + new String(encodedAuth));
+ urlUpdate = baseUrl.replaceAll(auth + "@", "");
+ } else {
+ urlUpdate = baseUrl;
+ }
+ HttpEntity httpEntity = new HttpEntity(headers);
+ responseEntity = restTemplate.exchange(urlUpdate + endpoint, HttpMethod.GET, httpEntity, String.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+ // TODO handle exceptions
+ }
+ return responseEntity;
+ }
+
+ @Bean
+ RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception {
+ RestTemplate restTemplate = builder.requestFactory(new HttpComponentsClientHttpRequestFactory(restClient))
+ .build();
+
+ restTemplate.setErrorHandler(new ResponseErrorHandler() {
+ @Override
+ public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
+ return clientHttpResponse.getStatusCode() != HttpStatus.OK;
+ }
+
+ @Override
+ public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
+ // TODO handle the error
+ }
+ });
+
+ return restTemplate;
+ }
+
+ private KeyStore loadPfx(String file, char[] password) throws Exception {
+ KeyStore keyStore = KeyStore.getInstance("PKCS12");
+ File key = ResourceUtils.getFile(file);
+ try (InputStream in = new FileInputStream(key)) {
+ keyStore.load(in, password);
+ }
+ return keyStore;
+ }
+}
diff --git a/src/main/java/org/onap/aai/cacher/web/JerseyConfiguration.java b/src/main/java/org/onap/aai/cacher/web/JerseyConfiguration.java
new file mode 100644
index 0000000..6498f2f
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/web/JerseyConfiguration.java
@@ -0,0 +1,132 @@
+/**
+ * ============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.cacher.web;
+
+import org.glassfish.jersey.filter.LoggingFilter;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.onap.aai.cacher.service.rest.CacheInteractionService;
+import org.onap.aai.cacher.service.rest.CacheKeyService;
+import org.reflections.Reflections;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Priority;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseFilter;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+@Component
+@ApplicationPath("/aai")
+public class JerseyConfiguration extends ResourceConfig {
+ private static final Logger log = Logger.getLogger(JerseyConfiguration.class.getName());
+
+ private Environment env;
+
+ @Autowired
+ public JerseyConfiguration(Environment env) {
+ this.env = env;
+ register(CacheKeyService.class);
+ register(CacheInteractionService.class);
+ property("jersey.config.servlet.filter.forwardOn404", true);
+ // Request Filters
+ registerFiltersForRequests();
+ // Response Filters
+ registerFiltersForResponses();
+
+ // Following registers the request headers and response headers
+ // If the LoggingFilter second argument is set to true, it will print response
+ // value as well
+ if ("true".equalsIgnoreCase(env.getProperty("aai.request.logging.enabled"))) {
+ register(new LoggingFilter(log, false));
+ }
+ }
+
+ public void registerFiltersForRequests() {
+
+ // Find all the classes within the interceptors package
+ Reflections reflections = new Reflections("org.onap.aai.interceptors");
+ // Filter them based on the clazz that was passed in
+ Set<Class<? extends ContainerRequestFilter>> filters = reflections.getSubTypesOf(ContainerRequestFilter.class);
+
+ // Check to ensure that each of the filter has the @Priority annotation and if
+ // not throw exception
+ for (Class filterClass : filters) {
+ if (filterClass.getAnnotation(Priority.class) == null) {
+ throw new RuntimeException(
+ "Container filter " + filterClass.getName() + " does not have @Priority annotation");
+ }
+ }
+
+ // Turn the set back into a list
+ List<Class<? extends ContainerRequestFilter>> filtersList = filters.stream().filter(f -> {
+ if (f.isAnnotationPresent(Profile.class) && !env.acceptsProfiles(f.getAnnotation(Profile.class).value())) {
+ return false;
+ }
+ return true;
+ }).collect(Collectors.toList());
+
+ // Sort them by their priority levels value
+ filtersList.sort((c1, c2) -> Integer.valueOf(c1.getAnnotation(Priority.class).value())
+ .compareTo(c2.getAnnotation(Priority.class).value()));
+
+ // Then register this to the jersey application
+ filtersList.forEach(this::register);
+ }
+
+ public void registerFiltersForResponses() {
+
+ // Find all the classes within the interceptors package
+ Reflections reflections = new Reflections("org.onap.aai.interceptors");
+ // Filter them based on the clazz that was passed in
+ Set<Class<? extends ContainerResponseFilter>> filters = reflections
+ .getSubTypesOf(ContainerResponseFilter.class);
+
+ // Check to ensure that each of the filter has the @Priority annotation and if
+ // not throw exception
+ for (Class filterClass : filters) {
+ if (filterClass.getAnnotation(Priority.class) == null) {
+ throw new RuntimeException(
+ "Container filter " + filterClass.getName() + " does not have @Priority annotation");
+ }
+ }
+
+ // Turn the set back into a list
+ List<Class<? extends ContainerResponseFilter>> filtersList = filters.stream().filter(f -> {
+ if (f.isAnnotationPresent(Profile.class) && !env.acceptsProfiles(f.getAnnotation(Profile.class).value())) {
+ return false;
+ }
+ return true;
+ }).collect(Collectors.toList());
+
+ // Sort them by their priority levels value
+ filtersList.sort((c1, c2) -> Integer.valueOf(c1.getAnnotation(Priority.class).value())
+ .compareTo(c2.getAnnotation(Priority.class).value()));
+
+ // Then register this to the jersey application
+ filtersList.forEach(this::register);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/aai/cacher/web/LocalHostAccessLog.java b/src/main/java/org/onap/aai/cacher/web/LocalHostAccessLog.java
new file mode 100644
index 0000000..81addb5
--- /dev/null
+++ b/src/main/java/org/onap/aai/cacher/web/LocalHostAccessLog.java
@@ -0,0 +1,58 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.web;
+
+import ch.qos.logback.access.jetty.RequestLogImpl;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.server.handler.RequestLogHandler;
+import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
+import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
+import org.springframework.boot.context.embedded.jetty.JettyServerCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Arrays;
+
+@Configuration
+public class LocalHostAccessLog {
+
+ @Bean
+ public EmbeddedServletContainerFactory jettyConfigBean() {
+ JettyEmbeddedServletContainerFactory jef = new JettyEmbeddedServletContainerFactory();
+ jef.addServerCustomizers((JettyServerCustomizer) server -> {
+
+ HandlerCollection handlers = new HandlerCollection();
+
+ Arrays.stream(server.getHandlers()).forEach(handlers::addHandler);
+
+ RequestLogHandler requestLogHandler = new RequestLogHandler();
+ requestLogHandler.setServer(server);
+
+ RequestLogImpl requestLogImpl = new RequestLogImpl();
+ requestLogImpl.setResource("/localhost-access-logback.xml");
+ requestLogImpl.start();
+
+ requestLogHandler.setRequestLog(requestLogImpl);
+ handlers.addHandler(requestLogHandler);
+ server.setHandler(handlers);
+ });
+ return jef;
+ }
+}
diff --git a/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java b/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java
new file mode 100644
index 0000000..f1198ae
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java
@@ -0,0 +1,41 @@
+/**
+ * ============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.interceptors;
+
+import org.onap.aai.util.FormatDate;
+
+import java.util.UUID;
+
+public abstract class AAIContainerFilter {
+
+ protected String genDate() {
+ FormatDate fd = new FormatDate("YYMMdd-HH:mm:ss:SSS");
+ return fd.getDateTime();
+ }
+
+ protected boolean isValidUUID(String transId) {
+ try {
+ UUID.fromString(transId);
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java b/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java
new file mode 100644
index 0000000..65d16e8
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java
@@ -0,0 +1,40 @@
+/**
+ * ============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.interceptors;
+
+public final class AAIHeaderProperties {
+
+ private AAIHeaderProperties() {
+ }
+
+ public static final String REQUEST_CONTEXT = "aai-request-context";
+
+ public static final String HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override";
+
+ public static final String TRANSACTION_ID = "X-TransactionId";
+
+ public static final String FROM_APP_ID = "X-FromAppId";
+
+ public static final String AAI_TX_ID = "X-AAI-TXID";
+
+ public static final String AAI_REQUEST = "X-REQUEST";
+
+ public static final String AAI_REQUEST_TS = "X-REQUEST-TS";
+}
diff --git a/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java b/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java
new file mode 100644
index 0000000..ea657bb
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java
@@ -0,0 +1,40 @@
+/**
+ * ============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.interceptors.post;
+
+/**
+ * Response Filter order is done reverse sorted so in the following case the
+ * first response filter would be HEADER_MANIPULATION, RESPONSE_TRANS_LOGGING,
+ * RESET_LOGGING_CONTEXT, and INVALID_RESPONSE_STATUS
+ */
+public final class AAIResponseFilterPriority {
+
+ private AAIResponseFilterPriority() {
+ }
+
+ public static final int INVALID_RESPONSE_STATUS = 1000;
+
+ public static final int RESET_LOGGING_CONTEXT = 2000;
+
+ public static final int RESPONSE_TRANS_LOGGING = 3000;
+
+ public static final int HEADER_MANIPULATION = 4000;
+
+}
diff --git a/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java b/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java
new file mode 100644
index 0000000..20fe32a
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java
@@ -0,0 +1,118 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.interceptors.post;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.interceptors.AAIHeaderProperties;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+
+import javax.annotation.Priority;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.Optional;
+
+@Priority(AAIResponseFilterPriority.RESPONSE_TRANS_LOGGING)
+public class ResponseTransactionLogging extends AAIContainerFilter implements ContainerResponseFilter {
+
+ private static final EELFLogger TRANSACTION_LOGGER = EELFManager.getInstance()
+ .getLogger(ResponseTransactionLogging.class);
+
+ @Autowired
+ private HttpServletResponse httpServletResponse;
+
+ @Autowired
+ private Environment env;
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
+ throws IOException {
+
+ this.transLogging(requestContext, responseContext);
+
+ }
+
+ private void transLogging(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
+
+ String logValue = env.getProperty("aai.transaction.logging");
+ String getValue = env.getProperty("aai.transaction.logging.get");
+ String postValue = env.getProperty("aai.transaction.logging.post");
+
+ String transId = requestContext.getHeaderString(AAIHeaderProperties.TRANSACTION_ID);
+ String fromAppId = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID);
+ String fullUri = requestContext.getUriInfo().getRequestUri().toString();
+ String requestTs = (String) requestContext.getProperty(AAIHeaderProperties.AAI_REQUEST_TS);
+
+ String httpMethod = requestContext.getMethod();
+
+ String status = Integer.toString(responseContext.getStatus());
+
+ String request = (String) requestContext.getProperty(AAIHeaderProperties.AAI_REQUEST);
+ String response = this.getResponseString(responseContext);
+
+ if (!Boolean.parseBoolean(logValue)) {
+ } else if (!Boolean.parseBoolean(getValue) && "GET".equals(httpMethod)) {
+ } else if (!Boolean.parseBoolean(postValue) && "POST".equals(httpMethod)) {
+ } else {
+
+ JsonObject logEntry = new JsonObject();
+ logEntry.addProperty("transactionId", transId);
+ logEntry.addProperty("status", status);
+ logEntry.addProperty("rqstDate", requestTs);
+ logEntry.addProperty("respDate", this.genDate());
+ logEntry.addProperty("sourceId", fromAppId + ":" + transId);
+ logEntry.addProperty("resourceId", fullUri);
+ logEntry.addProperty("resourceType", httpMethod);
+ logEntry.addProperty("rqstBuf", Objects.toString(request, ""));
+ logEntry.addProperty("respBuf", Objects.toString(response, ""));
+
+ try {
+ TRANSACTION_LOGGER.debug(logEntry.toString());
+ } catch (Exception e) {
+ ErrorLogHelper.logError("AAI_4000", "Exception writing transaction log.");
+ }
+ }
+
+ }
+
+ private String getResponseString(ContainerResponseContext responseContext) {
+ JsonObject response = new JsonObject();
+ response.addProperty("ID", responseContext.getHeaderString(AAIHeaderProperties.AAI_TX_ID));
+ response.addProperty("Content-Type", this.httpServletResponse.getContentType());
+ response.addProperty("Response-Code", responseContext.getStatus());
+ response.addProperty("Headers", responseContext.getHeaders().toString());
+ Optional<Object> entityOptional = Optional.ofNullable(responseContext.getEntity());
+ if (entityOptional.isPresent()) {
+ response.addProperty("Entity", entityOptional.get().toString());
+ } else {
+ response.addProperty("Entity", "");
+ }
+ return response.toString();
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java b/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java
new file mode 100644
index 0000000..140165b
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java
@@ -0,0 +1,38 @@
+/**
+ * ============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.interceptors.pre;
+
+public final class AAIRequestFilterPriority {
+
+ private AAIRequestFilterPriority() {}
+
+ public static final int REQUEST_TRANS_LOGGING = 1000;
+
+ public static final int HEADER_VALIDATION = 2000;
+
+ public static final int SET_LOGGING_CONTEXT = 3000;
+
+ public static final int HTTP_HEADER = 4000;
+
+ public static final int AUTHORIZATION = 4500;
+
+ public static final int HEADER_MANIPULATION = 6000;
+
+}
diff --git a/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java b/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java
new file mode 100644
index 0000000..dfc4376
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java
@@ -0,0 +1,87 @@
+/**
+ * ============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.interceptors.pre;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+import javax.annotation.Priority;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.interceptors.AAIHeaderProperties;
+import org.onap.aai.logging.ErrorLogHelper;
+
+@PreMatching
+@Priority(AAIRequestFilterPriority.HEADER_VALIDATION)
+public class HeaderValidation extends AAIContainerFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+
+ Optional<Response> oResp;
+
+ String transId = requestContext.getHeaderString(AAIHeaderProperties.TRANSACTION_ID);
+ String fromAppId = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID);
+
+ List<MediaType> acceptHeaderValues = requestContext.getAcceptableMediaTypes();
+
+ oResp = this.validateHeaderValuePresence(fromAppId, "AAI_4009", acceptHeaderValues);
+ if (oResp.isPresent()) {
+ requestContext.abortWith(oResp.get());
+ return;
+ }
+ oResp = this.validateHeaderValuePresence(transId, "AAI_4010", acceptHeaderValues);
+ if (oResp.isPresent()) {
+ requestContext.abortWith(oResp.get());
+ return;
+ }
+
+ if (!this.isValidUUID(transId)) {
+ transId = UUID.randomUUID().toString();
+ requestContext.getHeaders().get(AAIHeaderProperties.TRANSACTION_ID).clear();
+ requestContext.getHeaders().add(AAIHeaderProperties.TRANSACTION_ID, transId);
+ }
+
+ }
+
+ private Optional<Response> validateHeaderValuePresence(String value, String errorCode,
+ List<MediaType> acceptHeaderValues) {
+ Response response = null;
+ AAIException aaie;
+ if (value == null) {
+ aaie = new AAIException(errorCode);
+ return Optional.of(Response.status(aaie.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>()))
+ .build());
+ }
+
+ return Optional.ofNullable(response);
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java b/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java
new file mode 100644
index 0000000..c627b85
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java
@@ -0,0 +1,79 @@
+/**
+ * ============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.interceptors.pre;
+
+import org.onap.aai.cacher.Profiles;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.logging.ErrorLogHelper;
+import org.onap.aai.cacher.service.AuthorizationService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+
+import javax.annotation.Priority;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+@Profile(Profiles.ONE_WAY_SSL)
+@PreMatching
+@Priority(AAIRequestFilterPriority.AUTHORIZATION)
+public class OneWaySslAuthorization extends AAIContainerFilter implements ContainerRequestFilter {
+
+ @Autowired
+ private AuthorizationService authorizationService;
+
+ @Override
+ public void filter(ContainerRequestContext containerRequestContext) throws IOException
+ {
+
+ String basicAuth = containerRequestContext.getHeaderString("Authorization");
+ List<MediaType> acceptHeaderValues = containerRequestContext.getAcceptableMediaTypes();
+
+ if(basicAuth == null || !basicAuth.startsWith("Basic ")){
+ Optional<Response> responseOptional = errorResponse("AAI_3300", acceptHeaderValues);
+ containerRequestContext.abortWith(responseOptional.get());
+ return;
+ }
+
+ basicAuth = basicAuth.replaceAll("Basic ", "");
+
+ if(!authorizationService.checkIfUserAuthorized(basicAuth)){
+ Optional<Response> responseOptional = errorResponse("AAI_3300", acceptHeaderValues);
+ containerRequestContext.abortWith(responseOptional.get());
+ return;
+ }
+
+ }
+
+ private Optional<Response> errorResponse(String errorCode, List<MediaType> acceptHeaderValues) {
+ AAIException aaie = new AAIException(errorCode);
+ return Optional.of(Response.status(aaie.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>()))
+ .build());
+
+ }
+}
diff --git a/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java b/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java
new file mode 100644
index 0000000..1d9063f
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java
@@ -0,0 +1,60 @@
+/**
+ * ============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.interceptors.pre;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.Priority;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.interceptors.AAIHeaderProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+
+@PreMatching
+@Priority(AAIRequestFilterPriority.HEADER_MANIPULATION)
+public class RequestHeaderManipulation extends AAIContainerFilter implements ContainerRequestFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) {
+
+ String uri = requestContext.getUriInfo().getPath();
+ this.addRequestContext(uri, requestContext.getHeaders());
+
+ }
+
+ private void addRequestContext(String uri, MultivaluedMap<String, String> requestHeaders) {
+
+ String rc = "";
+
+ if (requestHeaders.containsKey(AAIHeaderProperties.REQUEST_CONTEXT)) {
+ requestHeaders.remove(AAIHeaderProperties.REQUEST_CONTEXT);
+ }
+ requestHeaders.put(AAIHeaderProperties.REQUEST_CONTEXT, Collections.singletonList(rc));
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java b/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java
new file mode 100644
index 0000000..f9976c2
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java
@@ -0,0 +1,131 @@
+/**
+ * ============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.interceptors.pre;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Random;
+import java.util.UUID;
+import java.security.SecureRandom;
+
+import javax.annotation.Priority;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.server.ContainerException;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.interceptors.AAIHeaderProperties;
+import org.onap.aai.util.AAIConfig;
+import org.onap.aai.util.AAIConstants;
+import org.onap.aai.util.HbaseSaltPrefixer;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.google.gson.JsonObject;
+import org.springframework.util.StringUtils;
+
+@PreMatching
+@Priority(AAIRequestFilterPriority.REQUEST_TRANS_LOGGING)
+public class RequestTransactionLogging extends AAIContainerFilter implements ContainerRequestFilter {
+
+ @Autowired
+ private HttpServletRequest httpServletRequest;
+
+ private static final String DEFAULT_CONTENT_TYPE = MediaType.APPLICATION_JSON;
+ private static final String DEFAULT_RESPONSE_TYPE = MediaType.APPLICATION_XML;
+
+ private static final String CONTENT_TYPE = "Content-Type";
+ private static final String ACCEPT = "Accept";
+ private static final String TEXT_PLAIN = "text/plain";
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+
+ String currentTimeStamp = genDate();
+ String fullId = this.getAAITxIdToHeader(currentTimeStamp);
+ this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_TX_ID, fullId);
+ this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_REQUEST, this.getRequest(requestContext, fullId));
+ this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_REQUEST_TS, currentTimeStamp);
+ this.addDefaultContentType(requestContext);
+ }
+
+ private void addToRequestContext(ContainerRequestContext requestContext, String name, String aaiTxIdToHeader) {
+ requestContext.setProperty(name, aaiTxIdToHeader);
+ }
+
+ private void addDefaultContentType(ContainerRequestContext requestContext) {
+
+ String contentType = requestContext.getHeaderString(CONTENT_TYPE);
+ String acceptType = requestContext.getHeaderString(ACCEPT);
+
+ if(contentType == null || contentType.contains(TEXT_PLAIN)){
+ requestContext.getHeaders().putSingle(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
+ }
+
+ if(StringUtils.isEmpty(acceptType) || acceptType.contains(TEXT_PLAIN)){
+ requestContext.getHeaders().putSingle(ACCEPT, DEFAULT_RESPONSE_TYPE);
+ }
+ }
+
+ private String getAAITxIdToHeader(String currentTimeStamp) {
+ String txId = UUID.randomUUID().toString();
+ try {
+ Random rand = new SecureRandom();
+ int number = rand.nextInt(99999);
+ txId = HbaseSaltPrefixer.getInstance().prependSalt(AAIConfig.get(AAIConstants.AAI_NODENAME) + "-"
+ + currentTimeStamp + "-" + number ); //new Random(System.currentTimeMillis()).nextInt(99999)
+ } catch (AAIException e) {
+ }
+
+ return txId;
+ }
+
+ private String getRequest(ContainerRequestContext requestContext, String fullId) {
+
+ JsonObject request = new JsonObject();
+ request.addProperty("ID", fullId);
+ request.addProperty("Http-Method", requestContext.getMethod());
+ request.addProperty(CONTENT_TYPE, httpServletRequest.getContentType());
+ request.addProperty("Headers", requestContext.getHeaders().toString());
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ InputStream in = requestContext.getEntityStream();
+
+ try {
+ if (in.available() > 0) {
+ ReaderWriter.writeTo(in, out);
+ byte[] requestEntity = out.toByteArray();
+ request.addProperty("Payload", new String(requestEntity, "UTF-8"));
+ requestContext.setEntityStream(new ByteArrayInputStream(requestEntity));
+ }
+ } catch (IOException ex) {
+ throw new ContainerException(ex);
+ }
+
+ return request.toString();
+ }
+
+}
diff --git a/src/main/java/org/onap/aai/interceptors/pre/SetLoggingContext.java b/src/main/java/org/onap/aai/interceptors/pre/SetLoggingContext.java
new file mode 100644
index 0000000..368d071
--- /dev/null
+++ b/src/main/java/org/onap/aai/interceptors/pre/SetLoggingContext.java
@@ -0,0 +1,70 @@
+/**
+ * ============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.interceptors.pre;
+
+import java.io.IOException;
+
+import javax.annotation.Priority;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+
+import org.onap.aai.interceptors.AAIContainerFilter;
+import org.onap.aai.interceptors.AAIHeaderProperties;
+import org.onap.aai.logging.LoggingContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+
+@PreMatching
+@Priority(AAIRequestFilterPriority.SET_LOGGING_CONTEXT)
+public class SetLoggingContext extends AAIContainerFilter implements ContainerRequestFilter {
+
+ @Autowired
+ private Environment environment;
+
+ @Autowired
+ private HttpServletRequest httpServletRequest;
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+
+ String uri = httpServletRequest.getRequestURI();
+ String queryString = httpServletRequest.getQueryString();
+
+ if(queryString != null && !queryString.isEmpty()){
+ uri = uri + "?" + queryString;
+ }
+
+ String httpMethod = requestContext.getMethod();
+ String transId = requestContext.getHeaderString(AAIHeaderProperties.TRANSACTION_ID);
+ String fromAppId = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID);
+
+ LoggingContext.init();
+ LoggingContext.requestId(transId);
+ LoggingContext.partnerName(fromAppId);
+ LoggingContext.targetEntity(environment.getProperty("spring.application.name"));
+ LoggingContext.component(fromAppId);
+ LoggingContext.serviceName(httpMethod + " " + uri);
+ LoggingContext.targetServiceName(httpMethod + " " + uri);
+ LoggingContext.statusCode(LoggingContext.StatusCode.COMPLETE);
+ }
+
+}
diff --git a/src/main/jenkins/Jenkinsfile b/src/main/jenkins/Jenkinsfile
new file mode 100644
index 0000000..c74d439
--- /dev/null
+++ b/src/main/jenkins/Jenkinsfile
@@ -0,0 +1,31 @@
+node ("${BUILD_SLAVE}") {
+ // get the jenkinsfile root directory
+ def rootDir = pwd()
+
+ def JAVA_HOME = tool 'jdk180'
+ env.PATH = "${JAVA_HOME}/bin:${env.PATH}"
+ sh 'which java'
+ sh 'java -version'
+
+ env.DOCKER_HOST="tcp://localhost:4243"
+
+ // load external groovy scripts
+ def build
+ def checkout
+ def deploy
+ dir('tmp') {
+ git url: "${GIT_URL}", branch: "${GIT_BRANCH}"
+ checkout = load 'src/main/jenkins/checkout.groovy'
+ build = load 'src/main/jenkins/build.groovy'
+ deploy = load 'src/main/jenkins/deploy.groovy'
+ }
+
+ // check out code from git
+ checkout.gitCheckout()
+
+ // build the git project
+ build.buildProject()
+
+ deploy.deployService()
+
+} \ No newline at end of file
diff --git a/src/main/jenkins/build.groovy b/src/main/jenkins/build.groovy
new file mode 100644
index 0000000..3170510
--- /dev/null
+++ b/src/main/jenkins/build.groovy
@@ -0,0 +1,14 @@
+
+
+def buildProject() {
+ stage 'Build Git Project'
+ wrap([$class: 'ConfigFileBuildWrapper', managedFiles: [[fileId: 'eb0c7cc1-e851-4bc2-9401-2680c225f88c', targetLocation: '', variable: 'MAVEN_SETTINGS']]]) {
+ mvn '-s $MAVEN_SETTINGS -f pom.xml'
+}
+}
+
+def mvn(args) {
+ sh "${tool 'maven3'}/bin/mvn ${args} ${MAVEN_GOALS}"
+}
+
+return this \ No newline at end of file
diff --git a/src/main/jenkins/checkout.groovy b/src/main/jenkins/checkout.groovy
new file mode 100644
index 0000000..ed439ec
--- /dev/null
+++ b/src/main/jenkins/checkout.groovy
@@ -0,0 +1,14 @@
+
+def gitCheckout() {
+ stage 'Checkout GIT'
+ //different ways to checkout
+ //checkout from master
+ //git "url: ${GIT_URL}, branch: ${GIT_BRANCH}"
+ //checkout from branch hardcoding"
+ //git branch: 'jenkins_deploy_test', credentialsId: 'b9bbafe5-53ce-4d2c-8b84-09137f75c592', url: 'https://codecloud.web.att.com/scm/st_ocnp/sdk-java-starter.git'
+ //checkout from branch parameters with credentials
+ //git branch: "${GIT_BRANCH}", credentialsId: 'b9bbafe5-53ce-4d2c-8b84-09137f75c592', url: "${GIT_URL}"
+ //checkout from branch parameters with no credentials
+ git branch: "${GIT_BRANCH}", url: "${GIT_URL}"
+}
+return this \ No newline at end of file
diff --git a/src/main/jenkins/deploy.groovy b/src/main/jenkins/deploy.groovy
new file mode 100644
index 0000000..1a000e3
--- /dev/null
+++ b/src/main/jenkins/deploy.groovy
@@ -0,0 +1,15 @@
+def deployService(){
+ stage 'Deploying Service'
+
+ // get the jenkinsfile root directory
+ def ROOT_DIR = pwd()
+ ROOT_DIR = "${ROOT_DIR}"+'/src/main/kubernetes'
+ echo "ROOTDIR : ${ROOT_DIR}"
+ sh "/opt/app/kubernetes/v1.3.4/bin/kubectl --kubeconfig=${ROOT_DIR}/kubectl.conf replace --force --cascade -f ${ROOT_DIR}/${artifactId}-svc.yaml"
+ sh "/opt/app/kubernetes/v1.3.4/bin/kubectl --kubeconfig=${ROOT_DIR}/kubectl.conf replace --force --cascade -f ${ROOT_DIR}/${artifactId}-rc.yaml"
+}
+return this
+
+
+
+
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..cd51b92
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,57 @@
+info.build.artifact=@project.artifactId@
+info.build.name=@project.name@
+info.build.description=@project.description@
+info.build.version=@project.version@
+
+spring.application.name=aai-cacher
+spring.jersey.type=filter
+spring.mvc.urls=swagger,docs,prometheus
+
+
+server.contextPath=/
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
+
+spring.profiles.active=production,one-way-ssl
+
+#The max number of active threads in this pool
+server.tomcat.max-threads=200
+#The minimum number of threads always kept alive
+server.tomcat.min-Spare-Threads=25
+#The number of milliseconds before an idle thread shutsdown, unless the number of active threads are less or equal to minSpareThreads
+server.tomcat.max-idle-time=60000
+
+
+#Add this properties only if you want to change the URL, AJSC Framework interceptors will intercept
+#com.att.ajsc.common.interceptors.PreInterceptor.url=/**
+#com.att.ajsc.common.interceptors.PostInterceptor.url=/**
+
+#Servlet context parameters
+server.context_parameters.p-name=value #context parameter with p-name as key and value as value.
+kubernetes.namespace=org-onap-aai
+
+#Dont override
+archetype.version=6.3.3.8
+archetype.name=sdk-java-jersey-archetype
+
+server.local.startpath=src/main/resources/
+server.basic.auth.location=${server.local.startpath}etc/auth/realm.properties
+
+server.port = 8444
+server.ssl.enabled-protocols=TLSv1.1,TLSv1.2
+server.ssl.key-store=${server.local.startpath}etc/auth/aai_keystore
+server.ssl.key-store-password=password(OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0)
+server.ssl.trust-store=${server.local.startpath}etc/auth/aai_keystore
+server.ssl.trust-store-password=password(OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0)
+server.ssl.client-auth=want
+server.ssl.key-store-type=JKS
+
+#mongodb configuration values
+mongodb.host=localhost
+mongodb.dbName=aai
+mongodb.port=27017
+
+#logging configurations
+aai.transaction.logging=true
+aai.transaction.logging.get=true
+aai.transaction.logging.post=true
+
diff --git a/src/main/resources/etc/appprops/aai-resources-uri-templates.properties b/src/main/resources/etc/appprops/aai-resources-uri-templates.properties
new file mode 100644
index 0000000..44066e1
--- /dev/null
+++ b/src/main/resources/etc/appprops/aai-resources-uri-templates.properties
@@ -0,0 +1,95 @@
+allotted-resource=/allotted-resources/allotted-resource/{id}
+availability-zone=/availability-zones/availability-zone/{availability-zone-name}
+class-of-service=/classes-of-service/class-of-service/{cos}
+cloud-region=/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}
+collection=/network/collections/collection/{collection-id}
+complex=/cloud-infrastructure/complexes/complex/{physical-location-id}
+configuration=/network/configurations/configuration/{configuration-id}
+connector=/business/connectors/connector/{resource-instance-id}
+constrained-element-set=/constrained-element-sets/constrained-element-set/{constrained-element-set-uuid}
+ctag-assignment=/ctag-assignments/ctag-assignment/{vlan-id-inner}
+ctag-pool=/ctag-pools/ctag-pool/{target-pe}/{availability-zone-name}
+customer=/business/customers/customer/{global-customer-id}
+cvlan-tag-entry=/cvlan-tags/cvlan-tag-entry/{cvlan-tag}
+dvs-switch=/dvs-switches/dvs-switch/{switch-name}
+element-choice-set=/element-choice-sets/element-choice-set/{element-choice-set-uuid}
+entitlement=/entitlements/entitlement/{group-uuid}/{resource-uuid}
+evc=/evcs/evc/{evc-id}
+flavor=/flavors/flavor/{flavor-id}
+forwarder-evc=/forwarder-evcs/forwarder-evc/{forwarder-evc-id}
+forwarder=/forwarders/forwarder/{sequence}
+forwarding-path=/network/forwarding-paths/forwarding-path/{forwarding-path-id}
+generic-vnf=/network/generic-vnfs/generic-vnf/{vnf-id}
+group-assignment=/group-assignments/group-assignment/{group-id}
+host-route=/host-routes/host-route/{host-route-id}
+image=/images/image/{image-id}
+instance-group=/network/instance-groups/instance-group/{id}
+ipsec-configuration=/network/ipsec-configurations/ipsec-configuration/{ipsec-configuration-id}
+l-interface=/l-interfaces/l-interface/{interface-name}
+l3-interface-ipv4-address-list=/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+l3-interface-ipv6-address-list=/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+l3-network=/network/l3-networks/l3-network/{network-id}
+lag-interface=/lag-interfaces/lag-interface/{interface-name}
+lag-link=/network/lag-links/lag-link/{link-name}
+license=/licenses/license/{group-uuid}/{resource-uuid}
+line-of-business=/business/lines-of-business/line-of-business/{line-of-business-name}
+logical-link=/network/logical-links/logical-link/{link-name}
+metadatum=/metadata/metadatum/{metaname}
+model-constraint=/model-constraints/model-constraint/{model-constraint-uuid}
+model-element=/model-elements/model-element/{model-element-uuid}
+model-ver=/model-vers/model-ver/{model-version-id}
+model=/service-design-and-creation/models/model/{model-invariant-id}
+multicast-configuration=/network/multicast-configurations/multicast-configuration/{multicast-configuration-id}
+named-query-element=/named-query-elements/named-query-element/{named-query-element-uuid}
+named-query=/service-design-and-creation/named-queries/named-query/{named-query-uuid}
+network-policy=/network/network-policies/network-policy/{network-policy-id}
+network-profile=/cloud-infrastructure/network-profiles/network-profile/{nm-profile-name}
+newvce=/network/newvces/newvce/{vnf-id2}
+nos-server=/nos-servers/nos-server/{nos-server-id}
+oam-network=/oam-networks/oam-network/{network-uuid}
+operational-environment=/cloud-infrastructure/operational-environments/operational-environment/{operational-environment-id}
+overloaded-model=/overloaded-model/{model-invariant-id}/{model-name-version-id}
+owning-entity=/business/owning-entities/owning-entity/{owning-entity-id}
+p-interface=/p-interfaces/p-interface/{interface-name}
+physical-link=/network/physical-links/physical-link/{link-name}
+platform=/business/platforms/platform/{platform-name}
+pnf=/network/pnfs/pnf/{pnf-name}
+port-group=/port-groups/port-group/{interface-id}
+project=/business/projects/project/{project-name}
+property-constraint=/property-constraints/property-constraint/{property-constraint-uuid}
+pserver=/cloud-infrastructure/pservers/pserver/{hostname}
+related-lookup=/related-lookups/related-lookup/{related-lookup-uuid}
+relationship=/relationship-list/relationship/{related-link}
+route-table-reference=/network/route-table-references/route-table-reference/{route-table-reference-id}
+route-target=/route-targets/route-target/{global-route-target}/{route-target-role}
+routing-instance=/routing-instances/routing-instance/{routing-instance-id}
+segmentation-assignment=/segmentation-assignments/segmentation-assignment/{segmentation-id}
+service-capability=/service-design-and-creation/service-capabilities/service-capability/{service-type}/{vnf-type}
+service-instance=/service-instances/service-instance/{service-instance-id}
+service-subscription=/service-subscriptions/service-subscription/{service-type}
+service=/service-design-and-creation/services/service/{service-id}
+site-pair-set=/network/site-pair-sets/site-pair-set/{site-pair-set-id}
+site-pair=/site-pairs/site-pair/{site-pair-id}
+snapshot=/snapshots/snapshot/{snapshot-id}
+sriov-pf=/sriov-pfs/sriov-pf/{pf-pci-id}
+sriov-vf=/sriov-vfs/sriov-vf/{pci-id}
+subnet=/subnets/subnet/{subnet-id}
+tenant=/tenants/tenant/{tenant-id}
+tunnel-xconnect=/tunnel-xconnects/tunnel-xconnect/{id}
+vce=/network/vces/vce/{vnf-id}
+vf-module=/vf-modules/vf-module/{vf-module-id}
+vig-server=/vig-servers/vig-server/{vig-address-type}
+vip-ipv4-address-list=/vip-ipv4-address-list/{vip-ipv4-address}
+vip-ipv6-address-list=/vip-ipv6-address-list/{vip-ipv6-address}
+virtual-data-center=/cloud-infrastructure/virtual-data-centers/virtual-data-center/{vdc-id}
+vlan-mapping=/vlan-mappings/vlan-mapping/{vlan-mapping-id}
+vlan=/vlans/vlan/{vlan-interface}
+vnf-image=/service-design-and-creation/vnf-images/vnf-image/{vnf-image-uuid}
+vnf=/vnf/{vnf-id}
+vnfc=/network/vnfcs/vnfc/{vnfc-name}
+volume-group=/volume-groups/volume-group/{volume-group-id}
+volume=/volumes/volume/{volume-id}
+vpls-pe=/network/vpls-pes/vpls-pe/{equipment-name}
+vpn-binding=/network/vpn-bindings/vpn-binding/{vpn-id}
+vserver=/vservers/vserver/{vserver-id}
+zone=/network/zones/zone/{zone-id} \ No newline at end of file
diff --git a/src/main/resources/etc/appprops/aaiDmaaPEventConsumer.properties b/src/main/resources/etc/appprops/aaiDmaaPEventConsumer.properties
new file mode 100644
index 0000000..398e175
--- /dev/null
+++ b/src/main/resources/etc/appprops/aaiDmaaPEventConsumer.properties
@@ -0,0 +1,23 @@
+TransportType=TBD
+Latitude=TBD
+Longitude=TBD
+
+Version=1.0
+ServiceName=TBD
+Environment=TEST
+Partner=BOT_R
+routeOffer=MR1SBKCD
+SubContextPath=/
+Protocol=http
+MethodType=GET
+username=TBD
+password=TBD
+contenttype=application/json
+host=TBD
+topic=AAI-EVENT
+group=aaiEventConsumer-dev
+id=NA
+timeout=15000
+limit=1000
+filter={"event-header.domain":"devINT1"}
+sessionstickinessrequired=no \ No newline at end of file
diff --git a/src/main/resources/etc/appprops/aaiconfig.properties b/src/main/resources/etc/appprops/aaiconfig.properties
new file mode 100644
index 0000000..0524c13
--- /dev/null
+++ b/src/main/resources/etc/appprops/aaiconfig.properties
@@ -0,0 +1,5 @@
+aai.truststore.filename=aai_keystore
+aai.truststore.passwd.x=OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0
+aai.logging.maxStackTraceEntries=10
+aai.cacher.dmaap.consumer.enableEventProcessing=false
+aai.cacher.dmaap.consumer.delayCheck=2
diff --git a/src/main/resources/etc/appprops/error.properties b/src/main/resources/etc/appprops/error.properties
new file mode 100644
index 0000000..896df00
--- /dev/null
+++ b/src/main/resources/etc/appprops/error.properties
@@ -0,0 +1,173 @@
+# Adding comment trying to trigger a build
+#------------------------------------------------------------------------------- ----------
+#Key=Disposition:Category:Severity:Error Code:HTTP ResponseCode:RESTError Code:Error Message
+#------------------------------------------------------------------------------- ----------
+# testing code, please don't change unless error utility source code changes
+AAI_TESTING=5:2:WARN:0000:400:0001:Error code for testing
+
+# General success
+AAI_0000=0:0:INFO:0000:200:0000:Success
+
+# health check success
+AAI_0001=0:0:INFO:0001:200:0001:Success X-FromAppId=%1 X-TransactionId=%2
+AAI_0002=0:0:INFO:0002:200:0001:Successful health check
+
+# Success with additional info
+AAI_0003=0:3:INFO:0003:202:0003:Success with additional info performing %1 on %2. Added %3 with key %4
+AAI_0004=0:3:INFO:0004:202:0003:Added prerequisite object to db
+
+#--- aairest: 3000-3299
+# svc errors
+AAI_3000=5:2:INFO:3000:400:3000:Invalid input performing %1 on %2
+AAI_3001=5:6:INFO:3001:404:3001:Resource not found for %1 using id %2
+AAI_3002=5:1:WARN:3002:400:3002:Error writing output performing %1 on %2
+AAI_3003=5:1:WARN:3003:400:3003:Failed to make edge to missing target node of type %3 with keys %4 performing %1 on %2
+AAI_3005=5:6:WARN:3005:404:3001:Node cannot be directly accessed for read, must be accessed via ancestor(s)
+AAI_3006=5:6:WARN:3006:404:3001:Node cannot be directly accessed for write, must be accessed via ancestor(s)
+AAI_3007=5:6:INFO:3007:410:3007:This version (%1) of the API is retired, please migrate to %2
+AAI_3008=5:6:WARN:3008:400:3008:URI is not encoded in UTF-8
+AAI_3009=5:6:WARN:3009:400:3002:Malformed URL
+AAI_3010=5:6:WARN:3010:400:3002:Cannot write via this URL
+AAI_3011=5:6:WARN:3011:400:3000:Unknown XML namespace used in payload
+AAI_3012=5:6:WARN:3012:400:3012:Unrecognized AAI function
+AAI_3013=5:6:WARN:3013:400:3013:Query payload missing required parameters %1
+AAI_3014=5:6:WARN:3014:400:3014:Query payload is invalid %1
+# pol errors
+AAI_3100=5:1:WARN:3100:400:3100:Unsupported operation %1
+AAI_3101=5:1:WARN:3101:403:3101:Attempt by client %1 to execute API %2
+AAI_3102=5:1:WARN:3102:400:3102:Error parsing input performing %1 on %2
+AAI_3300=5:1:WARN:3300:403:3300:Unauthorized
+AAI_3301=5:1:WARN:3301:401:3301:Stale credentials
+AAI_3302=5:1:WARN:3302:401:3301:Not authenticated
+AAI_3303=5:1:WARN:3303:403:3300:Too many objects would be returned by this request, please refine your request and retry
+
+#--- aaigen: 4000-4099
+AAI_4000=5:4:ERROR:4000:500:3002:Internal Error
+AAI_4001=5:4:FATAL:4001:500:3002:Configuration file not found
+AAI_4002=5:4:FATAL:4002:500:3002:Error reading Configuration file
+AAI_4003=5:4:ERROR:4003:500:3002:Error writing to log file
+AAI_4004=5:4:FATAL:4004:500:3002:Error reading/parsing the error properties file
+AAI_4005=5:4:FATAL:4005:500:3002:Missing or invalid configuration parameter
+AAI_4006=5:4:FATAL:4006:500:3002:Unexpected error in service
+AAI_4007=5:4:WARN:4007:500:3102:Input parsing error
+AAI_4008=5:4:ERROR:4008:500:3002:Output parsing error
+AAI_4009=4:0:WARN:4009:400:3000:Invalid X-FromAppId in header
+AAI_4010=4:0:WARN:4010:400:3000:Invalid X-TransactionId in header
+AAI_4011=5:4:ERROR:4011:500:3002:Missing data for REST error response
+AAI_4014=4:0:WARN:4014:400:3000:Invalid Accept header
+AAI_4015=4:0:WARN:4015:400:3000:You must provide at least one indexed property
+AAI_4016=4:0:WARN:4016:400:3000:The depth parameter must be a number or the string "all"
+AAI_4017=5:2:INFO:4017:400:3000:Could not set property
+AAI_4018=5:2:WARN:4018:400:3000:Unable to convert the string to integer
+#--- aaidbmap: 5102-5199
+AAI_5102=5:4:FATAL:5102:500:3002:Graph database is null after open
+AAI_5105=5:4:ERROR:5105:500:3002:Unexpected error reading/updating database
+AAI_5106=5:4:WARN:5106:404:3001:Node not found
+AAI_5107=5:2:WARN:5107:400:3000:Required information missing
+AAI_5108=5:2:WARN:5108:200:0:Unexpected information in request being ignored
+
+#--- aaidbgen: 6101-6199
+AAI_6101=5:4:ERROR:6101:500:3002:null JanusGraph object passed
+AAI_6102=5:4:WARN:6102:400:3000:Passed-in property is not valid for this nodeType
+AAI_6103=5:4:WARN:6103:400:3000:Required Node-property not found in input data
+AAI_6104=5:4:WARN:6104:400:3000:Required Node-property was passed with no data
+AAI_6105=5:4:WARN:6105:400:3000:Node-Key-Property not defined in DbMaps
+AAI_6106=5:4:WARN:6106:400:3000:Passed-in property is not valid for this edgeType
+AAI_6107=5:4:WARN:6107:400:3000:Required Edge-property not found in input data
+AAI_6108=5:4:WARN:6108:400:3000:Required Edge-property was passed with no data
+AAI_6109=5:4:WARN:6109:400:3000:Bad dependent Node value
+AAI_6110=5:4:ERROR:6110:400:3100:Node cannot be deleted
+AAI_6111=5:4:WARN:6111:400:3000:JSON processing error
+AAI_6112=5:4:ERROR:6112:400:3000:More than one node found by getUniqueNode()
+AAI_6114=5:4:INFO:6114:404:3001:Node Not Found
+AAI_6115=5:4:ERROR:6115:400:3000:Unrecognized NodeType
+AAI_6116=5:4:ERROR:6116:400:3000:Unrecognized Property
+AAI_6117=5:4:ERROR:6117:400:3000:Uniqueness constraint violated
+AAI_6118=5:4:WARN:6118:400:3000:Required Field not passed.
+AAI_6120=5:4:WARN:6120:400:3000:Bad Parameter Passed
+AAI_6121=5:4:ERROR:6121:400:3000:Problem with internal AAI reference data
+AAI_6122=5:4:ERROR:6122:400:3000:Data Set not complete in DB for this request
+AAI_6123=5:4:ERROR:6123:500:3000:Bad Data found by DataGrooming Tool - Investigate
+AAI_6124=5:4:ERROR:6124:500:3000:File read/write error
+AAI_6125=5:4:WARN:6125:500:3000:Problem Pulling Data Set
+AAI_6126=5:4:ERROR:6126:400:3000:Edge cannot be deleted
+AAI_6127=5:4:INFO:6127:404:3001:Edge Not Found
+AAI_6128=5:4:INFO:6128:500:3000:Unexpected error
+AAI_6129=5:4:INFO:6129:404:3003:Error making edge to target node
+AAI_6130=5:4:WARN:6130:412:3000:Precondition Required
+AAI_6131=5:4:WARN:6131:412:3000:Precondition Failed
+AAI_6132=5:4:WARN:6132:400:3000:Bad Model Definition
+AAI_6133=5:4:WARN:6133:400:3000:Bad Named Query Definition
+AAI_6134=5:4:ERROR:6134:500:6134:Could not persist transaction to storage back end. Exhausted retry amount
+AAI_6135=5:4:WARN:6135:412:3000:Resource version specified on create
+AAI_6136=5:4:ERROR:6136:400:3000:Object cannot hold multiple items
+AAI_6137=5:4:ERROR:6137:400:3000:Cannot perform writes on multiple vertices
+AAI_6138=5:4:ERROR:6138:400:3000:Cannot delete multiple vertices
+AAI_6139=5:4:ERROR:6139:404:3000:Attempted to add edge to vertex that does not exist
+AAI_6140=5:4:ERROR:6140:400:3000:Edge multiplicity violated
+AAI_6141=5:4:WARN:6141:400:3000:Please Refine Query
+AAI_6142=5:4:INFO:6142:400:3000:Retrying transaction
+AAI_6143=5:4:INFO:6143:400:3000:Ghost vertex found
+AAI_6144=5:4:WARN:6144:400:3000:Cycle found in graph
+AAI_6145=5:4:ERROR:6145:400:3000:Cannot create a nested/containment edge via relationship
+AAI_6146=5:4:ERROR:6146:400:3000:Ambiguous identity map found, use a URI instead
+AAI_6147=5:4:ERROR:6147:400:3000:Payload Limit Reached, reduce payload
+AAI_6148=5:4:INFO:6148:404:3001:Node Not Found. Start URI returned no vertexes, please check the start URI
+
+#--- aaicsvp: 7101-7199
+AAI_7101=5:4:ERROR:7101:500:3002:Unexpected error in CSV file processing
+AAI_7102=5:4:ERROR:7102:500:3002:Error in cleanup temporary directory
+#AAI_7103=4:2:ERROR:7103:500:3002:Unsupported user
+AAI_7104=5:4:ERROR:7104:500:3002:Failed to create directory
+AAI_7105=5:4:ERROR:7105:500:3002:Temporary directory exists
+AAI_7106=5:4:ERROR:7106:500:3002:Cannot delete
+AAI_7107=5:4:ERROR:7107:500:3002:Input file does not exist
+AAI_7108=5:4:ERROR:7108:500:3002:Output file does not exist
+AAI_7109=5:4:ERROR:7109:500:3002:Error closing file
+AAI_7110=5:4:ERROR:7110:500:3002:Error loading/reading properties file
+AAI_7111=5:4:ERROR:7111:500:3002:Error executing shell script
+AAI_7112=5:4:ERROR:7112:500:3002:Error creating output file
+AAI_7113=5:4:ERROR:7113:500:3002:Trailer record error
+AAI_7114=5:4:ERROR:7114:500:3002:Input file error
+AAI_7115=5:4:ERROR:7115:500:3002:Unexpected error
+AAI_7116=5:4:ERROR:7116:500:3002:Request error
+AAI_7117=5:4:ERROR:7117:500:3002:Error in get http client object
+AAI_7118=5:4:ERROR:7118:500:3002:Script Error
+AAI_7119=5:4:ERROR:7119:500:3002:Unknown host
+
+#--- aaisdnc: 7201-7299
+AAI_7202=5:4:ERROR:7202:500:3002:Error getting connection to odl
+AAI_7203=5:4:ERROR:7203:500:3002:Unexpected error calling DataChangeNotification API
+AAI_7204=5:4:ERROR:7204:500:3002:Error returned by DataChangeNotification API
+#AAI_7206=5:4:ERROR:7206:500:3002:Invalid data returned from ODL
+
+#--- NotificationEvent, using UEB space
+AAI_7350=5:4:ERROR:7305:500:3002:Notification event creation failed
+
+#--- aairestctlr: 7401-7499
+AAI_7401=5:4:ERROR:7401:500:3002:Error connecting to AAI REST API
+AAI_7402=5:4:ERROR:7402:500:3002:Unexpected error
+AAI_7403=5:4:WARN:7403:400:3001:Request error
+AAI_7404=5:4:INFO:7404:404:3001:Node not found
+AAI_7405=5:4:WARN:7405:200:0:UUID not formatted correctly, generating UUID
+AAI_7406=5:4:ERROR:7406:400:7406:Request Timed Out
+
+#--- aaicsiovals: 7501-7599
+#AAI_7501=5:4:WARN:7501:500:3002:Error getting connection to CSI-OVALS
+AAI_7502=5:4:WARN:7502:500:3002:Bad parameter when trying to build request for CSI-OVALS
+AAI_7503=5:4:WARN:7503:500:3002:Error returned by CSI-OVALS
+
+#--- aaiauth: 9101-9199
+AAI_9101=5:0:WARN:9101:403:3300:User is not authorized to perform function
+#AAI_9102=5:0:WARN:9102:401:3301:Refresh credentials from source
+#AAI_9103=5:0:WARN:9103:403:3300:User not found
+#AAI_9104=5:0:WARN:9104:401:3302:Authentication error
+#AAI_9105=5:0:WARN:9105:403:3300:Authorization error
+#AAI_9106=5:0:WARN:9106:403:3300:Invalid AppId
+#AAI_9107=5:0:WARN:9107:403:3300:No Username in Request
+AAI_9107=5:0:WARN:9107:403:3300:SSL is not provided in request, please contact admin
+AAI_9108=5:0:WARN:9107:403:3300:Basic auth credentials is not provided in the request
+
+#--- aaiinstar: 9201-9299
+#AAI_9201=5:4:ERROR:9201:500:3002:Unable to send notification
+AAI_9202=5:4:ERROR:9202:500:3002:Unable to start a thread
diff --git a/src/main/resources/etc/appprops/initialcachekeyconfig.json b/src/main/resources/etc/appprops/initialcachekeyconfig.json
new file mode 100644
index 0000000..f1fdabe
--- /dev/null
+++ b/src/main/resources/etc/appprops/initialcachekeyconfig.json
@@ -0,0 +1,41 @@
+{
+ "cachekeys":
+ [
+ {
+ "cacheKey": "cloud-region",
+ "baseUrl": "https://AAI:AAI@localhost:8447",
+ "module": "/aai/v13/",
+ "URI": "cloud-infrastructure/cloud-regions?depth=0&resultIndex=1&resultSize=3",
+ "timingIndicator": "onInit",
+ "httpMethod": "GET",
+ "parserStrategy": "aai-resource-get-all"
+ },
+ {
+ "cacheKey": "complex",
+ "baseUrl": "https://AAI:AAI@localhost:8447",
+ "module": "/aai/v13/",
+ "URI": "cloud-infrastructure/complexes?resultIndex=1&resultSize=3",
+ "timingIndicator": "onInit",
+ "httpMethod": "GET",
+ "parserStrategy": "aai-resource-get-all"
+ },
+ {
+ "cacheKey": "pserver",
+ "baseUrl": "https://AAI:AAI@localhost:8447",
+ "module": "/aai/v13/",
+ "URI": "cloud-infrastructure/pservers?depth=5807c3c3-92cd-44d7-a508-8539cd36ecda&resultIndex=1&resultSize=3",
+ "timingIndicator": "onInit",
+ "httpMethod": "GET",
+ "parserStrategy": "aai-resource-get-all"
+ },
+ {
+ "cacheKey": "generic-vnf",
+ "baseUrl": "https://AAI:AAI@localhost:8447",
+ "module": "/aai/v13/",
+ "URI": "network/generic-vnfs?depth=5807c3c3-92cd-44d7-a508-8539cd36ecda&resultIndex=1&resultSize=3",
+ "timingIndicator": "onInit",
+ "httpMethod": "GET",
+ "parserStrategy": "aai-resource-get-all"
+ }
+ ]
+} \ No newline at end of file
diff --git a/src/main/resources/etc/appprops/preferredRoute.txt b/src/main/resources/etc/appprops/preferredRoute.txt
new file mode 100644
index 0000000..a0290a1
--- /dev/null
+++ b/src/main/resources/etc/appprops/preferredRoute.txt
@@ -0,0 +1 @@
+MR1 \ No newline at end of file
diff --git a/src/main/resources/etc/auth/aai-client-cert.p12 b/src/main/resources/etc/auth/aai-client-cert.p12
new file mode 100644
index 0000000..292efb7
--- /dev/null
+++ b/src/main/resources/etc/auth/aai-client-cert.p12
Binary files differ
diff --git a/src/main/resources/etc/auth/aai_keystore b/src/main/resources/etc/auth/aai_keystore
new file mode 100644
index 0000000..16d93a7
--- /dev/null
+++ b/src/main/resources/etc/auth/aai_keystore
Binary files differ
diff --git a/src/main/resources/etc/auth/realm.properties b/src/main/resources/etc/auth/realm.properties
new file mode 100644
index 0000000..fb692cc
--- /dev/null
+++ b/src/main/resources/etc/auth/realm.properties
@@ -0,0 +1,12 @@
+# format : username: password[,rolename ...]
+# default username/password: AAI/AAI, MSO/MSO, ModelLoader/ModelLoader...
+AAI:OBF:1gfr1ev31gg7,admin
+MSO:OBF:1jzx1lz31k01,admin
+SDNC:OBF:1itr1i0l1i151isv,admin
+DCAE:OBF:1g8u1f9d1f991g8w,admin
+POLICY:OBF:1mk61i171ima1im41i0j1mko,admin
+ASDC:OBF:1f991j0u1j001f9d,admin
+VID:OBF:1jm91i0v1jl9,admin
+APPC:OBF:1f991ksf1ksf1f9d,admin
+ModelLoader:OBF:1qvu1v2h1sov1sar1wfw1j7j1wg21saj1sov1v1x1qxw,admin
+AaiUI:OBF:1gfr1p571unz1p4j1gg7,admin
diff --git a/src/main/resources/localhost-access-logback.xml b/src/main/resources/localhost-access-logback.xml
new file mode 100644
index 0000000..a318796
--- /dev/null
+++ b/src/main/resources/localhost-access-logback.xml
@@ -0,0 +1,62 @@
+<!--
+
+ ============LICENSE_START=======================================================
+ org.onap.aai
+ ================================================================================
+ Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+
+ ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+-->
+<configuration>
+ <property name="AJSC_HOME" value="${AJSC_HOME:-.}" />
+ <appender name="ACCESS"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${AJSC_HOME}/logs/ajsc-jetty/localhost_access.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${AJSC_HOME}/logs/ajsc-jetty/localhost_access.log.%d{yyyy-MM-dd}
+ </fileNamePattern>
+ </rollingPolicy>
+ <encoder class="org.onap.aai.logging.CustomLogPatternLayoutEncoder">
+ <Pattern>%a %u %z [%t] "%m %U%q" %s %b %y %i{X-TransactionId} %i{X-FromAppId} %i{X-Forwarded-For} %i{X-AAI-SSL-Client-CN} %i{X-AAI-SSL-Client-OU} %i{X-AAI-SSL-Client-O} %i{X-AAI-SSL-Client-L} %i{X-AAI-SSL-Client-ST} %i{X-AAI-SSL-Client-C} %i{X-AAI-SSL-Client-NotBefore} %i{X-AAI-SSL-Client-NotAfter} %i{X-AAI-SSL-Client-DN} %D</Pattern>
+ </encoder>
+ </appender>
+ <appender-ref ref="ACCESS" />
+</configuration>
+
+<!--
+%a - Remote IP address
+%A - Local IP address
+%b - Bytes sent, excluding HTTP headers, or '-' if no bytes were sent
+%B - Bytes sent, excluding HTTP headers
+%h - Remote host name
+%H - Request protocol
+%l - Remote logical username from identd (always returns '-')
+%m - Request method
+%p - Local port
+%q - Query string (prepended with a '?' if it exists, otherwise an empty string
+%r - First line of the request
+%s - HTTP status code of the response
+%S - User session ID
+%t - Date and time, in Common Log Format format
+%u - Remote user that was authenticated
+%U - Requested URL path
+%v - Local server name
+%I - current request thread name (can compare later with stacktraces)
+
+%z - Custom pattern that parses the cert for the subject
+%y - Custom pattern determines rest or dme2
+ --> \ No newline at end of file
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000..9caabe6
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,243 @@
+<!--
+
+ ============LICENSE_START=======================================================
+ org.onap.aai
+ ================================================================================
+ Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+
+ ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+-->
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
+ <statusListener class="ch.qos.logback.core.status.NopStatusListener" />
+
+ <property resource="application.properties" />
+
+ <property name="namespace" value="aai-cacher"/>
+
+ <property name="AJSC_HOME" value="${AJSC_HOME:-.}" />
+ <jmxConfigurator />
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+ <property name="eelfLogPattern" value="%ecompStartTime|%date{yyyy-MM-dd'T'HH:mm:ss.SSSZ, UTC}|%X{requestId}|%X{serviceInstanceId}|%-10t|%X{serverName}|%X{serviceName}|%X{partnerName}|%ecompStatusCode|%X{responseCode}|%replace(%replace(%X{responseDescription}){'\\|', '!'}){'\r|\n', '^'}|%X{instanceUUID}|%level|%X{severity}|%X{serverIpAddress}|%ecompElapsedTime|%X{server}|%X{clientIpAddress}|%eelfClassOfCaller|%X{unused}|%X{processKey}|%X{customField1}|%X{customField2}|%X{customField3}|%X{customField4}|co=%X{component}:%replace(%replace(%m){'\\|', '!'}){'\r|\n', '^'}%n"/>
+ <property name="eelfMetricLogPattern" value="%ecompStartTime|%date{yyyy-MM-dd'T'HH:mm:ss.SSSZ, UTC}|%X{requestId}|%X{serviceInstanceId}|%-10t|%X{serverName}|%X{serviceName}|%X{partnerName}|%X{targetEntity}|%X{targetServiceName}|%ecompStatusCode|%X{responseCode}|%replace(%replace(%X{responseDescription}){'\\|', '!'}){'\r|\n', '^'}|%X{instanceUUID}|%level|%X{severity}|%X{serverIpAddress}|%ecompElapsedTime|%X{server}|%X{clientIpAddress}|%eelfClassOfCaller|%X{unused}|%X{processKey}|%X{targetVirtualEntity}|%X{customField1}|%X{customField2}|%X{customField3}|%X{customField4}|co=%X{component}:%replace(%replace(%m){'\\|', '!'}){'\r|\n', '^'}%n"/>
+ <!-- <property name="eelfErrorLogPattern" value="%ecompStartTime|%X{requestId}|%-10t|%X{serviceName}|%X{partnerName}|%X{targetEntity}|%X{targetServiceName}|%ecompErrorCategory|%X{responseCode}|%replace(%replace(%X{responseDescription}){'\\|', '!'}){'\r|\n|\r\n', '^'}|co=%X{component}:%replace(%replace(%m){'\\|', '!'}){'\r|\n', '^'}%n"/> -->
+ <property name="eelfErrorLogPattern" value="%ecompStartTime|%X{requestId}|%-10t|%X{serviceName}|%X{partnerName}|%X{targetEntity}|%X{targetServiceName}|%ecompErrorCategory|%ecompResponseCode|%ecompResponseDescription|co=%X{component}:%replace(%replace(%m){'\\|', '!'}){'\r|\n', '^'}%n"/>
+ <property name="eelfTransLogPattern" value="%ecompStartTime|%date{yyyy-MM-dd'T'HH:mm:ss.SSSZ, UTC}|%X{requestId}|%X{serviceInstanceId}|%-10t|%X{serverName}|%X{serviceName}|%X{partnerName}|%ecompStatusCode|%X{responseCode}|%replace(%replace(%X{responseDescription}){'\\|', '!'}){'\r|\n', '^'}|%X{instanceUUID}|%level|%X{severity}|%X{serverIpAddress}|%ecompElapsedTime|%X{server}|%X{clientIpAddress}|%eelfClassOfCaller|%X{unused}|%X{processKey}|%X{customField1}|%X{customField2}|%X{customField3}|%X{customField4}|co=%X{partnerName}:%m%n"/>
+
+ <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
+ <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
+ <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>
+ %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
+ </pattern>
+ </encoder>
+ </appender>
+
+ <appender name="SANE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/rest/sane.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/sane.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n
+ </pattern>
+ </encoder>
+ </appender>
+
+ <appender name="asyncSANE" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <includeCallerData>true</includeCallerData>
+ <appender-ref ref="SANE" />
+ </appender>
+
+ <appender name="METRIC"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <file>${logDirectory}/rest/metrics.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/metrics.log.%d{yyyy-MM-dd}
+ </fileNamePattern>
+ </rollingPolicy>
+ <encoder class="org.onap.aai.logging.EcompEncoder">
+ <pattern>${eelfMetricLogPattern}</pattern>
+ </encoder>
+ </appender>
+ <appender name="asyncMETRIC" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <includeCallerData>true</includeCallerData>
+ <appender-ref ref="METRIC" />
+ </appender>
+
+ <appender name="DEBUG"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <file>${logDirectory}/rest/debug.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/debug.log.%d{yyyy-MM-dd}
+ </fileNamePattern>
+ </rollingPolicy>
+ <encoder class="org.onap.aai.logging.EcompEncoder">
+ <pattern>${eelfLogPattern}</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="asyncDEBUG" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <includeCallerData>true</includeCallerData>
+ <appender-ref ref="DEBUG" />
+ </appender>
+
+ <appender name="ERROR"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <file>${logDirectory}/rest/error.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/error.log.%d{yyyy-MM-dd}
+ </fileNamePattern>
+ </rollingPolicy>
+ <encoder class="org.onap.aai.logging.EcompEncoder">
+ <pattern>${eelfErrorLogPattern}</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="asyncERROR" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <includeCallerData>true</includeCallerData>
+ <appender-ref ref="ERROR" />
+ </appender>
+
+
+
+ <appender name="translog"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <file>${logDirectory}/rest/translog.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/translog.log.%d{yyyy-MM-dd}
+ </fileNamePattern>
+ </rollingPolicy>
+ <encoder class="org.onap.aai.logging.EcompEncoder">
+ <pattern>${eelfTransLogPattern}</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="asynctranslog" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <includeCallerData>true</includeCallerData>
+ <appender-ref ref="translog" />
+ </appender>
+
+ <appender name="external"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <file>${logDirectory}/external/external.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/external/external.log.%d{yyyy-MM-dd}
+ </fileNamePattern>
+ </rollingPolicy>
+ <encoder class="org.onap.aai.logging.EcompEncoder">
+ <pattern>${eelfLogPattern}</pattern>
+ </encoder>
+ </appender>
+ <logger name="org.onap.aai.cacher" level="DEBUG" additivity="false">
+ <appender-ref ref="asyncDEBUG" />
+ <appender-ref ref="asyncERROR" />
+ <appender-ref ref="asyncMETRIC" />
+ <appender-ref ref="asyncSANE" />
+ </logger>
+
+ <!-- Spring related loggers -->
+ <logger name="org.springframework" level="WARN" />
+ <logger name="org.springframework.beans" level="WARN" />
+ <logger name="org.springframework.web" level="WARN" />
+ <logger name="com.blog.spring.jms" level="WARN" />
+ <logger name="com.jayway.jsonpath" level="WARN" />
+
+ <logger name="com.netflix.loadbalancer" level="WARN" />
+
+ <logger name="org.apache.zookeeper" level="OFF" />
+
+ <!-- Other Loggers that may help troubleshoot -->
+ <logger name="net.sf" level="WARN" />
+ <logger name="org.apache.commons.httpclient" level="WARN" />
+ <logger name="org.apache.commons" level="WARN" />
+ <logger name="org.apache.coyote" level="WARN" />
+ <logger name="org.apache.jasper" level="WARN" />
+
+ <!-- Camel Related Loggers (including restlet/servlet/jaxrs/cxf logging.
+ May aid in troubleshooting) -->
+ <logger name="org.apache.camel" level="WARN" />
+ <logger name="org.apache.cxf" level="WARN" />
+ <logger name="org.apache.camel.processor.interceptor" level="WARN" />
+ <logger name="org.apache.cxf.jaxrs.interceptor" level="WARN" />
+ <logger name="org.apache.cxf.service" level="WARN" />
+ <logger name="org.restlet" level="WARN" />
+ <logger name="org.apache.camel.component.restlet" level="WARN" />
+
+ <logger name="org.hibernate.validator" level="WARN" />
+ <logger name="org.hibernate" level="WARN" />
+ <logger name="org.hibernate.ejb" level="OFF" />
+
+ <!-- logback internals logging -->
+ <logger name="ch.qos.logback.classic" level="WARN" />
+ <logger name="ch.qos.logback.core" level="WARN" />
+
+ <logger name="org.eclipse.jetty" level="WARN" />
+
+
+ <!-- logback jms appenders & loggers definition ends here -->
+
+ <logger name="org.onap.aai.interceptors.post" level="DEBUG"
+ additivity="false">
+ <appender-ref ref="asynctranslog" />
+ </logger>
+
+ <logger name="org.apache" level="OFF" />
+ <logger name="org.zookeeper" level="OFF" />
+ <logger name="org.janusgraph" level="WARN" />
+ <logger name="com.att.aft.dme2" level="WARN" />
+
+ <!-- ============================================================================ -->
+ <!-- General EELF logger -->
+ <!-- ============================================================================ -->
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="asyncDEBUG" />
+ <appender-ref ref="asyncERROR" />
+ <appender-ref ref="asyncMETRIC" />
+ </logger>
+
+ <root level="DEBUG">
+ <appender-ref ref="external" />
+ </root>
+</configuration>
diff --git a/src/test/java/org/onap/aai/cacher/common/MongoHelperSingletonNoFakeTest.java b/src/test/java/org/onap/aai/cacher/common/MongoHelperSingletonNoFakeTest.java
new file mode 100644
index 0000000..1a086bc
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/common/MongoHelperSingletonNoFakeTest.java
@@ -0,0 +1,490 @@
+/**
+ * ============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.cacher.common;
+
+import com.google.gson.JsonParser;
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.UpdateOptions;
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodProcess;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.IMongodConfig;
+import de.flapdoodle.embed.mongo.config.MongoCmdOptionsBuilder;
+import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Net;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.process.runtime.Network;
+import org.bson.Document;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.*;
+import org.onap.aai.cacher.dmaap.consumer.AAIDmaapEventProcessorScenariosTest;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.cacher.model.DBAction;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+
+public class MongoHelperSingletonNoFakeTest {
+
+ private static final String DB_NAME = AAIDmaapEventProcessorScenariosTest.class.getSimpleName();
+ private static MongoDatabase mongoDatabase;
+ private static DB db;
+ private static MongodProcess mongod;
+ private static MongoClient mongoC;
+
+ private MongoHelperSingleton mongoHelperSingleton;
+ private JsonParser parser = new JsonParser();
+
+
+ @BeforeClass
+ public static void setup() throws IOException, InterruptedException {
+
+ String bindIp = "localhost";
+ int port = 27017;
+ startEmbedded(port);
+
+ mongoC = new MongoClient(bindIp, port);
+ mongoDatabase = mongoC.getDatabase(DB_NAME);
+ db = mongoC.getDB(DB_NAME);
+
+ }
+
+ protected static void startEmbedded(int port) throws IOException {
+ IMongodConfig mongoConfigConfig = new MongodConfigBuilder()
+ .version(Version.Main.PRODUCTION)
+ .net(new Net(port, Network.localhostIsIPv6()))
+ .cmdOptions(new MongoCmdOptionsBuilder().verbose(true).build())
+ .configServer(false)
+ .build();
+
+ MongodExecutable mongodExecutable = MongodStarter.getDefaultInstance().prepare(mongoConfigConfig);
+
+ mongod = mongodExecutable.start();
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ if (mongod != null && mongod.isProcessRunning()) {
+ mongod.stop();
+ }
+ }
+
+ @Before
+ public void init() {
+ mongoHelperSingleton = new MongoHelperSingleton(db, mongoDatabase);
+ }
+
+ @After
+ public void cleanup() {
+ final List<String> collectionNames = new ArrayList<>();
+ mongoDatabase.listCollections().iterator().forEachRemaining(document -> collectionNames.add(document.getString("name")));
+ collectionNames.stream().forEach(collectionName -> mongoDatabase.getCollection(collectionName).drop());
+ }
+
+
+ private MongoCollection<Document> setupCollection(String collectionName) {
+
+ mongoDatabase.createCollection(collectionName);
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(collectionName);
+
+ Document findQuery = Document.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'}");
+ Document obj = Document.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1','hostname':'testPserver_1'," +
+ "'p-interfaces':{'p-interface':[" +
+ "{'interface-name':'interface-1','l-interfaces':{'l-interface':[{'interface-name':'l-interface-1','test':'test'}]}}," +
+ "{'interface-name':'interface-2'}" +
+ "]}}");
+ collection.replaceOne(findQuery, obj, new UpdateOptions().upsert(true));
+
+
+ findQuery = Document.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2'}");
+ obj = Document.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2','hostname':'testPserver_2'," +
+ "'p-interfaces':{'p-interface':[" +
+ "{'interface-name':'interface-1','l-interfaces':{'l-interface':[{'interface-name':'l-interface-1'}]}}," +
+ "{'interface-name':'interface-2'}" +
+ "]}}");
+ collection.replaceOne(findQuery, obj, new UpdateOptions().upsert(true));
+
+ findQuery = Document.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_99'}");
+ obj = Document.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_99','hostname':'testPserver_99'," +
+ "'p-interfaces':{'p-interface':[" +
+ "{'interface-name':'interface-1','l-interfaces':{'l-interface':[{'interface-name':'l-interface-1','l3-interface-ipv4-address-list':[{'l3-interface-ipv4-address':'address'}]}]}}," +
+ "{'interface-name':'interface-2'}" +
+ "]}}");
+ collection.replaceOne(findQuery, obj, new UpdateOptions().upsert(true));
+
+ assertEquals("Pre " + collectionName + " test: collection contains 3 documents", 3L, collection.count());
+
+ return collection;
+ }
+
+ @Test
+ public void getNestedObjectAddressList() throws JSONException {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_99'," +
+ "'hostname':'testPserver_99'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.interface-name':'l-interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.l3-interface-ipv4-address-list.l3-interface-ipv4-address':'address'}";
+ CacheEntry ce = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .isNested(true)
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject()).build();
+
+ Optional<Document> nested = mongoHelperSingleton.getObject(ce);
+
+ assertTrue(nested.isPresent());
+
+ JSONAssert.assertEquals(
+ new JSONObject("{'l3-interface-ipv4-address':'address'}"),
+ new JSONObject(nested.get().toJson()),
+ true);
+
+
+ }
+
+ @Test
+ public void getNestedObject() throws JSONException {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_99'," +
+ "'hostname':'testPserver_99'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.interface-name':'l-interface-1'}";
+ CacheEntry ce = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .isNested(true)
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject()).build();
+
+ Optional<Document> nested = mongoHelperSingleton.getObject(ce);
+
+ assertTrue(nested.isPresent());
+ JSONAssert.assertEquals(
+ new JSONObject("{'interface-name':'l-interface-1','l3-interface-ipv4-address-list':[{'l3-interface-ipv4-address':'address'}]}"),
+ new JSONObject(nested.get().toJson()),
+ true);
+
+ }
+
+ @Test
+ public void insertNewTop() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.INSERT_REPLACE)
+ .isNested(false)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_3")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_3'}").getAsJsonObject())
+ .withPayload(parser.parse("{'hostname':'testPserver_1'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.insertReplace(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 4 document", 4L, collection.count());
+
+ }
+
+ @Test
+ public void insertNewNested() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.interface-name':'interface-NEW'}";
+ Document nestedFind = Document.parse(nestedFindString);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.INSERT_REPLACE)
+ .isNested(true)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_1")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'}").getAsJsonObject())
+ .withPayload(parser.parse("{'interface-name':'interface-NEW'}").getAsJsonObject())
+ .withNestedField("p-interfaces.p-interface")
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject())
+ .withNestedFieldIdentifierObj(parser.parse("{'interface-name':'interface-NEW'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.insertReplace(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 1 document with new nested", 1L, collection.count(nestedFind));
+
+ }
+
+ @Test
+ public void insertNewTwoNested() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.interface-name':'l-interface-NEW'}";
+ Document nestedFind = Document.parse(nestedFindString);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.INSERT_REPLACE)
+ .isNested(true)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_1")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'}").getAsJsonObject())
+ .withPayload(parser.parse("{'interface-name':'l-interface-NEW','new-field':'NEW'}").getAsJsonObject())
+ .withNestedField("p-interfaces.p-interface.$.l-interfaces.l-interface")
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject())
+ .withNestedFieldIdentifierObj(parser.parse("{'interface-name':'l-interface-NEW'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.insertReplace(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 1 document with new nested", 1L, collection.count(nestedFind));
+
+ }
+
+ @Test
+ public void insertNewThreeNested() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.interface-name':'l-interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.vlans.vlan.vlan-interface':'vlan-NEW'}";
+ Document nestedFind = Document.parse(nestedFindString);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.INSERT_REPLACE)
+ .isNested(true)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_1")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.interface-name':'l-interface-1'}").getAsJsonObject())
+ .withPayload(parser.parse("{'vlan-interface':'vlan-NEW','new-field':'NEW4'}").getAsJsonObject())
+ .withNestedField("p-interfaces.p-interface.$.l-interfaces.l-interface.$.vlans.vlan")
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject())
+ .withNestedFieldIdentifierObj(parser.parse("{'vlan-interface':'vlan-NEW'}").getAsJsonObject())
+ .build();
+ assertTrue(mongoHelperSingleton.insertReplace(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 1 document with new nested", 1L, collection.count(nestedFind));
+
+ }
+
+
+ @Test
+ public void insertExstingNested() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'}";
+ Document nestedFind = Document.parse(nestedFindString);
+
+ String newNestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.new-field':'NEW'}";
+ Document newNestedFind = Document.parse(newNestedFindString);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.INSERT_REPLACE)
+ .isNested(true)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_1")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'}").getAsJsonObject())
+ .withPayload(parser.parse("{'interface-name':'interface-1','new-field':'NEW'}").getAsJsonObject())
+ .withNestedField("p-interfaces.p-interface")
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject())
+ .withNestedFieldIdentifierObj(parser.parse("{'interface-name':'interface-1'}").getAsJsonObject())
+ .build();
+
+ assertEquals("Pre " + collectionName + " test: collection contains 1 document with new nested", 1L, collection.count(nestedFind));
+ assertTrue(mongoHelperSingleton.insertReplace(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 1 document with new nested", 1L, collection.count(nestedFind));
+ assertEquals("Post " + collectionName + " test: collection contains 1 document with new nested property", 1L, collection.count(newNestedFind));
+
+ }
+
+ @Test
+ public void replaceTop() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.INSERT_REPLACE)
+ .isNested(false)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_2")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2'}").getAsJsonObject())
+ .withPayload(parser.parse("{'hostname':'testPserver_2','new-property':'NEW'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.insertReplace(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 3 document", 3L, collection.count());
+ assertEquals("Post " + collectionName + " test: collection contains 1 document with new property",
+ 1L,
+ collection.count(Document.parse("{'new-property':'NEW'}")));
+
+
+ }
+
+ @Test
+ public void deleteTopLevel() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.DELETE)
+ .isNested(false)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_2")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.delete(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 2 document", 2L, collection.count());
+
+ }
+
+ @Test
+ public void deleteNestedOneLevel() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'}";
+ Document nestedFind = Document.parse(nestedFindString);
+
+ assertEquals("Pre " + collectionName + " test: collection contains 1 document with filter",
+ 1L,
+ collection.count(nestedFind));
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.DELETE)
+ .isNested(true)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_2")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2'}").getAsJsonObject())
+ .withNestedField("p-interfaces.p-interface")
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject())
+ .withNestedFieldIdentifierObj(parser.parse("{'interface-name':'interface-1'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.delete(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 0 document",
+ 0L,
+ collection.count(nestedFind));
+
+ }
+
+ @Test
+ public void deleteNestedTwoLevel() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.interface-name':'l-interface-1'}";
+ Document nestedFind = Document.parse(nestedFindString);
+
+ assertEquals("Pre " + collectionName + " test: collection contains 1 document with filter",
+ 1L,
+ collection.count(nestedFind));
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.DELETE)
+ .isNested(true)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_2")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'}").getAsJsonObject())
+ .withNestedField("p-interfaces.p-interface.$.l-interfaces.l-interface")
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject())
+ .withNestedFieldIdentifierObj(parser.parse("{'interface-name':'l-interface-1'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.delete(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 0 document",
+ 0L,
+ collection.count(nestedFind));
+
+
+ }
+
+ //TODO delete non existent top
+
+
+} \ No newline at end of file
diff --git a/src/test/java/org/onap/aai/cacher/common/MongoHelperSingletonTest.java b/src/test/java/org/onap/aai/cacher/common/MongoHelperSingletonTest.java
new file mode 100644
index 0000000..872f099
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/common/MongoHelperSingletonTest.java
@@ -0,0 +1,417 @@
+/**
+ * ============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.cacher.common;
+
+import com.github.fakemongo.Fongo;
+import com.google.gson.JsonParser;
+import com.mongodb.DB;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.UpdateOptions;
+import org.bson.Document;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.onap.aai.cacher.model.DBAction;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class MongoHelperSingletonTest {
+
+ private static final String DB_NAME = "testDb";
+ private static MongoDatabase mongoDatabase;
+ private static DB db;
+ private MongoHelperSingleton mongoHelperSingleton;
+ private JsonParser parser = new JsonParser();
+
+
+ @BeforeClass
+ public static void setup() {
+ Fongo fongo = new Fongo(DB_NAME);
+ mongoDatabase = fongo.getDatabase(DB_NAME);
+ db = fongo.getDB(DB_NAME);
+ }
+
+ @Before
+ public void init() {
+ mongoHelperSingleton = new MongoHelperSingleton(db, mongoDatabase);
+ }
+
+ @After
+ public void cleanup() {
+ final List<String> collectionNames = new ArrayList<>();
+ mongoDatabase.listCollections().iterator().forEachRemaining(document -> collectionNames.add(document.getString("name")));
+ collectionNames.stream().forEach(collectionName -> mongoDatabase.getCollection(collectionName).drop());
+ }
+
+ private MongoCollection<Document> setupCollection(String collectionName) {
+
+ mongoDatabase.createCollection(collectionName);
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(collectionName);
+
+ Document findQuery = Document.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'}");
+ Document obj = Document.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1','hostname':'testPserver_1'," +
+ "'p-interfaces':{'p-interface':[" +
+ "{'interface-name':'interface-1','l-interfaces':{'l-interface':[{'interface-name':'l-interface-1','test':'test'}]}}," +
+ "{'interface-name':'interface-2'}" +
+ "]}}");
+ collection.replaceOne(findQuery, obj, new UpdateOptions().upsert(true));
+
+
+ findQuery = Document.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2'}");
+ obj = Document.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2','hostname':'testPserver_2'," +
+ "'p-interfaces':{'p-interface':[" +
+ "{'interface-name':'interface-1','l-interfaces':{'l-interface':[{'interface-name':'l-interface-1'}]}}," +
+ "{'interface-name':'interface-2'}" +
+ "]}}");
+ collection.replaceOne(findQuery, obj, new UpdateOptions().upsert(true));
+
+ findQuery = Document.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_99'}");
+ obj = Document.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_99','hostname':'testPserver_99'," +
+ "'p-interfaces':{'p-interface':[" +
+ "{'interface-name':'interface-1','l-interfaces':{'l-interface':[{'interface-name':'l-interface-1','l3-interface-ipv4-address-list':[{'l3-interface-ipv4-address':'address'}]}]}}," +
+ "{'interface-name':'interface-2'}" +
+ "]}}");
+ collection.replaceOne(findQuery, obj, new UpdateOptions().upsert(true));
+
+ assertEquals("Pre " + collectionName + " test: collection contains 3 documents", 3L, collection.count());
+
+ return collection;
+ }
+
+ @Test
+ public void getNestedObjectAddressList() throws JSONException {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+ setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_99'," +
+ "'hostname':'testPserver_99'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.interface-name':'l-interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.l3-interface-ipv4-address-list.l3-interface-ipv4-address':'address'}";
+ CacheEntry ce = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .isNested(true)
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject()).build();
+
+ Optional<Document> nested = mongoHelperSingleton.getObject(ce);
+
+ assertTrue(nested.isPresent());
+
+ JSONAssert.assertEquals(
+ new JSONObject("{'l3-interface-ipv4-address':'address'}"),
+ new JSONObject(nested.get().toJson()),
+ true);
+
+
+ }
+
+ @Test
+ public void getNestedObject() throws JSONException {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+ setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_99'," +
+ "'hostname':'testPserver_99'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.interface-name':'l-interface-1'}";
+ CacheEntry ce = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .isNested(true)
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject()).build();
+
+ Optional<Document> nested = mongoHelperSingleton.getObject(ce);
+
+ assertTrue(nested.isPresent());
+ JSONAssert.assertEquals(
+ new JSONObject("{'interface-name':'l-interface-1','l3-interface-ipv4-address-list':[{'l3-interface-ipv4-address':'address'}]}"),
+ new JSONObject(nested.get().toJson()),
+ true);
+ }
+
+ @Test
+ public void insertNewTop() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+ setupCollection(collectionName);
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.INSERT_REPLACE)
+ .isNested(false)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_3")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_3'}").getAsJsonObject())
+ .withPayload(parser.parse("{'hostname':'testPserver_1'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.insertReplace(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 4 document", 4L, collection.count());
+
+ }
+
+ @Test
+ public void insertNewNested() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+ setupCollection(collectionName);
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.interface-name':'interface-NEW'}";
+ Document nestedFind = Document.parse(nestedFindString);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.INSERT_REPLACE)
+ .isNested(true)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_1")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'}").getAsJsonObject())
+ .withPayload(parser.parse("{'interface-name':'interface-NEW'}").getAsJsonObject())
+ .withNestedField("p-interfaces.p-interface")
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject())
+ .withNestedFieldIdentifierObj(parser.parse("{'interface-name':'interface-NEW'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.insertReplace(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 1 document with new nested", 1L, collection.count(nestedFind));
+
+ }
+
+ @Test
+ public void insertNewTwoNested() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+ setupCollection(collectionName);
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.interface-name':'l-interface-NEW'}";
+ Document nestedFind = Document.parse(nestedFindString);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.INSERT_REPLACE)
+ .isNested(true)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_1")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'}").getAsJsonObject())
+ .withPayload(parser.parse("{'interface-name':'l-interface-NEW','new-field':'NEW'}").getAsJsonObject())
+ .withNestedField("p-interfaces.p-interface.$.l-interfaces.l-interface")
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject())
+ .withNestedFieldIdentifierObj(parser.parse("{'interface-name':'l-interface-NEW'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.insertReplace(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 1 document with new nested", 1L, collection.count(nestedFind));
+
+ }
+
+
+ @Test
+ public void insertExstingNested() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+ setupCollection(collectionName);
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'}";
+ Document nestedFind = Document.parse(nestedFindString);
+
+ String newNestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.new-field':'NEW'}";
+ Document newNestedFind = Document.parse(newNestedFindString);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.INSERT_REPLACE)
+ .isNested(true)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_1")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'}").getAsJsonObject())
+ .withPayload(parser.parse("{'interface-name':'interface-1','new-field':'NEW'}").getAsJsonObject())
+ .withNestedField("p-interfaces.p-interface")
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject())
+ .withNestedFieldIdentifierObj(parser.parse("{'interface-name':'interface-1'}").getAsJsonObject())
+ .build();
+
+ assertEquals("Pre " + collectionName + " test: collection contains 1 document with new nested", 1L, collection.count(nestedFind));
+ assertTrue(mongoHelperSingleton.insertReplace(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 1 document with new nested", 1L, collection.count(nestedFind));
+ assertEquals("Post " + collectionName + " test: collection contains 1 document with new nested property", 1L, collection.count(newNestedFind));
+
+ }
+
+ @Test
+ public void replaceTop() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+ setupCollection(collectionName);
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.INSERT_REPLACE)
+ .isNested(false)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_2")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2'}").getAsJsonObject())
+ .withPayload(parser.parse("{'hostname':'testPserver_2','new-property':'NEW'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.insertReplace(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 3 document", 3L, collection.count());
+ assertEquals("Post " + collectionName + " test: collection contains 1 document with new property",
+ 1L,
+ collection.count(Document.parse("{'new-property':'NEW'}")));
+
+
+ }
+
+ @Test
+ public void deleteTopLevel() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.DELETE)
+ .isNested(false)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_2")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.delete(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 2 document", 2L, collection.count());
+
+ }
+
+ @Test
+ public void deleteNestedOneLevel() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'}";
+ Document nestedFind = Document.parse(nestedFindString);
+
+ assertEquals("Pre " + collectionName + " test: collection contains 1 document with filter",
+ 1L,
+ collection.count(nestedFind));
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.DELETE)
+ .isNested(true)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_2")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2'}").getAsJsonObject())
+ .withNestedField("p-interfaces.p-interface")
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject())
+ .withNestedFieldIdentifierObj(parser.parse("{'interface-name':'interface-1'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.delete(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 0 document",
+ 0L,
+ collection.count(nestedFind));
+
+ }
+
+ @Test
+ public void deleteNestedTwoLevel() throws Exception {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ MongoCollection<Document> collection = setupCollection(collectionName);
+
+ String nestedFindString = "{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_1'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.interface-name':'l-interface-1'}";
+ Document nestedFind = Document.parse(nestedFindString);
+
+ assertEquals("Pre " + collectionName + " test: collection contains 1 document with filter",
+ 1L,
+ collection.count(nestedFind));
+
+ CacheEntry cacheEntry = CacheEntry.CacheEntryBuilder.createCacheEntry()
+ .inCollection(collectionName)
+ .withDbAction(DBAction.DELETE)
+ .isNested(true)
+ .withId("/cloud-infrastructure/pservers/pserver/testPserver_2")
+ .withFindQuery(parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/testPserver_2'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'}").getAsJsonObject())
+ .withNestedField("p-interfaces.p-interface.$.l-interfaces.l-interface")
+ .withNestedFind(parser.parse(nestedFindString).getAsJsonObject())
+ .withNestedFieldIdentifierObj(parser.parse("{'interface-name':'l-interface-1'}").getAsJsonObject())
+ .build();
+
+ assertTrue(mongoHelperSingleton.delete(cacheEntry));
+ assertEquals("Post " + collectionName + " test: collection contains 0 document",
+ 0L,
+ collection.count(nestedFind));
+
+ }
+
+ //TODO delete non existent top
+
+
+} \ No newline at end of file
diff --git a/src/test/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessorScenariosTest.java b/src/test/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessorScenariosTest.java
new file mode 100644
index 0000000..2c01f5a
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessorScenariosTest.java
@@ -0,0 +1,496 @@
+/**
+ * ============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.cacher.dmaap.consumer;
+
+import com.google.gson.JsonParser;
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoDatabase;
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodProcess;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.IMongodConfig;
+import de.flapdoodle.embed.mongo.config.MongoCmdOptionsBuilder;
+import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Net;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.process.runtime.Network;
+import org.apache.commons.io.IOUtils;
+import org.bson.Document;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.aai.cacher.common.MongoHelperSingleton;
+import org.onap.aai.cacher.injestion.parser.InjestionTestComponent;
+import org.onap.aai.cacher.injestion.parser.PayloadParserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.TestCase.assertFalse;
+import static org.junit.Assert.*;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@Configuration
+@ContextConfiguration(classes = {InjestionTestComponent.class, AAIDmaapEventProcessorScenariosTest.class})
+public class AAIDmaapEventProcessorScenariosTest {
+
+ private static final String DB_NAME = AAIDmaapEventProcessorScenariosTest.class.getSimpleName();
+ private static MongoDatabase mongoDb;
+ private static DB db;
+ private static MongodProcess mongod;
+ private static MongoClient mongoC;
+
+ private JsonParser parser = new JsonParser();
+
+ @Autowired
+ private AAIDmaapEventProcessor aaiDmaapEventProcessor;
+
+ @Bean
+ public DB db() {
+ return db;
+ }
+
+ @Bean
+ public MongoDatabase mongoDatabase() {
+ return mongoDb;
+ }
+
+ @Bean
+ public MongoHelperSingleton mongoHelperSingleton(DB db, MongoDatabase mongoDb) {
+ return new MongoHelperSingleton(db, mongoDb);
+ }
+
+ @Bean
+ public AAIDmaapEventProcessor aaiDmaapEventProcessor(MongoHelperSingleton mongoHelperSingleton, PayloadParserService payloadParserService) {
+ return new AAIDmaapEventProcessor(mongoHelperSingleton, payloadParserService);
+ }
+
+ @BeforeClass
+ public static void setup() throws IOException, InterruptedException {
+
+ String bindIp = "localhost";
+ int port = 27017;
+ startEmbedded(port);
+
+ mongoC = new MongoClient(bindIp, port);
+ mongoDb = mongoC.getDatabase(DB_NAME);
+ db = mongoC.getDB(DB_NAME);
+
+ }
+
+ protected static void startEmbedded(int port) throws IOException {
+ IMongodConfig mongoConfigConfig = new MongodConfigBuilder()
+ .version(Version.Main.PRODUCTION)
+ .net(new Net(port, Network.localhostIsIPv6()))
+ .cmdOptions(new MongoCmdOptionsBuilder().verbose(true).build())
+ .configServer(false)
+ .build();
+
+ MongodExecutable mongodExecutable = MongodStarter.getDefaultInstance().prepare(mongoConfigConfig);
+
+ mongod = mongodExecutable.start();
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ if (mongod != null && mongod.isProcessRunning()) {
+ mongod.stop();
+ }
+ }
+
+ @After
+ public void cleanup() {
+ final List<String> collectionNames = new ArrayList<>();
+ mongoDb.listCollections().iterator().forEachRemaining(document -> collectionNames.add(document.getString("name")));
+ collectionNames.forEach(collectionName -> mongoDb.getCollection(collectionName).drop());
+ }
+
+
+ @Test
+ public void createPserverCreateCRWithNestingAndRelationshipsToTest() throws Exception {
+ String pserverCreate = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'pserver','top-entity-type':'pserver','entity-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','event-type':'AAI-EVENT','domain':'JUNIT','action':'CREATE','sequence-number':'0','id':'0c3b336d-6554-4ddf-a4d7-90f97876a966','source-name':'JUNIT','version':'v13','timestamp':'20180209-21:02:20:344'},'entity':{'hostname':'pserver-1','in-maint':false}}";
+
+ aaiDmaapEventProcessor.process(pserverCreate);
+ assertNotEquals("pserver collection exists", mongoDatabase().getCollection("pserver"), null);
+ assertEquals("pserver collection contains 1", mongoDatabase().getCollection("pserver").count(), 1);
+ assertTrue("pserver collection contains the pserver in the event",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ assertFalse("pserver should not have relationship to vserver",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'," +
+ "'relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ assertFalse("pserver should not have relationship to l-interface",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'," +
+ "'relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1/l-interfaces/l-interface/l-int-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+
+
+ String crWithNestingAndWithRels = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'cloud-region','top-entity-type':'cloud-region','entity-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6','event-type':'AAI-EVENT','domain':'JUNIT','action':'CREATE','sequence-number':'0','id':'3d567832-df00-49b5-b862-4d3a341dbec1','source-name':'JUNIT','version':'v13','timestamp':'20180515-10:57:55:750'},'entity':{'tenants':{'tenant':[{'vservers':{'vserver':[{'relationship-list':{'relationship':[{'related-to':'pserver','relationship-data':[{'relationship-value':'pserver-1','relationship-key':'pserver.hostname'}],'related-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','relationship-label':'tosca.relationships.HostedOn'}]},'l-interfaces':{'l-interface':[{'interface-name':'l-int-1','interface-id':'l-int-1','l3-interface-ipv4-address-list':[{'neutron-network-id':'93fb399c-9bfc-4234-b2bb-a76eda38f117','neutron-subnet-id':'79e5bb69-24bb-4ea3-8d1d-c04fca5f5e1e','l3-interface-ipv4-address':'192.168.70.3'}],'relationship-list':{'relationship':[{'related-to':'pserver','relationship-data':[{'relationship-value':'pserver-1','relationship-key':'pserver.hostname'}],'related-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','relationship-label':'tosca.relationships.HostedOn'}]}}]},'vserver-id':'vserver-1'}]},'tenant-id':'tenenat-1'}]},'cloud-owner':'onap-cloud-owner','cloud-region-id':'mtn6'}}";
+
+ aaiDmaapEventProcessor.process(crWithNestingAndWithRels);
+
+ assertNotEquals("cloud-region collection exists", mongoDatabase().getCollection("cloud-region"), null);
+ assertTrue("Now pserver has relationship to vserver",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'," +
+ "'relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ assertTrue("Now pserver has relationship to l-interface",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'," +
+ "'relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1/l-interfaces/l-interface/l-int-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ }
+
+
+ @Test
+ public void createCRWithNestingCreatePserverRelationshipsToNestedTest() throws Exception {
+ String crWithNesting = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'cloud-region','top-entity-type':'cloud-region','entity-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6','event-type':'AAI-EVENT','domain':'JUNIT','action':'CREATE','sequence-number':'0','id':'3d567832-df00-49b5-b862-4d3a341dbec1','source-name':'JUNIT','version':'v13','timestamp':'20180515-10:57:55:750'},'entity':{'tenants':{'tenant':[{'vservers':{'vserver':[{'l-interfaces':{'l-interface':[{'interface-name':'l-int-1','interface-id':'l-int-1','l3-interface-ipv4-address-list':[{'neutron-network-id':'93fb399c-9bfc-4234-b2bb-a76eda38f117','neutron-subnet-id':'79e5bb69-24bb-4ea3-8d1d-c04fca5f5e1e','l3-interface-ipv4-address':'192.168.70.3'}]}]},'vserver-id':'vserver-1'}]},'tenant-id':'tenenat-1'}]},'cloud-owner':'onap-cloud-owner','cloud-region-id':'mtn6'}}";
+
+ aaiDmaapEventProcessor.process(crWithNesting);
+
+ assertNotEquals("cloud-region collection exists", mongoDatabase().getCollection("cloud-region"), null);
+
+ String pserverWithRelsToNested = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'pserver','top-entity-type':'pserver','entity-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','event-type':'AAI-EVENT','domain':'JUNIT','action':'CREATE','sequence-number':'0','id':'0c3b336d-6554-4ddf-a4d7-90f97876a966','source-name':'JUNIT','version':'v13','timestamp':'20180209-21:02:20:344'},'entity':{'hostname':'pserver-1','in-maint':false,'relationship-list':{'relationship':[{'related-to':'vserver','relationship-label':'tosca.relationships.HostedOn','related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1','relationship-data':[{'relationship-key':'cloud-region.cloud-owner','relationship-value':'onap-cloud-owner'},{'relationship-key':'cloud-region.cloud-region-id','relationship-value':'mtn6'},{'relationship-key':'tenant.tenant-id','relationship-value':'tenenat-1'},{'relationship-key':'vserver.vserver-id','relationship-value':'vserver-1'}]},{'related-to':'l-interface','relationship-label':'tosca.relationships.HostedOn','related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1/l-interfaces/l-interface/l-int-1','relationship-data':[{'relationship-key':'cloud-region.cloud-owner','relationship-value':'onap-cloud-owner'},{'relationship-key':'cloud-region.cloud-region-id','relationship-value':'mtn6'},{'relationship-key':'tenant.tenant-id','relationship-value':'tenenat-1'},{'relationship-key':'vserver.vserver-id','relationship-value':'vserver-1'},{'relationship-key':'l-interface.interface-name','relationship-value':'l-int-1'}]}]}}}";
+
+ aaiDmaapEventProcessor.process(pserverWithRelsToNested);
+ assertTrue("Now cloud-region->tenant->vserver now has relationship to pserver",
+ mongoDatabase().getCollection("cloud-region")
+ .find(Document.parse("{" +
+ "'cloud-owner':'onap-cloud-owner'," +
+ "'cloud-region-id':'mtn6'," +
+ "'tenants.tenant.tenant-id':'tenenat-1'," +
+ "'tenants.tenant.vservers.vserver.vserver-id':'vserver-1'," +
+ "'tenants.tenant.vservers.vserver.relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ assertTrue("Now cloud-region->tenant->vserver->l-interface now has relationship to pserver",
+ mongoDatabase().getCollection("cloud-region")
+ .find(Document.parse("{" +
+ "'cloud-owner':'onap-cloud-owner'," +
+ "'cloud-region-id':'mtn6'," +
+ "'tenants.tenant.tenant-id':'tenenat-1'," +
+ "'tenants.tenant.vservers.vserver.vserver-id':'vserver-1'," +
+ "'tenants.tenant.vservers.vserver.l-interfaces.l-interface.interface-name':'l-int-1'," +
+ "'tenants.tenant.vservers.vserver.relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ }
+
+ @Ignore
+ @Test
+ public void createPserverCreateCRWithNestingAndRelsToUpdateRemovingARelTest() throws Exception {
+ String pserverCreate = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'pserver','top-entity-type':'pserver','entity-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','event-type':'AAI-EVENT','domain':'JUNIT','action':'CREATE','sequence-number':'0','id':'0c3b336d-6554-4ddf-a4d7-90f97876a966','source-name':'JUNIT','version':'v13','timestamp':'20180209-21:02:20:344'},'entity':{'hostname':'pserver-1','in-maint':false}}";
+
+ aaiDmaapEventProcessor.process(pserverCreate);
+ assertNotEquals("pserver collection exists", mongoDatabase().getCollection("pserver"), null);
+ assertEquals("pserver collection contains 1", mongoDatabase().getCollection("pserver").count(), 1);
+ assertTrue("pserver collection contains the pserver in the event",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ assertFalse("pserver should not have relationship to vserver",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'," +
+ "'relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ assertFalse("pserver should not have relationship to l-interface",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'," +
+ "'relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1/l-interfaces/l-interface/l-int-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+
+
+ String crWithNestingAndWithRels = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'cloud-region','top-entity-type':'cloud-region','entity-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6','event-type':'AAI-EVENT','domain':'JUNIT','action':'CREATE','sequence-number':'0','id':'3d567832-df00-49b5-b862-4d3a341dbec1','source-name':'JUNIT','version':'v13','timestamp':'20180515-10:57:55:750'},'entity':{'tenants':{'tenant':[{'vservers':{'vserver':[{'relationship-list':{'relationship':[{'related-to':'pserver','relationship-data':[{'relationship-value':'pserver-1','relationship-key':'pserver.hostname'}],'related-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','relationship-label':'tosca.relationships.HostedOn'}]},'l-interfaces':{'l-interface':[{'interface-name':'l-int-1','interface-id':'l-int-1','l3-interface-ipv4-address-list':[{'neutron-network-id':'93fb399c-9bfc-4234-b2bb-a76eda38f117','neutron-subnet-id':'79e5bb69-24bb-4ea3-8d1d-c04fca5f5e1e','l3-interface-ipv4-address':'192.168.70.3'}],'relationship-list':{'relationship':[{'related-to':'pserver','relationship-data':[{'relationship-value':'pserver-1','relationship-key':'pserver.hostname'}],'related-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','relationship-label':'tosca.relationships.HostedOn'}]}}]},'vserver-id':'vserver-1'}]},'tenant-id':'tenenat-1'}]},'cloud-owner':'onap-cloud-owner','cloud-region-id':'mtn6'}}";
+
+ aaiDmaapEventProcessor.process(crWithNestingAndWithRels);
+
+ assertNotEquals("cloud-region collection exists", mongoDatabase().getCollection("cloud-region"), null);
+ assertTrue("Now pserver has relationship to vserver",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'," +
+ "'relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ assertTrue("Now pserver has relationship to l-interface",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'," +
+ "'relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1/l-interfaces/l-interface/l-int-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+
+
+ String updatePserverWithoutInterfaceRel = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'pserver','top-entity-type':'pserver','entity-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','event-type':'AAI-EVENT','domain':'JUNIT','action':'UPDATE','sequence-number':'0','id':'0c3b336d-6554-4ddf-a4d7-90f97876a966','source-name':'JUNIT','version':'v13','timestamp':'20180209-21:02:20:344'},'entity':{'hostname':'pserver-1','in-maint':false,'relationship-list':{'relationship':[{'related-to':'vserver','relationship-label':'tosca.relationships.HostedOn','related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1','relationship-data':[{'relationship-key':'cloud-region.cloud-owner','relationship-value':'onap-cloud-owner'},{'relationship-key':'cloud-region.cloud-region-id','relationship-value':'mtn6'},{'relationship-key':'tenant.tenant-id','relationship-value':'tenenat-1'},{'relationship-key':'vserver.vserver-id','relationship-value':'vserver-1'}]}]}}}";
+
+ aaiDmaapEventProcessor.process(updatePserverWithoutInterfaceRel);
+
+ assertTrue("Now cloud-region->tenant->vserver should still have relationship to pserver",
+ mongoDatabase().getCollection("cloud-region")
+ .find(Document.parse("{" +
+ "'cloud-owner':'onap-cloud-owner'," +
+ "'cloud-region-id':'mtn6'," +
+ "'tenants.tenant.tenant-id':'tenenat-1'," +
+ "'tenants.tenant.vservers.vserver.vserver-id':'vserver-1'," +
+ "'tenants.tenant.vservers.vserver.relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ assertFalse("Now cloud-region->tenant->vserver->l-interface should not have relationship to pserver",
+ mongoDatabase().getCollection("cloud-region")
+ .find(Document.parse("{" +
+ "'cloud-owner':'onap-cloud-owner'," +
+ "'cloud-region-id':'mtn6'," +
+ "'tenants.tenant.tenant-id':'tenenat-1'," +
+ "'tenants.tenant.vservers.vserver.vserver-id':'vserver-1'," +
+ "'tenants.tenant.vservers.vserver.l-interfaces.l-interface.interface-name':'l-int-1'," +
+ "'tenants.tenant.vservers.vserver.l-interfaces.l-interface.relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ }
+
+ @Test
+ public void createPserverCreateCRWithNestingAndRelationshipsToThenDeletePserverTest() throws Exception {
+ String pserverCreate = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'pserver','top-entity-type':'pserver','entity-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','event-type':'AAI-EVENT','domain':'JUNIT','action':'CREATE','sequence-number':'0','id':'0c3b336d-6554-4ddf-a4d7-90f97876a966','source-name':'JUNIT','version':'v13','timestamp':'20180209-21:02:20:344'},'entity':{'hostname':'pserver-1','in-maint':false}}";
+
+ aaiDmaapEventProcessor.process(pserverCreate);
+ assertNotEquals("pserver collection exists", mongoDatabase().getCollection("pserver"), null);
+ assertEquals("pserver collection contains 1", mongoDatabase().getCollection("pserver").count(), 1);
+ assertTrue("pserver collection contains the pserver in the event",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ assertFalse("pserver should not have relationship to vserver",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'," +
+ "'relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ assertFalse("pserver should not have relationship to l-interface",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'," +
+ "'relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1/l-interfaces/l-interface/l-int-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+
+
+ String crWithNestingAndWithRels = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'cloud-region','top-entity-type':'cloud-region','entity-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6','event-type':'AAI-EVENT','domain':'JUNIT','action':'CREATE','sequence-number':'0','id':'3d567832-df00-49b5-b862-4d3a341dbec1','source-name':'JUNIT','version':'v13','timestamp':'20180515-10:57:55:750'},'entity':{'tenants':{'tenant':[{'vservers':{'vserver':[{'relationship-list':{'relationship':[{'related-to':'pserver','relationship-data':[{'relationship-value':'pserver-1','relationship-key':'pserver.hostname'}],'related-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','relationship-label':'tosca.relationships.HostedOn'}]},'l-interfaces':{'l-interface':[{'interface-name':'l-int-1','interface-id':'l-int-1','l3-interface-ipv4-address-list':[{'neutron-network-id':'93fb399c-9bfc-4234-b2bb-a76eda38f117','neutron-subnet-id':'79e5bb69-24bb-4ea3-8d1d-c04fca5f5e1e','l3-interface-ipv4-address':'192.168.70.3'}],'relationship-list':{'relationship':[{'related-to':'pserver','relationship-data':[{'relationship-value':'pserver-1','relationship-key':'pserver.hostname'}],'related-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','relationship-label':'tosca.relationships.HostedOn'}]}}]},'vserver-id':'vserver-1'}]},'tenant-id':'tenenat-1'}]},'cloud-owner':'onap-cloud-owner','cloud-region-id':'mtn6'}}";
+
+ aaiDmaapEventProcessor.process(crWithNestingAndWithRels);
+
+ assertNotEquals("cloud-region collection exists", mongoDatabase().getCollection("cloud-region"), null);
+ assertTrue("Now pserver has relationship to vserver",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'," +
+ "'relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ assertTrue("Now pserver has relationship to l-interface",
+ mongoDatabase().getCollection("pserver")
+ .find(Document.parse("{" +
+ "'hostname':'pserver-1'," +
+ "'relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1/l-interfaces/l-interface/l-int-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+
+ String pserverDelete = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'pserver','top-entity-type':'pserver','entity-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','event-type':'AAI-EVENT','domain':'JUNIT','action':'DELETE','sequence-number':'0','id':'0c3b336d-6554-4ddf-a4d7-90f97876a966','source-name':'JUNIT','version':'v13','timestamp':'20180209-21:02:20:344'},'entity':{'hostname':'pserver-1','in-maint':false,'relationship-list':{'relationship':[{'related-to':'vserver','relationship-label':'tosca.relationships.HostedOn','related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1','relationship-data':[{'relationship-key':'cloud-region.cloud-owner','relationship-value':'onap-cloud-owner'},{'relationship-key':'cloud-region.cloud-region-id','relationship-value':'mtn6'},{'relationship-key':'tenant.tenant-id','relationship-value':'tenenat-1'},{'relationship-key':'vserver.vserver-id','relationship-value':'vserver-1'}]},{'related-to':'l-interface','relationship-label':'tosca.relationships.HostedOn','related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1/l-interfaces/l-interface/l-int-1','relationship-data':[{'relationship-key':'cloud-region.cloud-owner','relationship-value':'onap-cloud-owner'},{'relationship-key':'cloud-region.cloud-region-id','relationship-value':'mtn6'},{'relationship-key':'tenant.tenant-id','relationship-value':'tenenat-1'},{'relationship-key':'vserver.vserver-id','relationship-value':'vserver-1'},{'relationship-key':'l-interface.interface-name','relationship-value':'l-int-1'}]}]}}}";
+
+ aaiDmaapEventProcessor.process(pserverDelete);
+ assertNotEquals("pserver collection exists", mongoDatabase().getCollection("pserver"), null);
+ assertEquals("pserver collection contains 1", mongoDatabase().getCollection("pserver").count(), 0);
+
+ assertFalse("Now cloud-region->tenant->vserver should not have relationship to pserver",
+ mongoDatabase().getCollection("cloud-region")
+ .find(Document.parse("{" +
+ "'cloud-owner':'onap-cloud-owner'," +
+ "'cloud-region-id':'mtn6'," +
+ "'tenants.tenant.tenant-id':'tenenat-1'," +
+ "'tenants.tenant.vservers.vserver.vserver-id':'vserver-1'," +
+ "'tenants.tenant.vservers.vserver.relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+ assertFalse("Now cloud-region->tenant->vserver->l-interface should not have relationship to pserver",
+ mongoDatabase().getCollection("cloud-region")
+ .find(Document.parse("{" +
+ "'cloud-owner':'onap-cloud-owner'," +
+ "'cloud-region-id':'mtn6'," +
+ "'tenants.tenant.tenant-id':'tenenat-1'," +
+ "'tenants.tenant.vservers.vserver.vserver-id':'vserver-1'," +
+ "'tenants.tenant.vservers.vserver.l-interfaces.l-interface.interface-name':'l-int-1'," +
+ "'tenants.tenant.vservers.vserver.l-interfaces.l-interface.relationship-list.relationship.related-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1'" +
+ "}"))
+ .iterator().hasNext()
+ );
+
+ }
+
+
+ @Test
+ public void createPserverRelationshipsToNonExistingTest() throws Exception {
+
+ String pserverWithRelsToNested = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'pserver','top-entity-type':'pserver','entity-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','event-type':'AAI-EVENT','domain':'JUNIT','action':'CREATE','sequence-number':'0','id':'0c3b336d-6554-4ddf-a4d7-90f97876a966','source-name':'JUNIT','version':'v13','timestamp':'20180209-21:02:20:344'},'entity':{'hostname':'pserver-1','in-maint':false,'relationship-list':{'relationship':[{'related-to':'cloud-region','relationship-label':'tosca.relationships.HostedOn','related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6','relationship-data':[{'relationship-key':'cloud-region.cloud-owner','relationship-value':'onap-cloud-owner'},{'relationship-key':'cloud-region.cloud-region-id','relationship-value':'mtn6'}]},{'related-to':'vserver','relationship-label':'tosca.relationships.HostedOn','related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1','relationship-data':[{'relationship-key':'cloud-region.cloud-owner','relationship-value':'onap-cloud-owner'},{'relationship-key':'cloud-region.cloud-region-id','relationship-value':'mtn6'},{'relationship-key':'tenant.tenant-id','relationship-value':'tenenat-1'},{'relationship-key':'vserver.vserver-id','relationship-value':'vserver-1'}]},{'related-to':'l-interface','relationship-label':'tosca.relationships.HostedOn','related-link':'/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/mtn6/tenants/tenant/tenenat-1/vservers/vserver/vserver-1/l-interfaces/l-interface/l-int-1','relationship-data':[{'relationship-key':'cloud-region.cloud-owner','relationship-value':'onap-cloud-owner'},{'relationship-key':'cloud-region.cloud-region-id','relationship-value':'mtn6'},{'relationship-key':'tenant.tenant-id','relationship-value':'tenenat-1'},{'relationship-key':'vserver.vserver-id','relationship-value':'vserver-1'},{'relationship-key':'l-interface.interface-name','relationship-value':'l-int-1'}]}]}}}";
+
+ aaiDmaapEventProcessor.process(pserverWithRelsToNested);
+
+ }
+
+ @Test
+ public void linterfaceWithLinterfaceTest() throws Exception {
+
+ String linterfaceWithLinterface = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'l-interface','top-entity-type':'pserver','entity-link':'/aai/v13/cloud-infrastructure/pservers/pserver/c9e8ffb6-a360-4f9c-96c3-f5f0244dfe55-jenkins/lag-interfaces/lag-interface/8806d30d-e5f5-409e-9e9e-9b1c1943058d-jenkins/l-interfaces/l-interface/f4f9b9c7-eb83-4622-9d6f-14027a556ff5-jenkins/l-interfaces/l-interface/89796dd1-89a5-4ddc-bd13-324ba9bce3b6-jenkins','event-type':'AAI-EVENT','domain':'uINT1','action':'DELETE','sequence-number':'0','id':'9060077e-00a3-4239-80ed-855331b4d551','source-name':'FitNesse-Test-jenkins','version':'v13','timestamp':'20180625-01:24:04:857'},'entity':{'pserver-name2':'iqFmGNmNLM6','hostname':'c9e8ffb6-a360-4f9c-96c3-f5f0244dfe55-jenkins','lag-interfaces':{'lag-interface':[{'l-interfaces':{'l-interface':[{'l-interfaces':{'l-interface':[{'v6-wan-link-ip':'PuNFKRUUpd3','interface-name':'89796dd1-89a5-4ddc-bd13-324ba9bce3b6-jenkins','allowed-address-pairs':'RGo6MaADK','prov-status':'uot','macaddr':'xUj8TGre','interface-role':'SyT0hd9Uu4b','selflink':'HxDI','in-maint':false,'admin-status':'GDgD','is-port-mirrored':true,'resource-version':'1529889840462','is-ip-unnumbered':false,'network-name':'RXCo3p3p5BhBS','management-option':'jNiTd','interface-id':'4n8niH','interface-description':'drnTF3'}]},'interface-name':'f4f9b9c7-eb83-4622-9d6f-14027a556ff5-jenkins'}]},'interface-name':'8806d30d-e5f5-409e-9e9e-9b1c1943058d-jenkins'}]}}}";
+
+ aaiDmaapEventProcessor.process(linterfaceWithLinterface);
+
+ }
+
+ @Test
+ public void nosTest() throws Exception {
+
+ String nos = getEventPayload("nos");
+
+ aaiDmaapEventProcessor.process(nos);
+
+ }
+
+ @Test
+ public void addressListTest() throws Exception {
+
+ String event = getEventPayload("address-list");
+ aaiDmaapEventProcessor.process(event);
+
+ }
+
+ @Test
+ public void vceTest() throws Exception {
+
+ String event = getEventPayload("vce");
+ aaiDmaapEventProcessor.process(event);
+
+ }
+
+ @Test
+ public void largePserverTest() throws Exception {
+
+ String event = getEventPayload("large-pserver");
+ aaiDmaapEventProcessor.process(event);
+
+ }
+
+ @Test
+ public void delRel() throws Exception {
+
+ String event = getEventPayload("deleteRelationship/1-create-logical-link");
+ aaiDmaapEventProcessor.process(event);
+
+ event = getEventPayload("deleteRelationship/2-create-generic-vnf");
+ aaiDmaapEventProcessor.process(event);
+
+ event = getEventPayload("deleteRelationship/3-create-rel-generic-vnf-vlan-to-logical-link");
+ aaiDmaapEventProcessor.process(event);
+
+ event = getEventPayload("deleteRelationship/4-delete-rel-to-generic-vnf-vlan-from-logical-link");
+ aaiDmaapEventProcessor.process(event);
+
+ assertFalse("Now generic-vnf->l-interface->vlan should not have relationship to logical-link",
+ mongoDatabase().getCollection("generic-vnf")
+ .find(Document.parse("{" +
+ "'_id': '/network/generic-vnfs/generic-vnf/generic-vnf-id'," +
+ "'vnf-id': 'generic-vnf-id'," +
+ "'l-interfaces.l-interface.interface-name': 'l-interface-name-1'," +
+ "'l-interfaces.l-interface.vlans.vlan.vlan-interface': 'vlan-1'," +
+ "'l-interfaces.l-interface.vlans.vlan.relationship-list.relationship.related-link':'/aai/v13/network/logical-links/logical-link/logical-link'" +
+ "}"))
+ .iterator().hasNext());
+
+ }
+
+ protected String getEventPayload(String eventpayloadName) throws IOException {
+ return getPayload("test/payloads/dmaapEvents/" + eventpayloadName + ".json");
+ }
+
+ private String getPayload(String filename) throws IOException {
+
+ InputStream inputStream = getClass()
+ .getClassLoader()
+ .getResourceAsStream(filename);
+
+ String message = String.format("Unable to find the %s in src/test/resources", filename);
+ assertNotNull(message, inputStream);
+
+ return IOUtils.toString(inputStream);
+ }
+
+} \ No newline at end of file
diff --git a/src/test/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessorTest.java b/src/test/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessorTest.java
new file mode 100644
index 0000000..8fcd7e2
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/dmaap/consumer/AAIDmaapEventProcessorTest.java
@@ -0,0 +1,80 @@
+/**
+ * ============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.cacher.dmaap.consumer;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class AAIDmaapEventProcessorTest {
+ private AAIDmaapEventProcessor eventProcessor;
+
+ private String validEventMessage = "{'cambria.partition': 'AAI','event-header': {'id': 'ABC','source-name': 'sourceName'},'entity': {'hostname': 'hostName'}}";
+ private String invalidEventMessageHeader = "{'cambria.partition': 'AAI','Xevent-header': {'id': 'ABC','source-name': 'sourceName'},'entity': {'hostname': 'hostName'}}";
+ private String invalidEventMessageHeaderMissingId = "{'cambria.partition': 'AAI','event-header': {'idX': 'ABC','source-name': 'sourceName'},'entity': {'hostname': 'hostName'}}";
+ private String invalidEventMessageHeaderMissingSourceName = "{'cambria.partition': 'AAI','event-header': {'id': 'ABC','source-nameX': 'sourceName'},'entity': {'hostname': 'hostName'}}";
+ private String invalidEventMessageBody = "{'cambria.partition': 'AAI','event-header': {'id': 'ABC','source-name': 'sourceName'},'Xentity': {'hostname': 'hostName'}}";
+
+
+ @Before
+ public void setUp() throws Exception {
+ eventProcessor = new AAIDmaapEventProcessor();
+ }
+
+ @Ignore
+ @Test
+ public void testValidEventMessage() throws Exception {
+ eventProcessor.process(validEventMessage);
+ JSONObject header = eventProcessor.getEventHeader();
+ JSONObject body = eventProcessor.getEventBody();
+ assertEquals("header id", "ABC",header.getString("id") );
+ assertEquals("hostname", "hostName",body.getString("hostname") );
+ }
+
+ @Test(expected = JSONException.class)
+ public void testJSONException() throws Exception {
+ eventProcessor.process("invalidJson");
+ }
+
+ @Test(expected = JSONException.class)
+ public void testInvalidHeader() throws Exception {
+ eventProcessor.process(invalidEventMessageHeader);
+ }
+
+ @Test(expected = JSONException.class)
+ public void testInvalidHeaderMissingId() throws Exception {
+ eventProcessor.process(invalidEventMessageHeaderMissingId);
+ }
+
+ @Test(expected = JSONException.class)
+ public void testInvalidHeaderMissingSourceName() throws Exception {
+ eventProcessor.process(invalidEventMessageHeaderMissingSourceName);
+ }
+
+ @Test(expected = JSONException.class)
+ public void testInvalidEventMessageBody() throws Exception {
+ eventProcessor.process(invalidEventMessageBody);
+ }
+}
diff --git a/src/test/java/org/onap/aai/cacher/dmaap/consumer/AAIEventConsumerTest.java b/src/test/java/org/onap/aai/cacher/dmaap/consumer/AAIEventConsumerTest.java
new file mode 100644
index 0000000..3ca3390
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/dmaap/consumer/AAIEventConsumerTest.java
@@ -0,0 +1,185 @@
+/**
+ * ============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.cacher.dmaap.consumer;
+
+import com.att.nsa.mr.client.MRConsumer;
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoDatabase;
+
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodProcess;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.IMongodConfig;
+import de.flapdoodle.embed.mongo.config.MongoCmdOptionsBuilder;
+import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Net;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.process.runtime.Network;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.onap.aai.cacher.common.MongoHelperSingleton;
+import org.onap.aai.cacher.egestion.printer.EgestionTestComponent;
+import org.onap.aai.cacher.injestion.parser.InjestionTestComponent;
+import org.onap.aai.cacher.injestion.parser.PayloadParserService;
+import org.onap.aai.cacher.service.helper.RestClientHelperService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+//@Ignore
+@RunWith(SpringJUnit4ClassRunner.class)
+@Configuration
+@ContextConfiguration(classes = {InjestionTestComponent.class, AAIEventConsumerTest.class})
+public class AAIEventConsumerTest {
+ private static final String DB_NAME = AAIEventConsumerTest.class.getSimpleName();
+ private static MongoDatabase mongoDb;
+ private static RestClientHelperService restClientHelperService;
+ private static DB db;
+ private static MongodProcess mongod;
+ private static MongoClient mongoC;
+
+ private AAIEventConsumer aaiEventConsumer;
+
+ @Autowired
+ private AAIDmaapEventProcessor aaiDmaapEventProcessor;
+
+ @Bean
+ public DB db() {
+ return db;
+ }
+
+ @Bean
+ public MongoDatabase mongoDatabase() {
+ return mongoDb;
+ }
+
+ @Bean
+ public RestClientHelperService restClientHelperService() {
+ return restClientHelperService;
+ }
+
+ @Bean
+ public MongoHelperSingleton mongoHelperSingleton(DB db, MongoDatabase mongoDb) {
+ return new MongoHelperSingleton(db, mongoDb);
+ }
+
+ @Bean
+ public AAIDmaapEventProcessor aaiDmaapEventProcessor(MongoHelperSingleton mongoHelperSingleton, PayloadParserService payloadParserService) {
+ return new AAIDmaapEventProcessor(mongoHelperSingleton, payloadParserService);
+ }
+
+
+ MRConsumer client;
+ private String validEventMessage = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'pserver','top-entity-type':'pserver','entity-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','event-type':'AAI-EVENT','domain':'JUNIT','action':'CREATE','sequence-number':'0','id':'0c3b336d-6554-4ddf-a4d7-90f97876a966','source-name':'JUNIT','version':'v13','timestamp':'20180209-21:02:20:344'},'entity':{'hostname':'pserver-1','in-maint':false}}";
+ private String validHeldEventMessage = "{'cambria.partition':'AAI','event-header':{'severity':'NORMAL','entity-type':'pserver','top-entity-type':'pserver','entity-link':'/aai/v13/cloud-infrastructure/pservers/pserver/pserver-1','event-type':'AAI-EVENT','domain':'JUNIT','action':'CREATE','sequence-number':'0','id':'0c3b336d-6554-4ddf-a4d7-90f97876a966','source-name':'JUNIT','version':'v13','timestamp':'20180209-21:02:20:344'},'entity':{'hostname':'pserver-1','in-maint':false}}";
+ DmaapConsumerSingleton singleton = DmaapConsumerSingleton.getInstance();
+ List<String> eventMessageList = new ArrayList<>();
+
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ String bindIp = "localhost";
+ int port = 27017;
+ startEmbedded(port);
+
+ mongoC = new MongoClient(bindIp, port);
+ mongoDb = mongoC.getDatabase(DB_NAME);
+ db = mongoC.getDB(DB_NAME);
+
+ }
+
+ @Before
+ public void init() throws Exception {
+ eventMessageList.add(validEventMessage);
+ //super.setupBundleconfig();
+ aaiEventConsumer = new AAIEventConsumer("aaiDmaaPEventConsumer.properties", true);
+ Properties prop = aaiEventConsumer.getDmaapEventConsumerProperties();
+ client = Mockito.mock(MRConsumer.class);
+ aaiEventConsumer.setConsumer(client);
+
+
+ }
+
+ protected static void startEmbedded(int port) throws IOException {
+ IMongodConfig mongoConfigConfig = new MongodConfigBuilder()
+ .version(Version.Main.PRODUCTION)
+ .net(new Net(port, Network.localhostIsIPv6()))
+ .cmdOptions(new MongoCmdOptionsBuilder().verbose(true).build())
+ .configServer(false)
+ .build();
+
+ MongodExecutable mongodExecutable = MongodStarter.getDefaultInstance().prepare(mongoConfigConfig);
+
+ mongod = mongodExecutable.start();
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ if (mongod != null && mongod.isProcessRunning()) {
+ mongod.stop();
+ }
+ }
+
+ @After
+ public void cleanup() {
+ final List<String> collectionNames = new ArrayList<>();
+ mongoDb.listCollections().iterator().forEachRemaining(document -> collectionNames.add(document.getString("name")));
+ collectionNames.forEach(collectionName -> mongoDb.getCollection(collectionName).drop());
+ }
+
+ @Test
+ public void startProcessing() throws IOException, Exception {
+ Mockito.when(client.fetch()).thenReturn(eventMessageList);
+ aaiEventConsumer.startProcessing(aaiDmaapEventProcessor);
+ }
+
+ @Test
+ public void startProcessingWaitWithHeldEventMessage() throws IOException, Exception {
+ singleton.setIsInitialized(true);
+ singleton.setFirstEventMessage(validHeldEventMessage);
+ Mockito.when(client.fetch()).thenReturn(eventMessageList);
+ aaiEventConsumer.startProcessing(aaiDmaapEventProcessor);
+ }
+
+ @Test
+ public void startProcessingNoWaitWithHeldEventMessage() throws IOException, Exception {
+ singleton.setProcessEvents(true);
+ singleton.setFirstEventMessage(validHeldEventMessage);
+ Mockito.when(client.fetch()).thenReturn(eventMessageList);
+ aaiEventConsumer.startProcessing(aaiDmaapEventProcessor);
+ }
+
+}
+
diff --git a/src/test/java/org/onap/aai/cacher/dmaap/consumer/DmaapConsumerSingletonTest.java b/src/test/java/org/onap/aai/cacher/dmaap/consumer/DmaapConsumerSingletonTest.java
new file mode 100644
index 0000000..60ee2e1
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/dmaap/consumer/DmaapConsumerSingletonTest.java
@@ -0,0 +1,39 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.dmaap.consumer;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class DmaapConsumerSingletonTest {
+
+ static final String firstEventMessage = "firstMessageValue";
+ @Test
+ public void testSingleton() {
+ DmaapConsumerSingleton dmaapConsumerSingleton = DmaapConsumerSingleton.getInstance();
+ dmaapConsumerSingleton.setIsInitialized(true);
+ dmaapConsumerSingleton.setProcessEvents(false);
+ dmaapConsumerSingleton.setFirstEventMessage(firstEventMessage);
+ assertTrue("isInitialized", dmaapConsumerSingleton.getIsInitialized());
+ assertFalse("processEvents", dmaapConsumerSingleton.getProcessEvents());
+ assertEquals("firstEventMessage", firstEventMessage, dmaapConsumerSingleton.getFirstEventMessage());
+ }
+}
diff --git a/src/test/java/org/onap/aai/cacher/egestion/printer/EgestionTestComponent.java b/src/test/java/org/onap/aai/cacher/egestion/printer/EgestionTestComponent.java
new file mode 100644
index 0000000..fa4ce13
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/egestion/printer/EgestionTestComponent.java
@@ -0,0 +1,35 @@
+/**
+ * ============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.cacher.egestion.printer;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+import java.nio.file.FileSystems;
+
+@Configuration
+@ComponentScan(basePackages = {"org.onap.aai.cacher.egestion.printer"})
+public class EgestionTestComponent {
+ public EgestionTestComponent() {
+ System.setProperty("AJSC_HOME", FileSystems.getDefault().getPath(".").toAbsolutePath().toString());
+ System.setProperty("BUNDLECONFIG_DIR", "src/main/resources");
+
+ }
+}
diff --git a/src/test/java/org/onap/aai/cacher/injestion/parser/AAIResourcesUriTemplatesTest.java b/src/test/java/org/onap/aai/cacher/injestion/parser/AAIResourcesUriTemplatesTest.java
new file mode 100644
index 0000000..a48712f
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/injestion/parser/AAIResourcesUriTemplatesTest.java
@@ -0,0 +1,137 @@
+/**
+ * ============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.cacher.injestion.parser;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.*;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = InjestionTestComponent.class)
+public class AAIResourcesUriTemplatesTest {
+
+ @Autowired
+ AAIResourcesUriTemplates aaiResourcesUriTemplates;
+
+ @Test
+ public void getUriTemplateByType() throws Exception {
+
+ assertEquals("Service template is returned",
+ "/service-design-and-creation/services/service/{service-id}",
+ aaiResourcesUriTemplates.getUriTemplateByType("service"));
+
+ assertFalse(aaiResourcesUriTemplates.getUriTemplateByType("does not exist") != null);
+
+ }
+
+ @Test
+ public void getMatchingStartingTemplate() throws Exception {
+ String uri = "/service-design-and-creation/services/service/id/l-interfaces/l-interface/name/p-interfaces/p-interface/name2";
+ assertEquals("Service template is returned",
+ "/service-design-and-creation/services/service/{service-id}",
+ aaiResourcesUriTemplates.getMatchingStartingTemplate(uri).get());
+
+ uri = "/l-interfaces/l-interface/name/p-interfaces/p-interface/name2";
+ assertEquals("l-interface template is returned",
+ "/l-interfaces/l-interface/{interface-name}",
+ aaiResourcesUriTemplates.getMatchingStartingTemplate(uri).get());
+
+ uri = "/l-interface/name/p-interfaces/p-interface/name2";
+ assertFalse(aaiResourcesUriTemplates.getMatchingStartingTemplate(uri).isPresent());
+ }
+
+ @Test
+ public void uriToTemplatesValidTest() throws Exception {
+ String uri = "/service-design-and-creation/services/service/id/l-interfaces/l-interface/name/p-interfaces/p-interface/name2";
+ List<String> expected = Arrays.asList(
+ "/service-design-and-creation/services/service/{service-id}",
+ "/l-interfaces/l-interface/{interface-name}",
+ "/p-interfaces/p-interface/{interface-name}"
+ );
+
+ assertThat(aaiResourcesUriTemplates.uriToTemplates(uri), is(expected));
+ }
+
+ @Test
+ public void uriToTemplatesRepeatedValidTest() throws Exception {
+ String uri = "/service-design-and-creation/services/service/id/l-interfaces/l-interface/name/l-interfaces/l-interface/name2";
+ List<String> expected = Arrays.asList(
+ "/service-design-and-creation/services/service/{service-id}",
+ "/l-interfaces/l-interface/{interface-name}",
+ "/l-interfaces/l-interface/{interface-name}"
+ );
+
+ assertThat(aaiResourcesUriTemplates.uriToTemplates(uri), is(expected));
+ }
+
+ @Test
+ public void uriToSegmentsValidTest() throws Exception {
+ String uri = "/service-design-and-creation/services/service/id/l-interfaces/l-interface/name/p-interfaces/p-interface/name2";
+ List<String> expected = Arrays.asList(
+ "/service-design-and-creation/services/service/id",
+ "/l-interfaces/l-interface/name",
+ "/p-interfaces/p-interface/name2"
+ );
+
+ assertThat(aaiResourcesUriTemplates.uriToSegments(uri), is(expected));
+ }
+
+ @Test
+ public void uriAndTemplateToKeyValueMappingTest() throws Exception {
+ String uri = "/service-design-and-creation/services/service/id";
+ String template = "/service-design-and-creation/services/service/{service-id}";
+ Map<String, String> expected = new HashMap<>();
+ expected.put("service-id", "id");
+
+ assertThat(aaiResourcesUriTemplates.getUriTemplateMappings(uri, template), is(expected));
+ }
+
+ @Test
+ public void uriAndTemplateToKeyValueMappingWithEncodingTest() throws Exception {
+ String uri = "/service-design-and-creation/services/service/i%3Ad";
+ String template = "/service-design-and-creation/services/service/{service-id}";
+ Map<String, String> expected = new HashMap<>();
+ expected.put("service-id", "i:d");
+
+ assertThat(aaiResourcesUriTemplates.getUriTemplateMappings(uri, template), is(expected));
+ }
+
+ @Test
+ public void uriAndTemplateToKeyValueMappingWihtMultipleTest() throws Exception {
+ String uri = "/cloud-infrastructure/cloud-regions/cloud-region/owner/i%3Ad";
+ String template = "/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}";
+ Map<String, String> expected = new HashMap<>();
+ expected.put("cloud-owner", "owner");
+ expected.put("cloud-region-id", "i:d");
+
+ assertThat(aaiResourcesUriTemplates.getUriTemplateMappings(uri, template), is(expected));
+ }
+
+} \ No newline at end of file
diff --git a/src/test/java/org/onap/aai/cacher/injestion/parser/InjestionTestComponent.java b/src/test/java/org/onap/aai/cacher/injestion/parser/InjestionTestComponent.java
new file mode 100644
index 0000000..34cc8a3
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/injestion/parser/InjestionTestComponent.java
@@ -0,0 +1,35 @@
+/**
+ * ============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.cacher.injestion.parser;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+import java.nio.file.FileSystems;
+
+@Configuration
+@ComponentScan(basePackages = {"org.onap.aai.cacher.injestion"})
+public class InjestionTestComponent {
+ public InjestionTestComponent() {
+ System.setProperty("AJSC_HOME", FileSystems.getDefault().getPath(".").toAbsolutePath().toString());
+ System.setProperty("BUNDLECONFIG_DIR", "src/main/resources");
+
+ }
+}
diff --git a/src/test/java/org/onap/aai/cacher/injestion/parser/PayloadParserServiceTest.java b/src/test/java/org/onap/aai/cacher/injestion/parser/PayloadParserServiceTest.java
new file mode 100644
index 0000000..1579323
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/injestion/parser/PayloadParserServiceTest.java
@@ -0,0 +1,148 @@
+/**
+ * ============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.cacher.injestion.parser;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.aai.cacher.injestion.parser.strategy.PayloadParserType;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = InjestionTestComponent.class)
+public class PayloadParserServiceTest {
+
+ @Autowired
+ private PayloadParserService parserService;
+
+ private JsonParser parser = new JsonParser();
+
+ private String aaiGetAllServiceResponse =
+ "{" +
+ " 'service': [" +
+ " {" +
+ " 'service-id': 'service-id-1:1'," +
+ " 'service-description': 'A'," +
+ " 'resource-version': '1'" +
+ " }," +
+ " {" +
+ " 'service-id': 'service-id-2'," +
+ " 'service-description': 'B'," +
+ " 'resource-version': '2'" +
+ " }" +
+ " ]" +
+ "}";
+ private JsonObject aaiGetAllServiceResponseJson = parser.parse(aaiGetAllServiceResponse).getAsJsonObject();
+
+
+
+ private void print(List<CacheEntry> result) {
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ result.forEach(e -> System.out.println("Collection: " + e.getCollection() + "\nKey: " + e.getId() + "\n" + gson.toJson(e.getPayload())));
+ }
+
+ @Test
+ public void testGetAllAAIResourceTest() throws JSONException {
+ String expectedUri = "/service-design-and-creation/services/service/service-id-1%3A1";
+
+ List<CacheEntry> result = parserService.doParse("service", aaiGetAllServiceResponseJson, "aai-resource-get-all");
+ print(result);
+
+ assertTrue(result.stream().map(cacheIdentifier -> cacheIdentifier.getId()).anyMatch(id -> id.equals(expectedUri)));
+ JSONAssert.assertEquals(
+ new JSONObject(aaiGetAllServiceResponseJson.getAsJsonArray("service").get(0).getAsJsonObject().toString()),
+ new JSONObject(result.stream().filter(e -> e.getId().equals(expectedUri)).map(CacheEntry::getPayload).findFirst().get().toString()),
+ false);
+
+ }
+
+ @Test
+ public void testGetAllAAIResourceStringTest() throws JSONException {
+ String expectedUri = "/service-design-and-creation/services/service/service-id-2";
+
+ List<CacheEntry> result = parserService.doParse("service", aaiGetAllServiceResponse, PayloadParserType.AAI_RESOURCE_GET_ALL);
+ print(result);
+
+ assertTrue(result.stream().map(cacheIdentifier -> cacheIdentifier.getId()).anyMatch(id -> id.equals(expectedUri)));
+ JSONAssert.assertEquals(
+ new JSONObject(aaiGetAllServiceResponseJson.getAsJsonArray("service").get(1).getAsJsonObject().toString()),
+ new JSONObject(result.stream().filter(e -> e.getId().equals(expectedUri)).map(CacheEntry::getPayload).findFirst().get().toString()),
+ false);
+ }
+
+ @Test
+ public void testNoneStrategyTest1() throws JSONException {
+ String cacheKey = "service";
+ List<CacheEntry> result = parserService.doParse(cacheKey, aaiGetAllServiceResponse);
+ print(result);
+ noneTests(cacheKey, result);
+ }
+
+ @Test
+ public void testNoneStrategyTest2() throws JSONException {
+ String cacheKey = "service";
+ List<CacheEntry> result = parserService.doParse(cacheKey, aaiGetAllServiceResponseJson);
+ print(result);
+ noneTests(cacheKey, result);
+ }
+
+ @Test
+ public void testNoneStrategyTest3() throws JSONException {
+ String cacheKey = "service";
+ List<CacheEntry> result = parserService.doParse(cacheKey, aaiGetAllServiceResponse, PayloadParserType.NONE);
+ print(result);
+ noneTests(cacheKey, result);
+ }
+
+ @Test
+ public void testNoneStrategyTest4() throws JSONException {
+ String cacheKey = "service";
+ List<CacheEntry> result = parserService.doParse(cacheKey, aaiGetAllServiceResponse, "none");
+ print(result);
+ noneTests(cacheKey, result);
+ }
+
+ private void noneTests(String cacheKey, List<CacheEntry> result) throws JSONException {
+ assertThat(result.size(), is(1));
+ assertTrue(result.stream().map(cacheIdentifier -> cacheIdentifier.getId()).anyMatch(id -> id.equals(cacheKey)));
+ JSONAssert.assertEquals(
+ new JSONObject(aaiGetAllServiceResponse),
+ new JSONObject(result.get(0).getPayload().toString()),
+ false);
+ }
+
+
+}
+
diff --git a/src/test/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategyTest.java b/src/test/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategyTest.java
new file mode 100644
index 0000000..8a4ab0b
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategyTest.java
@@ -0,0 +1,429 @@
+/**
+ * ============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.cacher.injestion.parser.strategy;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.json.JSONObject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.aai.cacher.injestion.parser.InjestionTestComponent;
+import org.onap.aai.cacher.injestion.parser.PayloadParserService;
+import org.onap.aai.cacher.model.CacheEntry;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.util.MultiValueMap;
+
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = InjestionTestComponent.class)
+public class AAIResourceDmaapParserStrategyTest {
+
+ @Autowired
+ private PayloadParserService parserService;
+
+ @Autowired
+ @Qualifier("aai-resource-dmaap")
+ private AAIResourceDmaapParserStrategy aaiResourceDmaapParserStrategy;
+
+ private JsonParser parser = new JsonParser();
+
+ private JsonObject pserverCreateEvent = parser.parse(
+ new FileReader("./src/test/resources/test/payloads/dmaap-pserver-create.json")).getAsJsonObject();
+
+ public AAIResourceDmaapParserStrategyTest() throws FileNotFoundException {}
+
+ private void print(List<CacheEntry> result) {
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ result.forEach(e -> System.out.println("\n\nCollection: " + e.getCollection() +
+ "\nKey: " + e.getId() +
+ "\nFind: " + gson.toJson(e.getFindQuery()) +
+ "\nNestedFind: " + gson.toJson(e.getNestedFind()) +
+ "\nNestedField: " + e.getNestedField() +
+ "\nNestedFieldIdentifier: " + gson.toJson(e.getNestedFieldIdentifierObj()) +
+ "\nPayload: " + gson.toJson(e.getPayload())));
+ }
+
+ @Test
+ public void test(){
+ List<CacheEntry> result = parserService.doParse("dmaapEvent", pserverCreateEvent, PayloadParserType.AAI_RESOURCE_DMAAP);
+ print(result);
+ }
+
+
+ @Test
+ public void getUriTest() {
+ String fullUri = aaiResourceDmaapParserStrategy.getFullUri(pserverCreateEvent.getAsJsonObject("event-header"));
+ assertEquals("/aai/v12/cloud-infrastructure/pservers/pserver/dmaap-pserver-create", fullUri);
+ String uri = aaiResourceDmaapParserStrategy.getUri(fullUri);
+ assertEquals("/cloud-infrastructure/pservers/pserver/dmaap-pserver-create", uri);
+ }
+
+ @Test
+ public void getAaiUriSegmentsTest() {
+
+ String uri = "/service-design-and-creation/services/service/id/l-interfaces/l-interface/name/p-interfaces/p-interface/name2";
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+
+ assertEquals("3 segments are generated", 3, segments.size());
+
+ assertEquals("Segment 1 plural is services", "services", segments.get(0).getSegmentPlural().get());
+ assertEquals("Segment 2 plural is l-interfaces", "l-interfaces", segments.get(1).getSegmentPlural().get());
+ assertEquals("Segment 3 plural is p-interfaces", "p-interfaces", segments.get(2).getSegmentPlural().get());
+
+ assertEquals("Segment 1 singular is service", "service", segments.get(0).getSegmentSingular());
+ assertEquals("Segment 2 singular is l-interface", "l-interface", segments.get(1).getSegmentSingular());
+ assertEquals("Segment 3 singular is p-interface", "p-interface", segments.get(2).getSegmentSingular());
+
+ assertEquals("Segment 1 template",
+ "/service-design-and-creation/services/service/{service-id}",
+ segments.get(0).getSegmentTemplate());
+ assertEquals("Segment 2 template",
+ "/l-interfaces/l-interface/{interface-name}",
+ segments.get(1).getSegmentTemplate());
+ assertEquals("Segment 3 template",
+ "/p-interfaces/p-interface/{interface-name}",
+ segments.get(2).getSegmentTemplate());
+
+ assertEquals("Segment 1 uri",
+ "/service-design-and-creation/services/service/id",
+ segments.get(0).getSegment());
+ assertEquals("Segment 2 uri",
+ "/l-interfaces/l-interface/name",
+ segments.get(1).getSegment());
+ assertEquals("Segment 3 uri",
+ "/p-interfaces/p-interface/name2",
+ segments.get(2).getSegment());
+
+ Map<String, String> expected = new HashMap<>();
+ expected.put("service-id", "id");
+ assertEquals("Segment 1 mapping", expected, segments.get(0).getSegmentKeyValues());
+ expected = new HashMap<>();
+ expected.put("interface-name", "name");
+ assertEquals("Segment 2 mapping", expected, segments.get(1).getSegmentKeyValues());
+ expected = new HashMap<>();
+ expected.put("interface-name", "name2");
+ assertEquals("Segment 3 mapping", expected, segments.get(2).getSegmentKeyValues());
+ }
+
+ @Test
+ public void getEntityBodyChildTest() throws Exception {
+ String uri = "/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/ams1b/tenants/tenant/52fd05137ab4453bb53084a13c7bb7a4/vservers/vserver/vs-id";
+ String entityString =
+ "{" +
+ " 'tenants':" +
+ " {" +
+ " 'tenant': [" +
+ " {" +
+ " 'vservers':" +
+ " {" +
+ " 'vserver': [" +
+ " {" +
+ " 'in-maint': false," +
+ " 'resource-version': '1525978690717'," +
+ " 'vserver-name': 'slaa-regression-cr-id-api-server-449704329'," +
+ " 'vserver-id': 'vs-id'" +
+ " }" +
+ " ]" +
+ " }," +
+ " 'tenant-id': 'ten-id'," +
+ " 'tenant-name': 'name'" +
+ " }" +
+ " ]" +
+ " }," +
+ " 'cloud-owner': 'cr-o'," +
+ " 'owner-defined-type': 'lcp'," +
+ " 'cloud-region-id': 'cr-id'" +
+ "}";
+
+ JsonObject entity = parser.parse(entityString).getAsJsonObject();
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+
+ JsonObject result = aaiResourceDmaapParserStrategy.getEntityBody(entity, segments);
+
+ JSONAssert.assertEquals(
+ new JSONObject(entity
+ .getAsJsonObject("tenants").getAsJsonArray("tenant").get(0) .getAsJsonObject()
+ .getAsJsonObject("vservers").getAsJsonArray("vserver").get(0).getAsJsonObject()
+ .toString()),
+ new JSONObject(result.toString()),
+ true);
+
+ }
+
+ @Test
+ public void getEntityBodyTopTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn";
+ String entityString = "{'hostname':'hn','in-maint':false,'resource-version':'1525801811662','pserver-id':'0A47B945-9C74-4CBE-AD72-0DECB966EB94'}";
+
+ JsonObject entity = parser.parse(entityString).getAsJsonObject();
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+
+ JsonObject result = aaiResourceDmaapParserStrategy.getEntityBody(entity, segments);
+
+ JSONAssert.assertEquals(
+ new JSONObject(entity.toString()),
+ new JSONObject(result.toString()),
+ true);
+
+ }
+
+ @Test
+ public void getFindQueryTopTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn";
+ JsonObject expected = parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/hn'," +
+ "'hostname':'hn'}").getAsJsonObject();
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ JsonObject findQuery = aaiResourceDmaapParserStrategy.getFindQuery(segments);
+
+ JSONAssert.assertEquals(
+ new JSONObject(expected.toString()),
+ new JSONObject(findQuery.toString()),
+ true);
+ }
+
+ @Test
+ public void getFindQueryOneLevelTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn/p-interfaces/p-interface/interface-1";
+ JsonObject expected = parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/hn'," +
+ "'hostname':'hn'}").getAsJsonObject();
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ JsonObject findQuery = aaiResourceDmaapParserStrategy.getFindQuery(segments);
+
+ JSONAssert.assertEquals(
+ new JSONObject(expected.toString()),
+ new JSONObject(findQuery.toString()),
+ true);
+ }
+
+ @Test
+ public void getFindQueryTwoLevelTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn/p-interfaces/p-interface/interface-1/l-interfaces/l-interface/interface-2";
+ JsonObject expected = parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/hn'," +
+ "'hostname':'hn'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'}").getAsJsonObject();
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ JsonObject findQuery = aaiResourceDmaapParserStrategy.getFindQuery(segments);
+
+ JSONAssert.assertEquals(
+ new JSONObject(expected.toString()),
+ new JSONObject(findQuery.toString()),
+ true);
+ }
+
+ @Test
+ public void getNestedFindQueryTopTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn";
+ JsonObject expected = parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/hn'," +
+ "'hostname':'hn'}").getAsJsonObject();
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ JsonObject findQuery = aaiResourceDmaapParserStrategy.getNestedFindQuery(segments);
+
+ JSONAssert.assertEquals(
+ new JSONObject(expected.toString()),
+ new JSONObject(findQuery.toString()),
+ true);
+ }
+
+ @Test
+ public void getNestedFindQueryOneLevelTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn/p-interfaces/p-interface/interface-1";
+ JsonObject expected = parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/hn'," +
+ "'hostname':'hn'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'}").getAsJsonObject();
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ JsonObject findQuery = aaiResourceDmaapParserStrategy.getNestedFindQuery(segments);
+
+ JSONAssert.assertEquals(
+ new JSONObject(expected.toString()),
+ new JSONObject(findQuery.toString()),
+ true);
+ }
+
+ @Test
+ public void getNestedFindQueryTwoLevelTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn/p-interfaces/p-interface/interface-1/l-interfaces/l-interface/interface-2";
+ JsonObject expected = parser.parse("{'_id':'/cloud-infrastructure/pservers/pserver/hn'," +
+ "'hostname':'hn'," +
+ "'p-interfaces.p-interface.interface-name':'interface-1'," +
+ "'p-interfaces.p-interface.l-interfaces.l-interface.interface-name':'interface-2'}").getAsJsonObject();
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ JsonObject findQuery = aaiResourceDmaapParserStrategy.getNestedFindQuery(segments);
+
+ JSONAssert.assertEquals(
+ new JSONObject(expected.toString()),
+ new JSONObject(findQuery.toString()),
+ true);
+ }
+
+ @Test
+ public void getNestedFieldTopTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn";
+ String expected = "";
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ String nestedField = aaiResourceDmaapParserStrategy.getNestedField(segments);
+
+ assertEquals("Top nested field", expected, nestedField);
+ }
+
+ @Test
+ public void getNestedFieldOneLevelTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn/p-interfaces/p-interface/interface-1";
+ String expected = "p-interfaces.p-interface";
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ String nestedField = aaiResourceDmaapParserStrategy.getNestedField(segments);
+
+ assertEquals("Top nested field", expected, nestedField);
+ }
+
+ @Test
+ public void getNestedFieldTwoLevelTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn/p-interfaces/p-interface/interface-1/l-interfaces/l-interface/interface-2";
+ String expected = "p-interfaces.p-interface.$.l-interfaces.l-interface";
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ String nestedField = aaiResourceDmaapParserStrategy.getNestedField(segments);
+
+ assertEquals("Top nested field", expected, nestedField);
+ }
+
+ @Test
+ public void getNestedFieldThreeLevelOddCaseTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn/p-interfaces/p-interface/interface-1/l-interfaces/l-interface/interface-2/l3-interface-ipv4-address-list/addressA";
+ String expected = "p-interfaces.p-interface.$.l-interfaces.l-interface.$.l3-interface-ipv4-address-list";
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ String nestedField = aaiResourceDmaapParserStrategy.getNestedField(segments);
+
+ assertEquals("Top nested field", expected, nestedField);
+ }
+
+
+
+
+ @Test
+ public void getNestedIdentifierTopTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn";
+ JsonObject expected = parser.parse("{}").getAsJsonObject();
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ JsonObject nestedIdentifier = aaiResourceDmaapParserStrategy.getNestedIdentifier(segments);
+
+ JSONAssert.assertEquals(
+ new JSONObject(expected.toString()),
+ new JSONObject(nestedIdentifier.toString()),
+ true);
+ }
+
+ @Test
+ public void getNestedIdentifierOneLevelTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn/p-interfaces/p-interface/interface-1";
+ JsonObject expected = parser.parse("{'interface-name':'interface-1'}").getAsJsonObject();
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ JsonObject nestedIdentifier = aaiResourceDmaapParserStrategy.getNestedIdentifier(segments);
+
+ JSONAssert.assertEquals(
+ new JSONObject(expected.toString()),
+ new JSONObject(nestedIdentifier.toString()),
+ true);
+ }
+
+ @Test
+ public void getNestedIdentifierTwoLevelTest() throws Exception {
+ String uri = "/cloud-infrastructure/pservers/pserver/hn/p-interfaces/p-interface/interface-1/l-interfaces/l-interface/interface-2";
+ JsonObject expected = parser.parse("{'interface-name':'interface-2'}").getAsJsonObject();
+
+ List<AAIResourceDmaapParserStrategy.AAIUriSegment> segments = aaiResourceDmaapParserStrategy.getAaiUriSegments(uri);
+ JsonObject nestedIdentifier = aaiResourceDmaapParserStrategy.getNestedIdentifier(segments);
+
+ JSONAssert.assertEquals(
+ new JSONObject(expected.toString()),
+ new JSONObject(nestedIdentifier.toString()),
+ true);
+ }
+
+
+ @Test
+ public void getFullUriPrefixTest() throws Exception {
+ assertEquals("/aai/v12", aaiResourceDmaapParserStrategy.getFullUriPrefix("/aai/v12/network/pnfs/pnf/pnf-name-value/p-interfaces/p-interface/xe-10%2F3%2F2/l-interfaces/l-interface/l-interface-name"));
+ assertEquals("/aai/v4", aaiResourceDmaapParserStrategy.getFullUriPrefix("/aai/v4/names"));
+ }
+
+
+ @Test
+ public void fullUriToRelationshipObj() throws Exception {
+ String fullUri = AAIResourceDmaapParserStrategyTestConstants.VSERVER_URI;
+ String expectedRelObj = AAIResourceDmaapParserStrategyTestConstants.VSERVER_RELATIONSHIP_OBJ;
+ JsonObject relObj = aaiResourceDmaapParserStrategy.fullUriToRelationshipObj(fullUri, "tosca.relationships.HostedOn");
+
+ JSONAssert.assertEquals(new JSONObject(expectedRelObj), new JSONObject(relObj.toString()), true);
+ }
+
+ @Test
+ public void verifyRelationshipEntriesOnUpdateTest() throws Exception {
+ List<CacheEntry> result = aaiResourceDmaapParserStrategy
+ .process("TEST", parser.parse(AAIResourceDmaapParserStrategyTestConstants.GENERIC_VNF_EVENT_WITH_2_RELAT).getAsJsonObject());
+
+ assertEquals(3, result.size());
+
+ }
+ @Test
+ public void verifyRelationshipEntriesSimpleEvent() throws Exception {
+ List<CacheEntry> result = aaiResourceDmaapParserStrategy
+ .process("TEST", parser.parse(AAIResourceDmaapParserStrategyTestConstants.GENERIC_VNF_EVENT).getAsJsonObject());
+
+ assertEquals(1, result.size());
+
+ }
+
+ @Test
+ public void getFromRelationshipFullUriToRelationshipObjTest() throws Exception {
+ String entity = AAIResourceDmaapParserStrategyTestConstants.FULL_PSERVER;
+ String fullUri = AAIResourceDmaapParserStrategyTestConstants.FULL_PSERVER_URI;
+ MultiValueMap<String, AAIResourceDmaapParserStrategy.AAIRelatedToDetails> result = aaiResourceDmaapParserStrategy.getFromRelationshipFullUriToRelationshipObj(parser.parse(entity).getAsJsonObject(), fullUri);
+
+ assertEquals(3, result.size());
+
+ }
+} \ No newline at end of file
diff --git a/src/test/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategyTestConstants.java b/src/test/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategyTestConstants.java
new file mode 100644
index 0000000..659c881
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/injestion/parser/strategy/AAIResourceDmaapParserStrategyTestConstants.java
@@ -0,0 +1,372 @@
+/**
+ * ============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.cacher.injestion.parser.strategy;
+
+public class AAIResourceDmaapParserStrategyTestConstants {
+
+ public static final String VSERVER_URI = "/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/AAIAIC25/tenants/tenant/SERVERNAME%3A%3AXXXX/vservers/vserver/afce2113-297a-436c-811a-acf9981fff68";
+ public static final String VSERVER_RELATIONSHIP_OBJ = "{" +
+ " 'related-to': 'vserver'," +
+ " 'relationship-label': 'tosca.relationships.HostedOn'," +
+ " 'related-link': '/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/AAIAIC25/tenants/tenant/SERVERNAME%3A%3AXXXX/vservers/vserver/afce2113-297a-436c-811a-acf9981fff68'," +
+ " 'relationship-data': [" +
+ " {" +
+ " 'relationship-key': 'cloud-region.cloud-owner'," +
+ " 'relationship-value': 'onap-cloud-owner'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'cloud-region.cloud-region-id'," +
+ " 'relationship-value': 'AAIAIC25'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'tenant.tenant-id'," +
+ " 'relationship-value': 'SERVERNAME::XXXX'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'vserver.vserver-id'," +
+ " 'relationship-value': 'afce2113-297a-436c-811a-acf9981fff68'" +
+ " }" +
+ " ]" +
+ "}";
+
+ public static final String FULL_PSERVER_URI = "/aai/v12/cloud-infrastructure/pservers/pserver/SERVERNAME";
+ public static final String FULL_PSERVER = "{" +
+ " 'hostname': 'SERVERNAME'," +
+ " 'relationship-list':" +
+ " {" +
+ " 'relationship': [" +
+ " {" +
+ " 'related-to': 'generic-vnf'," +
+ " 'relationship-label': 'tosca.relationships.HostedOn'," +
+ " 'related-link': '/aai/v12/network/generic-vnfs/generic-vnf/205c64eb-88b1-490a-a838-b0080e6902bc'," +
+ " 'relationship-data': [" +
+ " {" +
+ " 'relationship-key': 'generic-vnf.vnf-id'," +
+ " 'relationship-value': '205c64eb-88b1-490a-a838-b0080e6902bc'" +
+ " }" +
+ " ]," +
+ " 'related-to-property': [" +
+ " {" +
+ " 'property-key': 'generic-vnf.vnf-name'," +
+ " 'property-value': 'USAUTOUFTIL2001UJDM02'" +
+ " }" +
+ " ]" +
+ " }," +
+ " {" +
+ " 'related-to': 'vserver'," +
+ " 'relationship-label': 'tosca.relationships.HostedOn'," +
+ " 'related-link': '/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/AAIAIC25/tenants/tenant/SERVERNAME%3A%3AXXXX/vservers/vserver/74a47c2c-b53f-4264-87fc-bb85c7f49207'," +
+ " 'relationship-data': [" +
+ " {" +
+ " 'relationship-key': 'cloud-region.cloud-owner'," +
+ " 'relationship-value': 'onap-cloud-owner'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'cloud-region.cloud-region-id'," +
+ " 'relationship-value': 'AAIAIC25'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'tenant.tenant-id'," +
+ " 'relationship-value': 'SERVERNAME::XXXX'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'vserver.vserver-id'," +
+ " 'relationship-value': '74a47c2c-b53f-4264-87fc-bb85c7f49207'" +
+ " }" +
+ " ]," +
+ " 'related-to-property': [" +
+ " {" +
+ " 'property-key': 'vserver.vserver-name'," +
+ " 'property-value': 'SERVERNAME-USAUTOUFTIL2001UJTE03'" +
+ " }" +
+ " ]" +
+ " }," +
+ " {" +
+ " 'related-to': 'vserver'," +
+ " 'relationship-label': 'tosca.relationships.HostedOn'," +
+ " 'related-link': '/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/AAIAIC25/tenants/tenant/SERVERNAME%3A%3AXXXX/vservers/vserver/afce2113-297a-436c-811a-acf9981fff68'," +
+ " 'relationship-data': [" +
+ " {" +
+ " 'relationship-key': 'cloud-region.cloud-owner'," +
+ " 'relationship-value': 'onap-cloud-owner'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'cloud-region.cloud-region-id'," +
+ " 'relationship-value': 'AAIAIC25'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'tenant.tenant-id'," +
+ " 'relationship-value': 'SERVERNAME::XXXX'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'vserver.vserver-id'," +
+ " 'relationship-value': 'afce2113-297a-436c-811a-acf9981fff68'" +
+ " }" +
+ " ]," +
+ " 'related-to-property': [" +
+ " {" +
+ " 'property-key': 'vserver.vserver-name'," +
+ " 'property-value': 'SERVERNAME-vjunos0'" +
+ " }" +
+ " ]" +
+ " }," +
+ " {" +
+ " 'related-to': 'complex'," +
+ " 'relationship-label': 'org.onap.relationships.inventory.LocatedIn'," +
+ " 'related-link': '/aai/v12/cloud-infrastructure/complexes/complex/STLSMO0914'," +
+ " 'relationship-data': [" +
+ " {" +
+ " 'relationship-key': 'complex.physical-location-id'," +
+ " 'relationship-value': 'STLSMO0914'" +
+ " }" +
+ " ]" +
+ " }" +
+ " ]" +
+ " }," +
+ " 'p-interfaces':" +
+ " {" +
+ " 'p-interface': [" +
+ " {" +
+ " 'interface-name': 'ge-0/0/10'," +
+ " 'relationship-list':" +
+ " {" +
+ " 'relationship': [" +
+ " {" +
+ " 'related-to': 'physical-link'," +
+ " 'relationship-label': 'tosca.relationships.network.LinksTo'," +
+ " 'related-link': '/aai/v12/network/physical-links/physical-link/HIS.1702.03053.121'," +
+ " 'relationship-data': [" +
+ " {" +
+ " 'relationship-key': 'physical-link.link-name'," +
+ " 'relationship-value': 'HIS.1702.03053.121'" +
+ " }" +
+ " ]" +
+ " }" +
+ " ]" +
+ " }" +
+ " }," +
+ " {" +
+ " 'interface-name': 'ge-0/0/11'," +
+ " 'relationship-list':" +
+ " {" +
+ " 'relationship': [" +
+ " {" +
+ " 'related-to': 'physical-link'," +
+ " 'relationship-label': 'tosca.relationships.network.LinksTo'," +
+ " 'related-link': '/aai/v12/network/physical-links/physical-link/HIS.1702.03053.122'," +
+ " 'relationship-data': [" +
+ " {" +
+ " 'relationship-key': 'physical-link.link-name'," +
+ " 'relationship-value': 'HIS.1702.03053.122'" +
+ " }" +
+ " ]" +
+ " }" +
+ " ]" +
+ " }" +
+ " }" +
+ " ]" +
+ " }" +
+ "}";
+
+
+ public final static String GENERIC_VNF_EVENT_WITH_2_RELAT = "{" +
+ " 'cambria.partition': 'AAI'," +
+ " 'event-header':" +
+ " {" +
+ " 'severity': 'NORMAL'," +
+ " 'entity-type': 'generic-vnf'," +
+ " 'top-entity-type': 'generic-vnf'," +
+ " 'entity-link': '/aai/v13/network/generic-vnfs/generic-vnf/cc1703a9-a63f-46c5-a6b1-7ff67f3a9848'," +
+ " 'event-type': 'AAI-EVENT'," +
+ " 'domain': 'e2e1'," +
+ " 'action': 'UPDATE'," +
+ " 'sequence-number': '0'," +
+ " 'id': '35717064-c145-4172-941a-ae71dced750e'," +
+ " 'version': 'v12'," +
+ " 'timestamp': '20180523-15:41:19:570'" +
+ " }," +
+ " 'entity':" +
+ " {" +
+ " 'vnf-id': 'cc1703a9-a63f-46c5-a6b1-7ff67f3a9848'," +
+ " 'vf-modules':" +
+ " {" +
+ " 'vf-module': [" +
+ " {" +
+ " 'vf-module-id': 'eb792c93-d7e6-481c-8a78-e63d39f63e3a'" +
+ " }," +
+ " {" +
+ " 'vf-module-id': '43448d88-099f-4a33-8860-889773440675'" +
+ " }" +
+ " ]" +
+ " }," +
+ " 'relationship-list':" +
+ " {" +
+ " 'relationship': [" +
+ " {" +
+ " 'related-to': 'service-instance'," +
+ " 'relationship-label': 'org.onap.relationships.inventory.ComposedOf'," +
+ " 'related-link': '/aai/v13/business/customers/customer/1702_IT3_SubscGblID_20170426162928/service-subscriptions/service-subscription/XXXX-VMS/service-instances/service-instance/SERVERNAME'," +
+ " 'relationship-data': [" +
+ " {" +
+ " 'relationship-key': 'customer.global-customer-id'," +
+ " 'relationship-value': '1702_IT3_SubscGblID_20170426162928'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'service-subscription.service-type'," +
+ " 'relationship-value': 'XXXX-VMS'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'service-instance.service-instance-id'," +
+ " 'relationship-value': 'SERVERNAME'" +
+ " }" +
+ " ]," +
+ " 'related-to-property': [" +
+ " {" +
+ " 'property-key': 'service-instance.service-instance-name'" +
+ " }" +
+ " ]" +
+ " }," +
+ " {" +
+ " 'related-to': 'vserver'," +
+ " 'relationship-label': 'tosca.relationships.HostedOn'," +
+ " 'related-link': '/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/AAIAIC25/tenants/tenant/SERVERNAME%3A%3AXXXX-VMS/vservers/vserver/e77451f2-1c07-4db4-b92b-9907b840fc8f'," +
+ " 'relationship-data': [" +
+ " {" +
+ " 'relationship-key': 'cloud-region.cloud-owner'," +
+ " 'relationship-value': 'onap-cloud-owner'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'cloud-region.cloud-region-id'," +
+ " 'relationship-value': 'AAIAIC25'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'tenant.tenant-id'," +
+ " 'relationship-value': 'SERVERNAME::XXXX-VMS'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'vserver.vserver-id'," +
+ " 'relationship-value': 'e77451f2-1c07-4db4-b92b-9907b840fc8f'" +
+ " }" +
+ " ]," +
+ " 'related-to-property': [" +
+ " {" +
+ " 'property-key': 'vserver.vserver-name'," +
+ " 'property-value': 'SERVERNAME-vsrx'" +
+ " }" +
+ " ]" +
+ " }" +
+ " ]" +
+ " }" +
+ " }," +
+ " 'existing-obj':" +
+ " {" +
+ " 'vnf-id': 'cc1703a9-a63f-46c5-a6b1-7ff67f3a9848'," +
+ " 'vf-modules':" +
+ " {" +
+ " 'vf-module': [" +
+ " {" +
+ " 'vf-module-id': 'eb792c93-d7e6-481c-8a78-e63d39f63e3a'" +
+ " }," +
+ " {" +
+ " 'vf-module-id': '43448d88-099f-4a33-8860-889773440675'," +
+ " 'relationship-list':" +
+ " {" +
+ " 'relationship': [" +
+ " {" +
+ " 'related-to': 'l3-network'," +
+ " 'relationship-data': [" +
+ " {" +
+ " 'relationship-value': '91eae07d-6f38-4fd8-b929-e7c04614c8c3'," +
+ " 'relationship-key': 'l3-network.network-id'" +
+ " }" +
+ " ]," +
+ " 'related-link': '/aai/v13/network/l3-networks/l3-network/91eae07d-6f38-4fd8-b929-e7c04614c8c3'," +
+ " 'relationship-label': 'org.onap.relationships.inventory.Uses'," +
+ " 'related-to-property': [" +
+ " {" +
+ " 'property-key': 'l3-network.network-name'," +
+ " 'property-value': 'ADIODvPE-24388-T-E2E-001_int_AdiodVpeTenantOamNetwork.vpeNodMisOam_net_2'" +
+ " }" +
+ " ]" +
+ " }" +
+ " ]" +
+ " }" +
+ " }" +
+ " ]" +
+ " }," +
+ " 'relationship-list':" +
+ " {" +
+ " 'relationship': [" +
+ " {" +
+ " 'related-to': 'vserver'," +
+ " 'relationship-label': 'tosca.relationships.HostedOn'," +
+ " 'related-link': '/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/AAIAIC25/tenants/tenant/SERVERNAME%3A%3AXXXX-VMS/vservers/vserver/e77451f2-1c07-4db4-b92b-9907b840fc8f'," +
+ " 'relationship-data': [" +
+ " {" +
+ " 'relationship-key': 'cloud-region.cloud-owner'," +
+ " 'relationship-value': 'onap-cloud-owner'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'cloud-region.cloud-region-id'," +
+ " 'relationship-value': 'AAIAIC25'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'tenant.tenant-id'," +
+ " 'relationship-value': 'SERVERNAME::XXXX-VMS'" +
+ " }," +
+ " {" +
+ " 'relationship-key': 'vserver.vserver-id'," +
+ " 'relationship-value': 'e77451f2-1c07-4db4-b92b-9907b840fc8f'" +
+ " }" +
+ " ]," +
+ " 'related-to-property': [" +
+ " {" +
+ " 'property-key': 'vserver.vserver-name'," +
+ " 'property-value': 'SERVERNAME-vsrx'" +
+ " }" +
+ " ]" +
+ " }" +
+ " ]" +
+ " }" +
+ " }" +
+ "}";
+
+ public final static String GENERIC_VNF_EVENT = "{" +
+ " 'cambria.partition': 'AAI'," +
+ " 'event-header':" +
+ " {" +
+ " 'severity': 'NORMAL'," +
+ " 'entity-type': 'generic-vnf'," +
+ " 'top-entity-type': 'generic-vnf'," +
+ " 'entity-link': '/aai/v13/network/generic-vnfs/generic-vnf/cc1703a9-a63f-46c5-a6b1-7ff67f3a9848'," +
+ " 'event-type': 'AAI-EVENT'," +
+ " 'domain': 'e2e1'," +
+ " 'action': 'UPDATE'," +
+ " 'sequence-number': '0'," +
+ " 'id': '35717064-c145-4172-941a-ae71dced750e'," +
+ " 'version': 'v12'," +
+ " 'timestamp': '20180523-15:41:19:570'" +
+ " }," +
+ " 'entity':" +
+ " {" +
+ " 'vnf-id': 'cc1703a9-a63f-46c5-a6b1-7ff67f3a9848'" +
+ " }" +
+ "}";
+}
diff --git a/src/test/java/org/onap/aai/cacher/model/CacheKeyTest.java b/src/test/java/org/onap/aai/cacher/model/CacheKeyTest.java
new file mode 100644
index 0000000..19a3b3b
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/model/CacheKeyTest.java
@@ -0,0 +1,169 @@
+/**
+ * ============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.cacher.model;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class CacheKeyTest {
+
+ public String inputGETOnInit = "{" +
+ "'cacheKey': 'cloud-region'," +
+ "'baseUrl': 'http://localhost:8447'," +
+ "'module': '/aai/v13/'," +
+ "'URI': 'cloud-infrastructure/cloud-regions?depth=0&resultIndex=1&resultSize=3'," +
+ "'timingIndicator': 'onInit'," +
+ "'httpMethod': 'GET'}";
+
+ public String inputGETFirstHitDefault = "{" +
+ "'cacheKey': 'cloud-region'," +
+ "'baseUrl': 'http://localhost:8447'," +
+ "'module': '/aai/v13/'," +
+ "'URI': 'cloud-infrastructure/cloud-regions?depth=0&resultIndex=1&resultSize=3'}";
+
+ public String inputGETScheduledDefault = "{" +
+ "'cacheKey': 'cloud-region'," +
+ "'baseUrl': 'http://localhost:8447'," +
+ "'module': '/aai/v13/'," +
+ "'timingIndicator': 'scheduled'," +
+ "'URI': 'cloud-infrastructure/cloud-regions?depth=0&resultIndex=1&resultSize=3'}";
+
+ public String inputGETScheduledWithSyncInterval = "{" +
+ "'cacheKey': 'cloud-region'," +
+ "'baseUrl': 'http://localhost:8447'," +
+ "'module': '/aai/v13/'," +
+ "'syncInterval': '2'," +
+ "'timingIndicator': 'scheduled'," +
+ "'URI': 'cloud-infrastructure/cloud-regions?depth=0&resultIndex=1&resultSize=3'}";
+
+ public String inputGETScheduledWithSyncIntervalWithId = "{" +
+ "'_id': 'cloud-region'," +
+ "'baseUrl': 'http://localhost:8447'," +
+ "'module': '/aai/v13/'," +
+ "'syncInterval': '2'," +
+ "'timingIndicator': 'scheduled'," +
+ "'URI': 'cloud-infrastructure/cloud-regions?depth=0&resultIndex=1&resultSize=3'}";
+
+
+ @Test
+ public void testCacheKeyObjectGETOnInit() {
+ JsonParser parser = new JsonParser();
+ JsonObject ckJson = (JsonObject) parser.parse(inputGETOnInit);
+ CacheKey ck = CacheKey.fromJson(ckJson);
+ assertEquals("cacheKey was incorrect", "cloud-region", ck.getCacheKey());
+ assertEquals("baseUrl was incorrect", "http://localhost:8447", ck.getBaseUrl());
+ assertEquals("Module was incorrect", "/aai/v13/", ck.getModule());
+ assertEquals("URI was incorrect", "cloud-infrastructure/cloud-regions?depth=0&resultIndex=1&resultSize=3", ck.getURI());
+ assertEquals("timingIndicator was incorrect", "onInit", ck.getTimingIndicator());
+ assertEquals("Http Method was incorrect", "GET", ck.getHttpMethod());
+ assertEquals("Http Body was incorrect", "-1", ck.getHttpBody());
+ assertEquals("Sync Interval was incorrect", "-1", ck.getSyncInterval());
+ assertEquals("Last Sync Start Time was incorrect", "-1", ck.getLastSyncStartTime());
+ assertEquals("Last Sync Success Time was incorrect", "-1", ck.getLastSyncSuccessTime());
+ }
+
+ @Test
+ public void testCacheKeyObjectGETFirstHitDefault() {
+ JsonParser parser = new JsonParser();
+ JsonObject ckJson = (JsonObject) parser.parse(inputGETFirstHitDefault);
+ CacheKey ck = CacheKey.fromJson(ckJson);
+ assertEquals("cacheKey was incorrect", "cloud-region", ck.getCacheKey());
+ assertEquals("baseUrl was incorrect", "http://localhost:8447", ck.getBaseUrl());
+ assertEquals("Module was incorrect", "/aai/v13/", ck.getModule());
+ assertEquals("URI was incorrect", "cloud-infrastructure/cloud-regions?depth=0&resultIndex=1&resultSize=3", ck.getURI());
+ assertEquals("timingIndicator was incorrect", "firstHit", ck.getTimingIndicator());
+ assertEquals("Http Method was incorrect", "GET", ck.getHttpMethod());
+ assertEquals("Http Body was incorrect", "-1", ck.getHttpBody());
+ assertEquals("Sync Interval was incorrect", "-1", ck.getSyncInterval());
+ assertEquals("Last Sync Start Time was incorrect", "-1", ck.getLastSyncStartTime());
+ assertEquals("Last Sync Success Time was incorrect", "-1", ck.getLastSyncSuccessTime());
+ }
+
+ @Test
+ public void testCacheKeyObjectDefaults() {
+ JsonParser parser = new JsonParser();
+ JsonObject ckJson = (JsonObject) parser.parse("{}");
+ CacheKey ck = CacheKey.fromJson(ckJson);
+ assertEquals("cacheKey was incorrect", "-1", ck.getCacheKey());
+ assertEquals("baseUrl was incorrect", "-1", ck.getBaseUrl());
+ assertEquals("Module was incorrect", "-1", ck.getModule());
+ assertEquals("URI was incorrect", "-1", ck.getURI());
+ assertEquals("timingIndicator was incorrect", "firstHit", ck.getTimingIndicator());
+ assertEquals("Http Method was incorrect", "GET", ck.getHttpMethod());
+ assertEquals("Http Body was incorrect", "-1", ck.getHttpBody());
+ assertEquals("Sync Interval was incorrect", "-1", ck.getSyncInterval());
+ assertEquals("Last Sync Start Time was incorrect", "-1", ck.getLastSyncStartTime());
+ assertEquals("Last Sync Success Time was incorrect", "-1", ck.getLastSyncSuccessTime());
+ }
+
+ @Test
+ public void testCacheKeyObjectGETScheduled() {
+ JsonParser parser = new JsonParser();
+ JsonObject ckJson = (JsonObject) parser.parse(inputGETScheduledDefault);
+ CacheKey ck = CacheKey.fromJson(ckJson);
+ assertEquals("cacheKey was incorrect", "cloud-region", ck.getCacheKey());
+ assertEquals("baseUrl was incorrect", "http://localhost:8447", ck.getBaseUrl());
+ assertEquals("Module was incorrect", "/aai/v13/", ck.getModule());
+ assertEquals("URI was incorrect", "cloud-infrastructure/cloud-regions?depth=0&resultIndex=1&resultSize=3", ck.getURI());
+ assertEquals("timingIndicator was incorrect", "scheduled", ck.getTimingIndicator());
+ assertEquals("Http Method was incorrect", "GET", ck.getHttpMethod());
+ assertEquals("Http Body was incorrect", "-1", ck.getHttpBody());
+ assertEquals("Sync Interval was incorrect", "1440", ck.getSyncInterval());
+ assertEquals("Last Sync Start Time was incorrect", "-1", ck.getLastSyncStartTime());
+ assertEquals("Last Sync Success Time was incorrect", "-1", ck.getLastSyncSuccessTime());
+ }
+
+ @Test
+ public void testCacheKeyObjectGETScheduledWithSyncInterval() {
+ JsonParser parser = new JsonParser();
+ JsonObject ckJson = (JsonObject) parser.parse(inputGETScheduledWithSyncInterval);
+ CacheKey ck = CacheKey.fromJson(ckJson);
+ assertEquals("cacheKey was incorrect", "cloud-region", ck.getCacheKey());
+ assertEquals("baseUrl was incorrect", "http://localhost:8447", ck.getBaseUrl());
+ assertEquals("Module was incorrect", "/aai/v13/", ck.getModule());
+ assertEquals("URI was incorrect", "cloud-infrastructure/cloud-regions?depth=0&resultIndex=1&resultSize=3", ck.getURI());
+ assertEquals("timingIndicator was incorrect", "scheduled", ck.getTimingIndicator());
+ assertEquals("Http Method was incorrect", "GET", ck.getHttpMethod());
+ assertEquals("Http Body was incorrect", "-1", ck.getHttpBody());
+ assertEquals("Sync Interval was incorrect", "2", ck.getSyncInterval());
+ assertEquals("Last Sync Start Time was incorrect", "-1", ck.getLastSyncStartTime());
+ assertEquals("Last Sync Success Time was incorrect", "-1", ck.getLastSyncSuccessTime());
+ }
+
+ @Test
+ public void testCacheKeyObjectGETScheduledWithSyncIntervalWithId() {
+ JsonParser parser = new JsonParser();
+ JsonObject ckJson = (JsonObject) parser.parse(inputGETScheduledWithSyncIntervalWithId);
+ CacheKey ck = CacheKey.fromJson(ckJson);
+ assertEquals("cacheKey was incorrect", "cloud-region", ck.getCacheKey());
+ assertEquals("baseUrl was incorrect", "http://localhost:8447", ck.getBaseUrl());
+ assertEquals("Module was incorrect", "/aai/v13/", ck.getModule());
+ assertEquals("URI was incorrect", "cloud-infrastructure/cloud-regions?depth=0&resultIndex=1&resultSize=3", ck.getURI());
+ assertEquals("timingIndicator was incorrect", "scheduled", ck.getTimingIndicator());
+ assertEquals("Http Method was incorrect", "GET", ck.getHttpMethod());
+ assertEquals("Http Body was incorrect", "-1", ck.getHttpBody());
+ assertEquals("Sync Interval was incorrect", "2", ck.getSyncInterval());
+ assertEquals("Last Sync Start Time was incorrect", "-1", ck.getLastSyncStartTime());
+ assertEquals("Last Sync Success Time was incorrect", "-1", ck.getLastSyncSuccessTime());
+ }
+}
diff --git a/src/test/java/org/onap/aai/cacher/service/helper/CacheHelperServiceScenariosTest.java b/src/test/java/org/onap/aai/cacher/service/helper/CacheHelperServiceScenariosTest.java
new file mode 100644
index 0000000..f4543ad
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/service/helper/CacheHelperServiceScenariosTest.java
@@ -0,0 +1,232 @@
+/**
+ * ============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.cacher.service.helper;
+
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoDatabase;
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodProcess;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.IMongodConfig;
+import de.flapdoodle.embed.mongo.config.MongoCmdOptionsBuilder;
+import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Net;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.process.runtime.Network;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.aai.cacher.common.MongoHelperSingleton;
+import org.onap.aai.cacher.egestion.printer.EgestionTestComponent;
+import org.onap.aai.cacher.injestion.parser.InjestionTestComponent;
+import org.onap.aai.cacher.injestion.parser.strategy.PayloadParserType;
+import org.onap.aai.cacher.model.CacheKey;
+import org.onap.aai.cacher.util.AAIConstants;
+import org.onap.aai.exceptions.AAIException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ws.rs.core.Response;
+
+import static org.junit.Assert.*;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@Configuration
+@ContextConfiguration(classes = {InjestionTestComponent.class, EgestionTestComponent.class, CacheHelperServiceScenariosTest.class})
+public class CacheHelperServiceScenariosTest {
+
+ private String aaiGetAllComplexResponse =
+ "{" +
+ " 'complex': [" +
+ " {" +
+ " 'physical-location-id': 'physical-location-id-1'," +
+ " 'resource-version': '1'" +
+ " }," +
+ " {" +
+ " 'physical-location-id': 'physical-location-id-2'," +
+ " 'resource-version': '2'" +
+ " }" +
+ " ]" +
+ "}";
+
+ private String idForDeleteCache = "/cloud-infrastructure/complexes/complex/physical-location-id-2";
+
+
+ private static final String DB_NAME = CacheHelperServiceScenariosTest.class.getSimpleName();
+ private static MongoDatabase mongoDb;
+ private static RestClientHelperService restClientHelperService;
+ private static DB db;
+ private static MongodProcess mongod;
+ private static MongoClient mongoC;
+
+
+ @Autowired
+ private CacheHelperService cacheHelperService;
+
+ @Bean
+ public DB db() {
+ return db;
+ }
+
+ @Bean
+ public MongoDatabase mongoDatabase() {
+ return mongoDb;
+ }
+
+ @Bean
+ public RestClientHelperService restClientHelperService() {
+ return restClientHelperService;
+ }
+
+ @Bean
+ public MongoHelperSingleton mongoHelperSingleton(DB db, MongoDatabase mongoDb) {
+ return new MongoHelperSingleton(db, mongoDb);
+ }
+
+ @Bean
+ public CacheHelperService cacheHelperService() {
+ return new CacheHelperService();
+ }
+
+ @BeforeClass
+ public static void setup() throws IOException, InterruptedException {
+
+ String bindIp = "localhost";
+ int port = 27017;
+ startEmbedded(port);
+
+ mongoC = new MongoClient(bindIp, port);
+ mongoDb = mongoC.getDatabase(DB_NAME);
+ db = mongoC.getDB(DB_NAME);
+
+ }
+
+ protected static void startEmbedded(int port) throws IOException {
+ IMongodConfig mongoConfigConfig = new MongodConfigBuilder()
+ .version(Version.Main.PRODUCTION)
+ .net(new Net(port, Network.localhostIsIPv6()))
+ .cmdOptions(new MongoCmdOptionsBuilder().verbose(true).build())
+ .configServer(false)
+ .build();
+
+ MongodExecutable mongodExecutable = MongodStarter.getDefaultInstance().prepare(mongoConfigConfig);
+
+ mongod = mongodExecutable.start();
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ if (mongod != null && mongod.isProcessRunning()) {
+ mongod.stop();
+ }
+ }
+
+ @After
+ public void cleanup() {
+ final List<String> collectionNames = new ArrayList<>();
+ mongoDb.listCollections().iterator().forEachRemaining(document -> collectionNames.add(document.getString("name")));
+ collectionNames.forEach(collectionName -> mongoDb.getCollection(collectionName).drop());
+ }
+
+
+ @Test
+ public void cacheKeyProcessingTest() throws Exception {
+
+ CacheKey ck = new CacheKey("complex");
+ cacheHelperService.addCacheKey(ck);
+ Response resp = cacheHelperService.getAllKeys();
+ assertEquals("getAllKeys", 200, resp.getStatus());
+ CacheKey ck1 = new CacheKey("pserver");
+ ck1.timingIndicator = "scheduled";
+ cacheHelperService.addCacheKey(ck1);
+ resp = cacheHelperService.getAllKeys();
+ assertEquals("getAllKeys", 200, resp.getStatus());
+ CacheKey retrieveCk = cacheHelperService.retrieveCacheKeyObject(ck);
+ assertEquals("retrieved cacheKey complex", "complex", retrieveCk.getCacheKey());
+
+ retrieveCk.setParserStrategy(PayloadParserType.AAI_RESOURCE_GET_ALL.toString());
+ cacheHelperService.updateCacheKey(retrieveCk);
+ assertEquals("retrieved cacheKey complex", PayloadParserType.AAI_RESOURCE_GET_ALL.toString(), retrieveCk.getParserStrategy());
+ assertEquals("getScheduledCaches", 1, cacheHelperService.getScheduledCaches().size());
+
+ resp = cacheHelperService.populateCache(retrieveCk, aaiGetAllComplexResponse);
+ assertEquals("populateCache", 201, resp.getStatus());
+ resp = cacheHelperService.getData(retrieveCk);
+ assertEquals("getData", 200, resp.getStatus());
+ resp = cacheHelperService.retrieveCollectionByKey(retrieveCk, AAIConstants.COLLECTION_CACHEKEY);
+ assertEquals("retrieveCollectionByKey", 200, resp.getStatus());
+ resp = cacheHelperService.deleteCache(idForDeleteCache, "complex");
+ assertEquals("deleteCache1", 204, resp.getStatus());
+ resp = cacheHelperService.deleteCache("noSuchId", "complex");
+ assertEquals("deleteCache2", 404, resp.getStatus());
+
+
+ assertTrue("isShouldTrigger1", cacheHelperService.isShouldTrigger(retrieveCk));
+ long current = System.currentTimeMillis();
+ DateFormat formatter = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.SSSZ");
+ String syncStartTime = formatter.format(current - 61000);
+ String syncEndTime = formatter.format(current - 60500);
+ // setup sync in progress
+ retrieveCk.syncInterval = "1";
+ retrieveCk.lastSyncStartTime = syncEndTime;
+ retrieveCk.lastSyncEndTime = syncStartTime;
+ cacheHelperService.updateCacheKey(retrieveCk);
+
+ resp = cacheHelperService.forceSync(retrieveCk);
+ assertEquals("forceSync", 500, resp.getStatus());
+ retrieveCk.lastSyncStartTime = syncStartTime;
+ retrieveCk.lastSyncEndTime = syncEndTime;
+ assertTrue("isShouldTrigger2", cacheHelperService.isShouldTrigger(retrieveCk));
+
+ resp = cacheHelperService.deleteCacheKeyAndAssociatedCache("complex");
+ assertEquals("deleteCacheKeyAndAssociatedCache", 204, resp.getStatus());
+ List<CacheKey> ckList = new ArrayList<CacheKey>();
+ ck = new CacheKey("pnf");
+ ck1 = new CacheKey("logical-link");
+ ckList.add(ck);
+ ckList.add(ck1);
+ assertTrue(cacheHelperService.bulkAddCacheKeys(ckList));
+
+ }
+
+ @Test
+ public void buildResponseTest() throws Exception {
+ List<String> issueList = Arrays.asList("First Issue", "Second Issue");
+ Response resp = cacheHelperService.buildValidationResponse(issueList);
+ assertEquals("buildValidationResponse", 400, resp.getStatus());
+ AAIException ex = new AAIException("AAI_4000");
+ resp = cacheHelperService.buildExceptionResponse(ex);
+ assertEquals("buildExceptionResponse", 500, resp.getStatus());
+
+ }
+}
diff --git a/src/test/java/org/onap/aai/cacher/service/helper/CacheHelperServiceTest.java b/src/test/java/org/onap/aai/cacher/service/helper/CacheHelperServiceTest.java
new file mode 100644
index 0000000..4a2ed94
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/service/helper/CacheHelperServiceTest.java
@@ -0,0 +1,88 @@
+/**
+ * ============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.cacher.service.helper;
+
+import org.junit.Test;
+import org.onap.aai.cacher.model.CacheKey;
+
+import java.text.SimpleDateFormat;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class CacheHelperServiceTest {
+
+ private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.SSSZ");
+
+ @Test
+ public void isShouldTrigger1() throws Exception {
+
+ CacheKey cacheKey = new CacheKey("test");
+ cacheKey.setLastSyncStartTime("-1");
+ cacheKey.setLastSyncEndTime("-1");
+ cacheKey.setLastSyncSuccessTime("-1");
+ cacheKey.setSyncInterval("1");
+
+ CacheHelperService cacheHelperService = new CacheHelperService();
+ assertTrue("No timings set (should trigger)", cacheHelperService.isShouldTrigger(cacheKey));
+ }
+
+ @Test
+ public void isShouldTrigger2() throws Exception {
+
+ CacheKey cacheKey = new CacheKey("test");
+ cacheKey.setLastSyncStartTime(sdf.format(System.currentTimeMillis()-300000)); //5 mins ago
+ cacheKey.setLastSyncEndTime("-1"); // has not ended
+ cacheKey.setLastSyncSuccessTime("-1");
+ cacheKey.setSyncInterval("1"); //1 min interval
+
+ CacheHelperService cacheHelperService = new CacheHelperService();
+ assertFalse("Start time set (should not trigger)", cacheHelperService.isShouldTrigger(cacheKey));
+ }
+
+ @Test
+ public void isShouldTrigger3() throws Exception {
+
+ CacheKey cacheKey = new CacheKey("test");
+ cacheKey.setLastSyncStartTime(sdf.format(System.currentTimeMillis()-300000)); //5 mins ago
+ cacheKey.setLastSyncEndTime(sdf.format(System.currentTimeMillis()-240000)); // 4 mins ago
+ cacheKey.setLastSyncSuccessTime("-1");
+ cacheKey.setSyncInterval("1"); //1 min interval
+
+ CacheHelperService cacheHelperService = new CacheHelperService();
+ assertTrue("Start time less than endtime (should trigger)", cacheHelperService.isShouldTrigger(cacheKey));
+ }
+
+ @Test
+ public void isShouldTrigger4() throws Exception {
+
+ CacheKey cacheKey = new CacheKey("test");
+ cacheKey.setLastSyncStartTime(sdf.format(System.currentTimeMillis()-300000)); //5 mins ago
+ cacheKey.setLastSyncEndTime(sdf.format(System.currentTimeMillis()-360000)); // 6 mins ago
+ cacheKey.setLastSyncSuccessTime("-1");
+ cacheKey.setSyncInterval("1"); //1 min interval
+
+ CacheHelperService cacheHelperService = new CacheHelperService();
+ assertFalse("Start time greater than endtime (should not trigger)", cacheHelperService.isShouldTrigger(cacheKey));
+ }
+
+
+
+} \ No newline at end of file
diff --git a/src/test/java/org/onap/aai/cacher/service/helper/CrudOperationsTest.java b/src/test/java/org/onap/aai/cacher/service/helper/CrudOperationsTest.java
new file mode 100644
index 0000000..1aa1d81
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/service/helper/CrudOperationsTest.java
@@ -0,0 +1,409 @@
+/**
+ * ============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.cacher.service.helper;
+
+import com.github.fakemongo.Fongo;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.FindOneAndUpdateOptions;
+import com.mongodb.client.model.UpdateOptions;
+import org.bson.Document;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class CrudOperationsTest {
+
+ public static final String DB_NAME = "testDb";
+ private static MongoDatabase mongoDatabase;
+
+ @BeforeClass
+ public static void setup() {
+ Fongo fongo = new Fongo(DB_NAME);
+ mongoDatabase = fongo.getDatabase(DB_NAME);
+ }
+
+ @Test
+ public void insertOrUpdateObjInCollection() {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ mongoDatabase.createCollection(collectionName);
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(collectionName);
+
+ Document findQuery1 = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"}");
+ Document newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\",\"hostname\":\"testPserver_1\",\"equip-type\":\"JUNIPER XXXX\",\"p-interfaces\":{\"p-interface\":[{\"interface-name\":\"interface-1\"}]}}");
+ collection.replaceOne(findQuery1, newObj, new UpdateOptions().upsert(true));
+
+ Document findQuery2 = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_2\"}");
+ newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_2\",\"hostname\":\"testPserver_2\",\"equip-type\":\"JUNIPER XXXX\",\"p-interfaces\":{\"p-interface\":[{\"interface-name\":\"interface-1\"}]}}");
+ collection.replaceOne(findQuery2, newObj, new UpdateOptions().upsert(true));
+
+ newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_2\",\"hostname\":\"testPserver_2\",\"equip-type\":\"NEW\",\"p-interfaces\":{\"p-interface\":[{\"interface-name\":\"interface-1\"}]}}");
+ collection.replaceOne(findQuery2, newObj, new UpdateOptions().upsert(true));
+
+ FindIterable<Document> docs = collection.find();
+ int counter = 0;
+ for (Document doc : docs) {
+ counter++;
+ }
+ assertEquals("collection contains 2 document", 2, counter);
+
+ Document doc = collection.find(findQuery1).first();
+ assertEquals("Found testPserver_1", "testPserver_1", doc.getString("hostname"));
+
+ doc = collection.find(findQuery2).first();
+ assertEquals("Found testPserver_2", "testPserver_2", doc.getString("hostname"));
+ assertEquals("testPserver_2 has NEW as equip-type", "NEW", doc.getString("equip-type"));
+ }
+
+ @Test
+ public void removeObjectFromCollection() {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ mongoDatabase.createCollection(collectionName);
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(collectionName);
+
+ Document findQuery1 = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"}");
+ Document newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\",\"hostname\":\"testPserver_1\",\"equip-type\":\"JUNIPER XXXX\",\"p-interfaces\":{\"p-interface\":[{\"interface-name\":\"interface-1\"}]}}");
+ collection.replaceOne(findQuery1, newObj, new UpdateOptions().upsert(true));
+
+ Document findQuery2 = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_2\"}");
+ newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_2\",\"hostname\":\"testPserver_2\",\"equip-type\":\"JUNIPER XXXX\",\"p-interfaces\":{\"p-interface\":[{\"interface-name\":\"interface-1\"}]}}");
+ collection.replaceOne(findQuery2, newObj, new UpdateOptions().upsert(true));
+
+ assertEquals("PRE DELETE: collection contains 2 documents", 2, collection.count());
+
+ collection.deleteOne(findQuery1);
+
+ assertEquals("POST DELETE: collection contains 1 documents", 1, collection.count());
+
+
+ }
+
+ @Test
+ public void findOneFromCollection() {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ mongoDatabase.createCollection(collectionName);
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(collectionName);
+
+ Document findQuery1 = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"}");
+ Document newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\",\"hostname\":\"testPserver_1\",\"equip-type\":\"JUNIPER XXXX\",\"p-interfaces\":{\"p-interface\":[{\"interface-name\":\"interface-1\"}]}}");
+ collection.replaceOne(findQuery1, newObj, new UpdateOptions().upsert(true));
+
+ Document findQuery2 = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_2\"}");
+ newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_2\",\"hostname\":\"testPserver_2\",\"equip-type\":\"JUNIPER XXXX\",\"p-interfaces\":{\"p-interface\":[{\"interface-name\":\"interface-1\"}]}}");
+ collection.replaceOne(findQuery2, newObj, new UpdateOptions().upsert(true));
+
+ Document findQuery = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_2\"}");
+
+ assertEquals("collection contains 1 document with id /cloud-infrastructure/pservers/pserver/testPserver_2",
+ 1L, collection.count(findQuery));
+ }
+
+ @Test
+ public void findFromCollectionWithNested() {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ mongoDatabase.createCollection(collectionName);
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(collectionName);
+
+ Document findQuery1 = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"}");
+ Document newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\",\"hostname\":\"testPserver_1\",\"equip-type\":\"JUNIPER XXXX\",\"p-interfaces\":{\"p-interface\":[{\"interface-name\":\"interface-1\"}]}}");
+ collection.replaceOne(findQuery1, newObj, new UpdateOptions().upsert(true));
+
+ Document findQuery = Document.parse(
+ "{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"," +
+ "\"p-interfaces.p-interface.interface-name\":\"interface-1\"}"
+ );
+
+ assertEquals("collection contains 1 document with id /cloud-infrastructure/pservers/pserver/testPserver_2",
+ 1L, collection.count(findQuery));
+
+
+ }
+
+ @Test
+ public void findFromCollectionWithNestedFail() {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ mongoDatabase.createCollection(collectionName);
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(collectionName);
+
+ Document findQuery1 = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"}");
+ Document newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\",\"hostname\":\"testPserver_1\",\"equip-type\":\"JUNIPER XXXX\",\"p-interfaces\":{\"p-interface\":[{\"interface-name\":\"interface-1\"}]}}");
+ collection.replaceOne(findQuery1, newObj, new UpdateOptions().upsert(true));
+
+ Document findQuery = Document.parse(
+ "{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"," +
+ "\"p-interfaces.p-interface.interface-name\":\"interface-NONE\"}"
+ );
+
+ assertEquals("collection contains 1 document with id /cloud-infrastructure/pservers/pserver/testPserver_2",
+ 0L, collection.count(findQuery));
+
+ }
+
+
+ @Test
+ public void addToNestedListWithNonExistingList() {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ mongoDatabase.createCollection(collectionName);
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(collectionName);
+
+ Document findQuery = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"}");
+ Document newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\",\"hostname\":\"testPserver_1\",\"equip-type\":\"JUNIPER XXXX\"}");
+ collection.replaceOne(findQuery, newObj, new UpdateOptions().upsert(true));
+
+ //Check for existing obj
+ String field = "p-interfaces.p-interface";
+ String obj = "{\"interface-name\":\"interface-NEW\"}";
+ String nestedFindString = "{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"," +
+ "\"p-interfaces.p-interface.interface-name\":\"interface-NEW\"}";
+
+ Document nestedFind = Document.parse(nestedFindString);
+
+ assertEquals("PRE UPDATE: collection contains 0 document with id and nested field",
+ Long.valueOf(0L),
+ Long.valueOf(collection.count(nestedFind)));
+
+ Document doc = new Document();
+ doc.put(field, Document.parse(obj));
+ Document push = new Document();
+ push.put("$push", doc);
+
+ System.out.println(collection.find(findQuery).first().toJson());
+
+ collection.findOneAndUpdate(findQuery, push, new FindOneAndUpdateOptions().upsert(true));
+
+ System.out.println(collection.find(findQuery).first().toJson());
+
+ assertEquals("POST UPDATE: collection contains 1 document with id and nested field",
+ Long.valueOf(1L),
+ Long.valueOf(collection.count(nestedFind)));
+
+ }
+
+ @Test
+ public void addToNestedExistingList() {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ mongoDatabase.createCollection(collectionName);
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(collectionName);
+
+ Document findQuery = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"}");
+ Document newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\",\"hostname\":\"testPserver_1\",\"equip-type\":\"JUNIPER XXXX\",\"p-interfaces\":{\"p-interface\":[{\"interface-name\":\"interface-1\"}]}}");
+ collection.replaceOne(findQuery, newObj, new UpdateOptions().upsert(true));
+
+ //Check for existing obj
+ String field = "p-interfaces.p-interface";
+ String obj = "{\"interface-name\":\"interface-NEW\"}";
+ String nestedFindString = "{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"," +
+ "\"p-interfaces.p-interface.interface-name\":\"interface-NEW\"}";
+
+ Document nestedFind = Document.parse(nestedFindString);
+
+ assertEquals("PRE UPDATE: collection contains 0 document with id and nested field",
+ Long.valueOf(0L),
+ Long.valueOf(collection.count(nestedFind)));
+
+ Document doc = new Document();
+ doc.put(field, Document.parse(obj));
+ Document push = new Document();
+ push.put("$push", doc);
+
+ System.out.println(collection.find(findQuery).first().toJson());
+
+ collection.findOneAndUpdate(findQuery, push, new FindOneAndUpdateOptions().upsert(true));
+
+ System.out.println(collection.find(findQuery).first().toJson());
+
+ assertEquals("POST UPDATE: collection contains 1 document with id and nested field",
+ Long.valueOf(1L),
+ Long.valueOf(collection.count(nestedFind)));
+
+ }
+
+ @Test
+ public void addToNestedWhereNestedObjExists() {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ mongoDatabase.createCollection(collectionName);
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(collectionName);
+
+ Document findQuery = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"}");
+ Document newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\",\"hostname\":\"testPserver_1\",\"equip-type\":\"JUNIPER XXXX\",\"p-interfaces\":{\"p-interface\":[{\"interface-name\":\"interface-1\"}]}}");
+ collection.replaceOne(findQuery, newObj, new UpdateOptions().upsert(true));
+
+ //Check for existing obj
+ String field = "p-interfaces.p-interface";
+ String obj = "{\"interface-name\":\"interface-NEW\",\"new-field\":\"NEW\"}";
+ String nestedFindString = "{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"," +
+ "\"p-interfaces.p-interface.interface-name\":\"interface-1\"}";
+ String nestedFindUsingNewFieldString = "{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"," +
+ "\"p-interfaces.p-interface.new-field\":\"NEW\"}";
+ String nestedFieldPull = "{\"p-interfaces.p-interface\":{\"interface-name\":\"interface-1\"}}";
+
+ Document nestedFind = Document.parse(nestedFindString);
+
+ assertEquals("PRE UPDATE: collection contains 1 document with id and nested field",
+ Long.valueOf(1L),
+ Long.valueOf(collection.count(nestedFind)));
+ assertEquals("PRE UPDATE: collection contains 0 document with id and new nested field",
+ Long.valueOf(0L),
+ Long.valueOf(collection.count(Document.parse(nestedFindUsingNewFieldString))));
+
+ //REMOVE existing
+ Document pull = new Document();
+ pull.put("$pull", Document.parse(nestedFieldPull));
+
+ collection.findOneAndUpdate(nestedFind, pull);
+
+ assertEquals("PRE UPDATE POST DELETE: collection no longer the nested obj that will be inserted",
+ Long.valueOf(0L),
+ Long.valueOf(collection.count(nestedFind)));
+
+
+ Document doc = new Document();
+ doc.put(field, Document.parse(obj));
+ Document push = new Document();
+ push.put("$push", doc);
+
+ System.out.println(collection.find(findQuery).first().toJson());
+
+ collection.findOneAndUpdate(findQuery, push, new FindOneAndUpdateOptions().upsert(true));
+
+ System.out.println(collection.find(findQuery).first().toJson());
+
+ assertEquals("POST UPDATE: collection contains 1 document with id and nested field",
+ Long.valueOf(1L),
+ Long.valueOf(collection.count(Document.parse(nestedFindUsingNewFieldString))));
+
+ }
+
+ @Test
+ public void addToNestedWhereNestedObjExistsTwoLevels() {
+ String collectionName = new Object() {}
+ .getClass()
+ .getEnclosingMethod()
+ .getName();
+
+ mongoDatabase.createCollection(collectionName);
+
+ MongoCollection<Document> collection = mongoDatabase.getCollection(collectionName);
+
+ Document newObj = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\",\"hostname\":\"testPserver_1\"," +
+ "\"p-interfaces\":{\"p-interface\":[" +
+ "{\"interface-name\":\"interface-1\",\"l-interfaces\":{\"l-interface\":[{\"interface-name\":\"l-interface-1\"}]}}," +
+ "{\"interface-name\":\"interface-2\"}" +
+ "]}}");
+
+ Document findQuery = Document.parse("{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"," +
+ "\"p-interfaces.p-interface.interface-name\":\"interface-1\"}");
+
+ collection.replaceOne(findQuery, newObj, new UpdateOptions().upsert(true));
+
+ //Check for existing obj
+ String field = "p-interfaces.p-interface.$.l-interfaces.l-interface";
+ String obj = "{\"interface-name\":\"l-interface-1\",\"new-field\":\"NEW\"}";
+
+ String nestedFindString = "{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"," +
+ "\"p-interfaces.p-interface.interface-name\":\"interface-1\"," +
+ "\"p-interfaces.p-interface.l-interfaces.l-interface.interface-name\":\"l-interface-1\"}";
+
+ String nestedFindUsingNewFieldString = "{\"_id\":\"/cloud-infrastructure/pservers/pserver/testPserver_1\"," +
+ "\"p-interfaces.p-interface.interface-name\":\"interface-1\"" +
+ "\"p-interfaces.p-interface.l-interfaces.l-interface.new-field\":\"NEW\"}";
+
+ String nestedFieldPull = "{\"p-interfaces.p-interface.$.l-interfaces.l-interface\":{\"interface-name\":\"l-interface-1\"}}";
+
+ Document nestedFind = Document.parse(nestedFindString);
+
+ assertEquals("PRE UPDATE: collection contains 1 document with id and nested field",
+ Long.valueOf(1L),
+ Long.valueOf(collection.count(nestedFind)));
+ assertEquals("PRE UPDATE: collection contains 0 document with id and new nested field",
+ Long.valueOf(0L),
+ Long.valueOf(collection.count(Document.parse(nestedFindUsingNewFieldString))));
+
+ //REMOVE existing
+ Document pull = new Document();
+ pull.put("$pull", Document.parse(nestedFieldPull));
+
+ collection.findOneAndUpdate(nestedFind, pull);
+
+ assertEquals("PRE UPDATE POST DELETE: collection no longer the nested obj that will be inserted",
+ Long.valueOf(0L),
+ Long.valueOf(collection.count(nestedFind)));
+
+
+ Document doc = new Document();
+ doc.put(field, Document.parse(obj));
+ Document push = new Document();
+ push.put("$push", doc);
+
+ System.out.println(collection.find(findQuery).first().toJson());
+
+ collection.findOneAndUpdate(findQuery, push, new FindOneAndUpdateOptions().upsert(true));
+
+ System.out.println(collection.find(findQuery).first().toJson());
+
+ assertEquals("POST UPDATE: collection contains 1 document with id and nested field",
+ Long.valueOf(1L),
+ Long.valueOf(collection.count(Document.parse(nestedFindUsingNewFieldString))));
+
+ }
+
+} \ No newline at end of file
diff --git a/src/test/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidationTest.java b/src/test/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidationTest.java
new file mode 100644
index 0000000..53f90a3
--- /dev/null
+++ b/src/test/java/org/onap/aai/cacher/service/rest/util/CacheKeyRequestValidationTest.java
@@ -0,0 +1,90 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.cacher.service.rest.util;
+
+import com.google.gson.JsonParser;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.onap.aai.cacher.service.helper.CacheHelperService;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class CacheKeyRequestValidationTest {
+
+ protected CacheHelperService cacheHelperService;
+ protected CacheKeyRequestValidation addCacheKeyRequestValidation;
+ protected CacheKeyRequestValidation updateCacheKeyRequestValidation;
+
+ private String emptyPayload = "{}";
+ private String nonEmptyPayload = "{\"cacheKey\" : \"complex\"}";
+ private JsonParser parser;
+
+ @Before
+ public void setup() {
+ cacheHelperService = Mockito.mock(CacheHelperService.class);
+ addCacheKeyRequestValidation = new CacheKeyRequestValidation(CacheKeyRequestValidationType.ADD);
+ updateCacheKeyRequestValidation = new CacheKeyRequestValidation(CacheKeyRequestValidationType.UPDATE);
+ parser = new JsonParser();
+ }
+
+ @Test
+ public void testNullPayload() {
+ List<String> results = addCacheKeyRequestValidation.validateCacheKeyRequest(null, cacheHelperService);
+ assertEquals("null payload ok", "Unsupported CacheKey request format, empty payload.", results.get(0));
+ }
+
+ @Test
+ public void testEmptyPayload() {
+ List<String> results = addCacheKeyRequestValidation.validateCacheKeyRequest(parser.parse(emptyPayload).getAsJsonObject(), cacheHelperService);
+ assertEquals("empty payload ok", "Unsupported CacheKey request format, unspecified cacheKey.", results.get(0));
+ }
+
+ @Test
+ public void testAddNewCacheKey() {
+ Mockito.when(cacheHelperService.isKeyPresent(Mockito.any(), Mockito.anyString())).thenReturn(false);
+ List<String> results = addCacheKeyRequestValidation.validateCacheKeyRequest(parser.parse(nonEmptyPayload).getAsJsonObject(), cacheHelperService);
+ assertEquals("add new CacheKey ok", 0, results.size());
+ }
+
+ @Test
+ public void testAddExistingCacheKey() {
+ Mockito.when(cacheHelperService.isKeyPresent(Mockito.any(), Mockito.anyString())).thenReturn(true);
+ List<String> results = addCacheKeyRequestValidation.validateCacheKeyRequest(parser.parse(nonEmptyPayload).getAsJsonObject(), cacheHelperService);
+ assertEquals("add existing CacheKey ok", "Invalid request to add cacheKey complex, cacheKey exists.", results.get(0));
+ }
+
+
+ @Test
+ public void testUpdateNewCacheKey() {
+ Mockito.when(cacheHelperService.isKeyPresent(Mockito.any(), Mockito.anyString())).thenReturn(false);
+ List<String> results = updateCacheKeyRequestValidation.validateCacheKeyRequest(parser.parse(nonEmptyPayload).getAsJsonObject(), cacheHelperService);
+ assertEquals("update new CacheKey ok", "Invalid request to update cacheKey complex, cacheKey does not exist.", results.get(0));
+ }
+
+ @Test
+ public void testUpdateExistingCacheKey() {
+ Mockito.when(cacheHelperService.isKeyPresent(Mockito.any(), Mockito.anyString())).thenReturn(true);
+ List<String> results = updateCacheKeyRequestValidation.validateCacheKeyRequest(parser.parse(nonEmptyPayload).getAsJsonObject(), cacheHelperService);
+ assertEquals("update existing CacheKey ok", 0, results.size());
+ }
+}
diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties
new file mode 100644
index 0000000..5439e9f
--- /dev/null
+++ b/src/test/resources/application-test.properties
@@ -0,0 +1,14 @@
+info.build.artifact=@project.artifactId@
+info.build.name=@project.name@
+info.build.description=@project.description@
+info.build.version=@project.version@
+
+spring.jersey.type=filter
+
+logging.level.root=info
+logging.level.org.glassfish=info
+logging.level.org.glassfish.jersey=info
+
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
+
+logging.pattern.console=%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr($ threadId: {PID:- }){magenta} %clr(---){faint} %clr([ hostname: %X{hostname} serviceName: %X{serviceName} version: %X{version} transactionId: %X{transactionId} requestTimeStamp: %X{requestTimestamp} responseTimeStamp: %X{responseTimestamp} duration: %X{duration}]){yellow} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wex \ No newline at end of file
diff --git a/src/test/resources/test/payloads/dmaap-pserver-create.json b/src/test/resources/test/payloads/dmaap-pserver-create.json
new file mode 100644
index 0000000..735817d
--- /dev/null
+++ b/src/test/resources/test/payloads/dmaap-pserver-create.json
@@ -0,0 +1,100 @@
+{
+ "cambria.partition": "AAI",
+ "event-header":
+ {
+ "severity": "NORMAL",
+ "entity-type": "pserver",
+ "top-entity-type": "pserver",
+ "entity-link": "/aai/v12/cloud-infrastructure/pservers/pserver/dmaap-pserver-create",
+ "event-type": "AAI-EVENT",
+ "domain": "test",
+ "action": "CREATE",
+ "sequence-number": "0",
+ "id": "id-dmaap-pserver-create",
+ "source-name": "test",
+ "version": "v12",
+ "timestamp": "20180508-17:50:11:681"
+ },
+ "entity":
+ {
+ "hostname": "dmaap-pserver-create",
+ "equip-type": "JUNIPER XXXX",
+ "relationship-list":
+ {
+ "relationship": [
+ {
+ "related-to": "complex",
+ "relationship-data": [
+ {
+ "relationship-value": "CHARILWJNA0",
+ "relationship-key": "complex.physical-location-id"
+ }
+ ],
+ "related-link": "/aai/v12/cloud-infrastructure/complexes/complex/CHARILWJNA0",
+ "relationship-label": "org.onap.relationships.inventory.LocatedIn"
+ }
+ ]
+ },
+ "equip-vendor": "JUNIPER",
+ "equip-model": "NFX250-XYZ-LS1",
+ "in-maint": false,
+ "serial-number": "",
+ "resource-version": "1525801811662",
+ "pserver-id": "0A47B945-9C74-4CBE-AD72-0DECB966EB94",
+ "p-interfaces":
+ {
+ "p-interface": [
+ {
+ "interface-name": "ge-0/0/10",
+ "relationship-list":
+ {
+ "relationship": [
+ {
+ "related-to": "physical-link",
+ "relationship-label": "tosca.relationships.network.LinksTo",
+ "related-link": "/aai/v12/network/physical-links/physical-link/HIS.1702.03053.121",
+ "relationship-data": [
+ {
+ "relationship-key": "physical-link.link-name",
+ "relationship-value": "HIS.1702.03053.121"
+ }
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "interface-name": "ge-0/0/11",
+ "relationship-list":
+ {
+ "relationship": [
+ {
+ "related-to": "vserver",
+ "relationship-label": "tosca.relationships.HostedOn",
+ "related-link": "/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/AAIAIC25/tenants/tenant/SERVERNAME%3A%3AXXXX/vservers/vserver/afce2113-297a-436c-811a-acf9981fff68",
+ "relationship-data": [
+ {
+ "relationship-key": "cloud-region.cloud-owner",
+ "relationship-value": "onap-cloud-owner"
+ },
+ {
+ "relationship-key": "cloud-region.cloud-region-id",
+ "relationship-value": "AAIAIC25"
+ },
+ {
+ "relationship-key": "tenant.tenant-id",
+ "relationship-value": "SERVERNAME::XXXX"
+ },
+ {
+ "relationship-key": "vserver.vserver-id",
+ "relationship-value": "afce2113-297a-436c-811a-acf9981fff68"
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+}
diff --git a/src/test/resources/test/payloads/dmaapEvents/address-list.json b/src/test/resources/test/payloads/dmaapEvents/address-list.json
new file mode 100644
index 0000000..b2ea6b8
--- /dev/null
+++ b/src/test/resources/test/payloads/dmaapEvents/address-list.json
@@ -0,0 +1,47 @@
+{
+ "cambria.partition": "AAI",
+ "event-header": {
+ "severity": "NORMAL",
+ "entity-type": "l3-interface-ipv4-address-list",
+ "top-entity-type": "generic-vnf",
+ "entity-link": "/aai/v13/network/generic-vnfs/generic-vnf/generic-vnf-987654321-39-jenkins/l-interfaces/l-interface/interface-name-generic-vnf-987654321-39-jenkins/vlans/vlan/vlan-interface-generic-vnf-987654321-39-jenkins/l3-interface-ipv4-address-list/l3-interface-ipv4-address-generic-vnf-987654321-39-jenkins",
+ "event-type": "AAI-EVENT",
+ "domain": "uINT1",
+ "action": "DELETE",
+ "sequence-number": "0",
+ "id": "7a899562-a0c1-414e-83aa-0021a5c7646b",
+ "source-name": "FitNesse-Test-generic-vnf-AAI-9278-02",
+ "version": "v13",
+ "timestamp": "20180625-00:05:26:664"
+ },
+ "entity": {
+ "vnf-id": "generic-vnf-987654321-39-jenkins",
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "vlans": {
+ "vlan": [
+ {
+ "vlan-interface": "vlan-interface-generic-vnf-987654321-39-jenkins",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 79781362,
+ "resource-version": "1529885125714",
+ "neutron-network-id": "example-neutron-network-id-val-73336",
+ "neutron-subnet-id": "example-neutron-subnet-id-val-86272",
+ "vlan-id-inner": 8858186,
+ "l3-interface-ipv4-address": "l3-interface-ipv4-address-generic-vnf-987654321-39-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 5350919
+ }
+ ]
+ }
+ ]
+ },
+ "interface-name": "interface-name-generic-vnf-987654321-39-jenkins"
+ }
+ ]
+ },
+ "vnf-name": "example-vnf-name-val-21021"
+ }
+} \ No newline at end of file
diff --git a/src/test/resources/test/payloads/dmaapEvents/deleteRelationship/1-create-logical-link.json b/src/test/resources/test/payloads/dmaapEvents/deleteRelationship/1-create-logical-link.json
new file mode 100644
index 0000000..5277b3d
--- /dev/null
+++ b/src/test/resources/test/payloads/dmaapEvents/deleteRelationship/1-create-logical-link.json
@@ -0,0 +1,20 @@
+{
+ "cambria.partition": "AAI",
+ "event-header": {
+ "severity": "NORMAL",
+ "entity-type": "logical-link",
+ "top-entity-type": "logical-link",
+ "entity-link": "/aai/v13/network/logical-links/logical-link/logical-link",
+ "event-type": "AAI-EVENT",
+ "domain": "uINT1",
+ "action": "CREATE",
+ "sequence-number": "0",
+ "id": "fe89fd6b-8b1b-4ab6-8b3a-d5bb7942dbee",
+ "source-name": "junit",
+ "version": "v13",
+ "timestamp": "20180712-17:47:24:042"
+ },
+ "entity": {
+ "link-name": "logical-link"
+ }
+} \ No newline at end of file
diff --git a/src/test/resources/test/payloads/dmaapEvents/deleteRelationship/2-create-generic-vnf.json b/src/test/resources/test/payloads/dmaapEvents/deleteRelationship/2-create-generic-vnf.json
new file mode 100644
index 0000000..57fe6a2
--- /dev/null
+++ b/src/test/resources/test/payloads/dmaapEvents/deleteRelationship/2-create-generic-vnf.json
@@ -0,0 +1,32 @@
+{
+ "cambria.partition": "AAI",
+ "event-header": {
+ "severity": "NORMAL",
+ "entity-type": "generic-vnf",
+ "top-entity-type": "generic-vnf",
+ "entity-link": "/aai/v13/network/generic-vnfs/generic-vnf/generic-vnf-id",
+ "event-type": "AAI-EVENT",
+ "domain": "uINT1",
+ "action": "CREATE",
+ "sequence-number": "0",
+ "id": "d56359e7-4dcb-471a-9a6a-2afbb353b5bd",
+ "source-name": "junit",
+ "version": "v13",
+ "timestamp": "20180712-17:47:24:440"
+ },
+ "entity": {
+ "vnf-id": "generic-vnf-id",
+ "l-interfaces": {
+ "l-interface": [{
+ "vlans": {
+ "vlan": [{
+ "vlan-interface": "vlan-1"
+ }
+ ]
+ },
+ "interface-name": "l-interface-name-1"
+ }
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/src/test/resources/test/payloads/dmaapEvents/deleteRelationship/3-create-rel-generic-vnf-vlan-to-logical-link.json b/src/test/resources/test/payloads/dmaapEvents/deleteRelationship/3-create-rel-generic-vnf-vlan-to-logical-link.json
new file mode 100644
index 0000000..bdfabe8
--- /dev/null
+++ b/src/test/resources/test/payloads/dmaapEvents/deleteRelationship/3-create-rel-generic-vnf-vlan-to-logical-link.json
@@ -0,0 +1,45 @@
+{
+ "cambria.partition": "AAI",
+ "event-header": {
+ "severity": "NORMAL",
+ "entity-type": "vlan",
+ "top-entity-type": "generic-vnf",
+ "entity-link": "/aai/v13/network/generic-vnfs/generic-vnf/generic-vnf-id/l-interfaces/l-interface/l-interface-name-1/vlans/vlan/vlan-1",
+ "event-type": "AAI-EVENT",
+ "domain": "uINT1",
+ "action": "UPDATE",
+ "sequence-number": "0",
+ "id": "bd2bc927-d28b-4472-a582-317c4c19c98b",
+ "source-name": "FitNesse-Relationship-Test-ps2418",
+ "version": "v13",
+ "timestamp": "20180712-17:47:24:609"
+ },
+ "entity": {
+ "vnf-id": "generic-vnf-id",
+ "l-interfaces": {
+ "l-interface": [{
+ "vlans": {
+ "vlan": [{
+ "relationship-list": {
+ "relationship": [{
+ "related-to": "logical-link",
+ "relationship-data": [{
+ "relationship-value": "logical-link",
+ "relationship-key": "logical-link.link-name"
+ }
+ ],
+ "related-link": "/aai/v13/network/logical-links/logical-link/logical-link",
+ "relationship-label": "org.onap.relationships.inventory.Uses"
+ }
+ ]
+ },
+ "vlan-interface": "vlan-1"
+ }
+ ]
+ },
+ "interface-name": "l-interface-name-1"
+ }
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/src/test/resources/test/payloads/dmaapEvents/deleteRelationship/4-delete-rel-to-generic-vnf-vlan-from-logical-link.json b/src/test/resources/test/payloads/dmaapEvents/deleteRelationship/4-delete-rel-to-generic-vnf-vlan-from-logical-link.json
new file mode 100644
index 0000000..20c2278
--- /dev/null
+++ b/src/test/resources/test/payloads/dmaapEvents/deleteRelationship/4-delete-rel-to-generic-vnf-vlan-from-logical-link.json
@@ -0,0 +1,20 @@
+{
+ "cambria.partition": "AAI",
+ "event-header": {
+ "severity": "NORMAL",
+ "entity-type": "logical-link",
+ "top-entity-type": "logical-link",
+ "entity-link": "/aai/v13/network/logical-links/logical-link/logical-link",
+ "event-type": "AAI-EVENT",
+ "domain": "uINT1",
+ "action": "UPDATE",
+ "sequence-number": "0",
+ "id": "3f9ea0cf-da42-4a9e-817b-7fb1eab0cabe",
+ "source-name": "junit",
+ "version": "v13",
+ "timestamp": "20180712-17:47:25:057"
+ },
+ "entity": {
+ "link-name": "logical-link"
+ }
+} \ No newline at end of file
diff --git a/src/test/resources/test/payloads/dmaapEvents/large-pserver.json b/src/test/resources/test/payloads/dmaapEvents/large-pserver.json
new file mode 100644
index 0000000..1d7cf14
--- /dev/null
+++ b/src/test/resources/test/payloads/dmaapEvents/large-pserver.json
@@ -0,0 +1,2088 @@
+{
+ "cambria.partition": "AAI",
+ "event-header": {
+ "severity": "NORMAL",
+ "entity-type": "pserver",
+ "top-entity-type": "pserver",
+ "entity-link": "/aai/v13/cloud-infrastructure/pservers/pserver/c9e8ffb6-a360-4f9c-96c3-f5f0244dfe55-jenkins",
+ "event-type": "AAI-EVENT",
+ "domain": "uINT1",
+ "action": "UPDATE",
+ "sequence-number": "0",
+ "id": "5cc57cd2-c55c-4bbc-bf92-cba20b6d2bf3",
+ "source-name": "FitNesse-Test-jenkins",
+ "version": "v13",
+ "timestamp": "20180625-01:24:01:437"
+ },
+ "entity": {
+ "ptnii-equip-name": "ly3mdbqA7Gaha",
+ "ipaddress-v6-loopback-0": "VWN",
+ "equip-vendor": "zfK",
+ "purpose": "pxyHYQ6",
+ "pserver-selflink": "xS4YnSMvWpX",
+ "number-of-cpus": 359,
+ "ipaddress-v6-aim": "7vxG9SYzaH",
+ "pserver-name2": "iqFmGNmNLM6",
+ "hostname": "c9e8ffb6-a360-4f9c-96c3-f5f0244dfe55-jenkins",
+ "inv-status": "pS24ORbjyauE",
+ "disk-in-gigabytes": 509,
+ "equip-type": "41kdNkU",
+ "fqdn": "ldTOgy",
+ "serial-number": "5iYx0byET",
+ "ipaddress-v6-oam": "pc910",
+ "pserver-id": "RswqQD",
+ "prov-status": "pMB6hQ2XA35gL",
+ "ipv4-oam-address": "dQn9sGTx8T",
+ "ipaddress-v4-loopback-0": "qKCu9dNYq",
+ "lag-interfaces": {
+ "lag-interface": [
+ {
+ "interface-role": "TA0roiR2Dlstf",
+ "speed-value": "bs6yh1DIrc",
+ "in-maint": true,
+ "resource-version": "1529889840378",
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "v6-wan-link-ip": "pRl0e9CWJ",
+ "vlans": {
+ "vlan": [
+ {
+ "vlan-description": "RRiCxGpYLE7IG",
+ "vpn-key": "dENkRyQ6",
+ "prov-status": "YipbUEnORoUR",
+ "vlan-id-inner": 708,
+ "vlan-id-outer": 715,
+ "orchestration-status": "f28",
+ "speed-value": "nQ7rxAY1",
+ "in-maint": false,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840437",
+ "neutron-network-id": "2OkhCFUDCWz",
+ "neutron-subnet-id": "rAkO7",
+ "l3-interface-ipv6-prefix-length": 880,
+ "vlan-id-inner": 441,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "c72250d4-3718-458f-8a78-18b60ba84981-jenkins",
+ "vlan-id-outer": 334
+ },
+ {
+ "resource-version": "1529889840443",
+ "neutron-network-id": "Fjk5w3x",
+ "neutron-subnet-id": "CoGV7pgh0L0w",
+ "l3-interface-ipv6-prefix-length": 930,
+ "vlan-id-inner": 343,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "2e33be8a-ebe9-46b9-9ed8-b68fd7fafa37-jenkins",
+ "vlan-id-outer": 276
+ }
+ ],
+ "resource-version": "1529889840421",
+ "is-ip-unnumbered": false,
+ "speed-units": "9gi0",
+ "vlan-interface": "624adb22-bcf6-4efe-bc20-a1fa2fcdc8b5-jenkins",
+ "backdoor-connection": "VtvN8kWyDNAY",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 723,
+ "resource-version": "1529889840432",
+ "neutron-network-id": "0iGBId",
+ "neutron-subnet-id": "7Wv9mkgSgQMep",
+ "vlan-id-inner": 903,
+ "l3-interface-ipv4-address": "a69c17e3-9902-4ad8-9bf0-547a12144944-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 40
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 816,
+ "resource-version": "1529889840425",
+ "neutron-network-id": "OHzi6OHC",
+ "neutron-subnet-id": "z6cy",
+ "vlan-id-inner": 156,
+ "l3-interface-ipv4-address": "efb60dd0-2f6d-40b9-9aec-f123c900088f-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 678
+ }
+ ]
+ },
+ {
+ "vlan-description": "dko1ww",
+ "vpn-key": "tTnYmdtMuvj",
+ "prov-status": "LXwvfjKwggY",
+ "vlan-id-inner": 785,
+ "vlan-id-outer": 64,
+ "orchestration-status": "YDueDsc",
+ "speed-value": "rnq",
+ "in-maint": true,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840413",
+ "neutron-network-id": "9GwSXJO",
+ "neutron-subnet-id": "MLw92oJx",
+ "l3-interface-ipv6-prefix-length": 416,
+ "vlan-id-inner": 619,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "290c0ffd-8b30-4447-b3d0-15fd7aaf3a0a-jenkins",
+ "vlan-id-outer": 266
+ },
+ {
+ "resource-version": "1529889840407",
+ "neutron-network-id": "7mhjNSDw",
+ "neutron-subnet-id": "CfIbyRJVK",
+ "l3-interface-ipv6-prefix-length": 980,
+ "vlan-id-inner": 15,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "fe62bfe1-bb1f-430c-a73a-17129a774006-jenkins",
+ "vlan-id-outer": 538
+ }
+ ],
+ "resource-version": "1529889840390",
+ "is-ip-unnumbered": true,
+ "speed-units": "NZnxJ0",
+ "vlan-interface": "ba6322cc-8a92-4c52-9f1c-e1ed151685f4-jenkins",
+ "backdoor-connection": "hknHtwrQ8",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 123,
+ "resource-version": "1529889840395",
+ "neutron-network-id": "S1lm",
+ "neutron-subnet-id": "ArbSTda9",
+ "vlan-id-inner": 433,
+ "l3-interface-ipv4-address": "39f4c806-0a69-44ce-801e-6e788dde996c-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 454
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 874,
+ "resource-version": "1529889840402",
+ "neutron-network-id": "4eQNt",
+ "neutron-subnet-id": "jcbWZEE1iuIxo",
+ "vlan-id-inner": 179,
+ "l3-interface-ipv4-address": "bc0f320b-307f-40f0-a985-83adab31ceae-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 274
+ }
+ ]
+ }
+ ]
+ },
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "v6-wan-link-ip": "RtXRWVNEJADY",
+ "interface-name": "dc917efb-f045-4250-b3e3-1f13de0c50c6-jenkins",
+ "allowed-address-pairs": "xXhZud",
+ "prov-status": "ESgNJKvFRBbJ",
+ "macaddr": "J3BfKm",
+ "interface-role": "tRCKYmQWZr",
+ "selflink": "zqJy",
+ "in-maint": false,
+ "admin-status": "BbiEg3U",
+ "is-port-mirrored": false,
+ "resource-version": "1529889840457",
+ "is-ip-unnumbered": true,
+ "network-name": "p03hQIJEj",
+ "management-option": "qI4hY9rO",
+ "interface-id": "M1mVymxqCG9B",
+ "interface-description": "X0ylXoZxd8"
+ },
+ {
+ "v6-wan-link-ip": "PuNFKRUUpd3",
+ "interface-name": "89796dd1-89a5-4ddc-bd13-324ba9bce3b6-jenkins",
+ "allowed-address-pairs": "RGo6MaADK",
+ "prov-status": "uot",
+ "macaddr": "xUj8TGre",
+ "interface-role": "SyT0hd9Uu4b",
+ "selflink": "HxDI",
+ "in-maint": false,
+ "admin-status": "GDgD",
+ "is-port-mirrored": true,
+ "resource-version": "1529889840462",
+ "is-ip-unnumbered": false,
+ "network-name": "RXCo3p3p5BhBS",
+ "management-option": "jNiTd",
+ "interface-id": "4n8niH",
+ "interface-description": "drnTF3"
+ }
+ ]
+ },
+ "interface-name": "f4f9b9c7-eb83-4622-9d6f-14027a556ff5-jenkins",
+ "allowed-address-pairs": "tsZfdO6K",
+ "prov-status": "3arI73HikM",
+ "macaddr": "0q6FMAB",
+ "interface-role": "4cyrEGb5ldY",
+ "selflink": "baX",
+ "in-maint": true,
+ "admin-status": "NbXMnykI",
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840487",
+ "neutron-network-id": "IHaNS4GYk8We",
+ "neutron-subnet-id": "Avamy",
+ "l3-interface-ipv6-prefix-length": 980,
+ "vlan-id-inner": 995,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "91e884de-b2b7-471a-a245-44aeb7c134a6-jenkins",
+ "vlan-id-outer": 9
+ },
+ {
+ "resource-version": "1529889840481",
+ "neutron-network-id": "Nus6ae0m",
+ "neutron-subnet-id": "fA3l0lvnHdtb",
+ "l3-interface-ipv6-prefix-length": 809,
+ "vlan-id-inner": 340,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "ce4f5d92-0522-4c36-9d42-57e9138a177e-jenkins",
+ "vlan-id-outer": 753
+ }
+ ],
+ "is-port-mirrored": true,
+ "resource-version": "1529889840382",
+ "is-ip-unnumbered": false,
+ "sriov-vfs": {
+ "sriov-vf": [
+ {
+ "vf-vlan-filter": "0BKVj51qatJhI",
+ "vf-vlan-strip": false,
+ "neutron-network-id": "s8H",
+ "vf-broadcast-allow": false,
+ "vf-mac-anti-spoof-check": true,
+ "vf-unknown-multicast-allow": true,
+ "pci-id": "7e5a9324-386f-4328-aa77-a4f6cf7f0dbe-jenkins",
+ "vf-mirrors": "agzCT75g3Vg",
+ "resource-version": "1529889840451",
+ "vf-link-status": "bwtQlepGf",
+ "vf-mac-filter": "EkaVjcgrNl",
+ "vf-insert-stag": false,
+ "vf-vlan-anti-spoof-check": true,
+ "vf-unknown-unicast-allow": true
+ }
+ ]
+ },
+ "network-name": "8BqQdZOAl2lo",
+ "management-option": "CY2Ta8s",
+ "interface-id": "6Ch",
+ "interface-description": "VlMDLY2l7z",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 251,
+ "resource-version": "1529889840474",
+ "neutron-network-id": "K52",
+ "neutron-subnet-id": "7CZjzB",
+ "vlan-id-inner": 790,
+ "l3-interface-ipv4-address": "a82b6014-8aa2-4bd8-b6e7-01c5f7a19c33-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 58
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 404,
+ "resource-version": "1529889840468",
+ "neutron-network-id": "LqT0cwY4tdE",
+ "neutron-subnet-id": "Imj2rt0HAMGG",
+ "vlan-id-inner": 525,
+ "l3-interface-ipv4-address": "e7c633df-9024-493e-8b7f-5b10415cb1aa-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 108
+ }
+ ]
+ },
+ {
+ "v6-wan-link-ip": "Ln26J5hGX7M",
+ "vlans": {
+ "vlan": [
+ {
+ "vlan-description": "I9JkId",
+ "vpn-key": "LRdP",
+ "prov-status": "APYZv",
+ "vlan-id-inner": 35,
+ "vlan-id-outer": 831,
+ "orchestration-status": "T1wt2oC",
+ "speed-value": "GHxANnX",
+ "in-maint": true,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840558",
+ "neutron-network-id": "emLOUy0Qmmo",
+ "neutron-subnet-id": "fzgS9OJ",
+ "l3-interface-ipv6-prefix-length": 752,
+ "vlan-id-inner": 998,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "1bfe762c-4c38-431b-b15f-ca66c8a31a28-jenkins",
+ "vlan-id-outer": 293
+ },
+ {
+ "resource-version": "1529889840564",
+ "neutron-network-id": "20qzZFzb",
+ "neutron-subnet-id": "RWfDmt",
+ "l3-interface-ipv6-prefix-length": 400,
+ "vlan-id-inner": 427,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "4ea1cc4f-1400-494e-99c7-820b213a4c03-jenkins",
+ "vlan-id-outer": 270
+ }
+ ],
+ "resource-version": "1529889840541",
+ "is-ip-unnumbered": false,
+ "speed-units": "9CDfulUnymX1x",
+ "vlan-interface": "0016f9ca-1ef3-4b14-bed0-fd9d7a5f7020-jenkins",
+ "backdoor-connection": "hIq",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 12,
+ "resource-version": "1529889840546",
+ "neutron-network-id": "sYe5FRwMDe",
+ "neutron-subnet-id": "snexxGpM",
+ "vlan-id-inner": 834,
+ "l3-interface-ipv4-address": "eae2bc5c-e72e-41b6-93f7-73a3db342e2f-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 934
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 687,
+ "resource-version": "1529889840552",
+ "neutron-network-id": "OyNhYSJ",
+ "neutron-subnet-id": "iAE",
+ "vlan-id-inner": 820,
+ "l3-interface-ipv4-address": "c16e3d11-45cf-4ae2-aa7e-e40e23d4a454-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 12
+ }
+ ]
+ },
+ {
+ "vlan-description": "HFZ0s1sqrx",
+ "vpn-key": "DA3vkcsmXoNa",
+ "prov-status": "PLXCq2sZr",
+ "vlan-id-inner": 349,
+ "vlan-id-outer": 230,
+ "orchestration-status": "tIlhc9",
+ "speed-value": "9rk46hsxtjUJY",
+ "in-maint": true,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840534",
+ "neutron-network-id": "uzY",
+ "neutron-subnet-id": "hevG",
+ "l3-interface-ipv6-prefix-length": 188,
+ "vlan-id-inner": 247,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "418916cc-8123-4b24-8879-9f512e771c70-jenkins",
+ "vlan-id-outer": 995
+ },
+ {
+ "resource-version": "1529889840528",
+ "neutron-network-id": "9sqJYket",
+ "neutron-subnet-id": "TA0Ir2iH",
+ "l3-interface-ipv6-prefix-length": 313,
+ "vlan-id-inner": 619,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "1812bc12-be5c-4cca-9b87-03bd19277b04-jenkins",
+ "vlan-id-outer": 627
+ }
+ ],
+ "resource-version": "1529889840511",
+ "is-ip-unnumbered": true,
+ "speed-units": "siXy4hm",
+ "vlan-interface": "010547b9-4495-4fb5-a1b2-d4dbb8833e83-jenkins",
+ "backdoor-connection": "1F0cNOsS",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 780,
+ "resource-version": "1529889840522",
+ "neutron-network-id": "jwWHQK7",
+ "neutron-subnet-id": "UsxImV5pL9LL",
+ "vlan-id-inner": 637,
+ "l3-interface-ipv4-address": "d814d5bd-a23c-4f21-9f3d-2c631f424aac-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 418
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 262,
+ "resource-version": "1529889840516",
+ "neutron-network-id": "JDuBaq3Cbhd",
+ "neutron-subnet-id": "1DFTpWjFLzcZ6",
+ "vlan-id-inner": 191,
+ "l3-interface-ipv4-address": "a1dc02f5-11eb-46cd-81e8-6e51e82f7eff-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 426
+ }
+ ]
+ }
+ ]
+ },
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "v6-wan-link-ip": "3J1Z18yxgQ004",
+ "interface-name": "9471edc4-3e56-43c1-987b-a7d50b831ffa-jenkins",
+ "allowed-address-pairs": "QXWns3Qp",
+ "prov-status": "FacORXn",
+ "macaddr": "hp9PJwVAD",
+ "interface-role": "17o1WXMEldX8",
+ "selflink": "brAO",
+ "in-maint": true,
+ "admin-status": "04KWsIfV3",
+ "is-port-mirrored": false,
+ "resource-version": "1529889840583",
+ "is-ip-unnumbered": false,
+ "network-name": "8xX9B4eSfixos",
+ "management-option": "m2w0o5B",
+ "interface-id": "zzbAbZvn6sT",
+ "interface-description": "qkWDaz1Qix"
+ },
+ {
+ "v6-wan-link-ip": "PxVRinMq5Vgq4",
+ "interface-name": "a11a5207-4fb1-4dc2-a167-95c2712fdc35-jenkins",
+ "allowed-address-pairs": "oG7yZKSv6KONP",
+ "prov-status": "tCy3ilKzFIR",
+ "macaddr": "ttHiTiLtkN25z",
+ "interface-role": "OpQ3C",
+ "selflink": "dZe4nCK",
+ "in-maint": false,
+ "admin-status": "PqB6G3n16lEG",
+ "is-port-mirrored": false,
+ "resource-version": "1529889840578",
+ "is-ip-unnumbered": true,
+ "network-name": "6PQItO",
+ "management-option": "PK28FqG",
+ "interface-id": "Gpy8kn1QXK",
+ "interface-description": "HLG0XZ"
+ }
+ ]
+ },
+ "interface-name": "02dc1675-e1c3-4cfb-a2e6-8aa67b6f1c2d-jenkins",
+ "allowed-address-pairs": "7xJnB",
+ "prov-status": "cMv3MM0GPOk",
+ "macaddr": "JVQ8SS6",
+ "interface-role": "r1hnvD02Xgs",
+ "selflink": "r3F",
+ "in-maint": true,
+ "admin-status": "4iU",
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840608",
+ "neutron-network-id": "oLuz7jf",
+ "neutron-subnet-id": "ouBsOQ",
+ "l3-interface-ipv6-prefix-length": 421,
+ "vlan-id-inner": 864,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "95782900-e9e2-459f-8039-e8c165a22688-jenkins",
+ "vlan-id-outer": 760
+ },
+ {
+ "resource-version": "1529889840602",
+ "neutron-network-id": "yT9BgKa5Q",
+ "neutron-subnet-id": "4wuHUPFV",
+ "l3-interface-ipv6-prefix-length": 454,
+ "vlan-id-inner": 775,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "af360d6d-06c6-44af-ab10-7f3e253d6f5c-jenkins",
+ "vlan-id-outer": 733
+ }
+ ],
+ "is-port-mirrored": true,
+ "resource-version": "1529889840504",
+ "is-ip-unnumbered": true,
+ "sriov-vfs": {
+ "sriov-vf": [
+ {
+ "vf-vlan-filter": "szyj3DJNs",
+ "vf-vlan-strip": true,
+ "neutron-network-id": "oe0yQEK2pt",
+ "vf-broadcast-allow": false,
+ "vf-mac-anti-spoof-check": false,
+ "vf-unknown-multicast-allow": false,
+ "pci-id": "1e9a98ce-5235-47d3-ab4b-d106c77eac4f-jenkins",
+ "vf-mirrors": "RLPA",
+ "resource-version": "1529889840572",
+ "vf-link-status": "7cbMLgWUQCA",
+ "vf-mac-filter": "6MFqin1N10K",
+ "vf-insert-stag": true,
+ "vf-vlan-anti-spoof-check": true,
+ "vf-unknown-unicast-allow": false
+ }
+ ]
+ },
+ "network-name": "sf6cI7Fb",
+ "management-option": "GZl1Yw",
+ "interface-id": "pZNGvpNZ",
+ "interface-description": "jiPT6esm7",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 268,
+ "resource-version": "1529889840589",
+ "neutron-network-id": "BTsABqXg",
+ "neutron-subnet-id": "qjg5eZlk",
+ "vlan-id-inner": 877,
+ "l3-interface-ipv4-address": "a64ab58a-26ea-464b-a32d-c30d6bf1d40f-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 31
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 395,
+ "resource-version": "1529889840596",
+ "neutron-network-id": "v2LUT",
+ "neutron-subnet-id": "VTknAqDz",
+ "vlan-id-inner": 205,
+ "l3-interface-ipv4-address": "0076fd8f-ecb3-4527-b3ee-fee132be8db6-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 461
+ }
+ ]
+ }
+ ]
+ },
+ "interface-name": "8806d30d-e5f5-409e-9e9e-9b1c1943058d-jenkins",
+ "speed-units": "dtp",
+ "prov-status": "2zeuU",
+ "interface-description": "hvVs",
+ "interface-id": "KFxtMnPc5yK0B"
+ },
+ {
+ "interface-role": "XY4Wle1e0",
+ "speed-value": "pK4kfeQqTNFh4",
+ "in-maint": true,
+ "resource-version": "1529889840619",
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "v6-wan-link-ip": "MsEqgBrWffZ",
+ "vlans": {
+ "vlan": [
+ {
+ "vlan-description": "LfyQImV4m0",
+ "vpn-key": "bYw0P",
+ "prov-status": "JQCyvJ",
+ "vlan-id-inner": 566,
+ "vlan-id-outer": 558,
+ "orchestration-status": "HIF",
+ "speed-value": "Ar7CSlrCY",
+ "in-maint": false,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840646",
+ "neutron-network-id": "PoZ",
+ "neutron-subnet-id": "y7SaFxU9te4O",
+ "l3-interface-ipv6-prefix-length": 631,
+ "vlan-id-inner": 207,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "8466bb52-7984-4792-a37f-b522a0b49f83-jenkins",
+ "vlan-id-outer": 941
+ },
+ {
+ "resource-version": "1529889840652",
+ "neutron-network-id": "NcYrcVwTCtEH",
+ "neutron-subnet-id": "370eM",
+ "l3-interface-ipv6-prefix-length": 137,
+ "vlan-id-inner": 830,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "e291654f-f843-470c-9888-e5ed0e751a8b-jenkins",
+ "vlan-id-outer": 351
+ }
+ ],
+ "resource-version": "1529889840629",
+ "is-ip-unnumbered": false,
+ "speed-units": "iPOB5",
+ "vlan-interface": "67dd28da-6b2b-420b-8586-d50ad2832b16-jenkins",
+ "backdoor-connection": "Sm8BM",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 455,
+ "resource-version": "1529889840634",
+ "neutron-network-id": "ILjdNY7FyDFTa",
+ "neutron-subnet-id": "l5D",
+ "vlan-id-inner": 499,
+ "l3-interface-ipv4-address": "5724d3ec-a533-4dda-821d-564fa6f1bd9c-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 863
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 129,
+ "resource-version": "1529889840640",
+ "neutron-network-id": "ShC4WNzIO",
+ "neutron-subnet-id": "vg73RjKeCDqdL",
+ "vlan-id-inner": 947,
+ "l3-interface-ipv4-address": "3e843120-b62d-4c97-bb41-7f0219db7b14-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 634
+ }
+ ]
+ },
+ {
+ "vlan-description": "jQcFXNZd",
+ "vpn-key": "SWZEIY6YS",
+ "prov-status": "3CGAI",
+ "vlan-id-inner": 277,
+ "vlan-id-outer": 527,
+ "orchestration-status": "zPNrcQLm4uv6P",
+ "speed-value": "EnMy3",
+ "in-maint": true,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840682",
+ "neutron-network-id": "odwHBa91BM1q",
+ "neutron-subnet-id": "gyUcUX10",
+ "l3-interface-ipv6-prefix-length": 712,
+ "vlan-id-inner": 88,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "039308d2-d148-427b-b5fd-10674761c44d-jenkins",
+ "vlan-id-outer": 367
+ },
+ {
+ "resource-version": "1529889840676",
+ "neutron-network-id": "Gza",
+ "neutron-subnet-id": "pIq",
+ "l3-interface-ipv6-prefix-length": 466,
+ "vlan-id-inner": 230,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "b88fd72b-daaf-4501-ae0e-03ae6dd908fb-jenkins",
+ "vlan-id-outer": 881
+ }
+ ],
+ "resource-version": "1529889840659",
+ "is-ip-unnumbered": false,
+ "speed-units": "kCGl",
+ "vlan-interface": "b765805d-a9ee-4b67-9878-b9ce5393afcd-jenkins",
+ "backdoor-connection": "3Uj",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 464,
+ "resource-version": "1529889840670",
+ "neutron-network-id": "dCij",
+ "neutron-subnet-id": "JsAH2B",
+ "vlan-id-inner": 806,
+ "l3-interface-ipv4-address": "6c72d28b-2068-4421-b434-c91aed94d05f-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 944
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 409,
+ "resource-version": "1529889840664",
+ "neutron-network-id": "K7Iu55Aeg7",
+ "neutron-subnet-id": "Szh5oyDazQxx",
+ "vlan-id-inner": 574,
+ "l3-interface-ipv4-address": "9bd8b783-fa5f-464f-8c70-c2b7073aaa31-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 901
+ }
+ ]
+ }
+ ]
+ },
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "v6-wan-link-ip": "9JOASEc",
+ "interface-name": "1f2c5777-382d-42a1-95dd-ad46dd3970b6-jenkins",
+ "allowed-address-pairs": "cj7hTo",
+ "prov-status": "esrpGpgM66MA",
+ "macaddr": "ABRk4hv1fYAvm",
+ "interface-role": "fOx5Ci",
+ "selflink": "bNOyib",
+ "in-maint": false,
+ "admin-status": "aflI2BZ",
+ "is-port-mirrored": true,
+ "resource-version": "1529889840695",
+ "is-ip-unnumbered": false,
+ "network-name": "W9ikzRrF7mB",
+ "management-option": "qHHbFL",
+ "interface-id": "O4z",
+ "interface-description": "UYX398gN8i"
+ },
+ {
+ "v6-wan-link-ip": "oSFHmh2phxen",
+ "interface-name": "17e6f113-b3e2-48a1-bb53-dbaa7318c3f2-jenkins",
+ "allowed-address-pairs": "B0LqLPi",
+ "prov-status": "ZMERs2idY",
+ "macaddr": "iavYQQ8D0",
+ "interface-role": "LWDdQz9ooY",
+ "selflink": "NaTAzh6",
+ "in-maint": false,
+ "admin-status": "Rwba4Pyl",
+ "is-port-mirrored": true,
+ "resource-version": "1529889840701",
+ "is-ip-unnumbered": false,
+ "network-name": "qVNOCDe",
+ "management-option": "mYzH",
+ "interface-id": "6xOTvBMzb4A",
+ "interface-description": "xNHFfbZ"
+ }
+ ]
+ },
+ "interface-name": "1d6289a3-7dda-42d7-ad36-b8aa82c3527a-jenkins",
+ "allowed-address-pairs": "SDWi77k0TXOfD",
+ "prov-status": "ce9dCt",
+ "macaddr": "pg3ALUfE6T",
+ "interface-role": "FTsH1RM9",
+ "selflink": "dWkOVoX",
+ "in-maint": true,
+ "admin-status": "Mn3",
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840719",
+ "neutron-network-id": "Ac9ESt",
+ "neutron-subnet-id": "Z7Lj",
+ "l3-interface-ipv6-prefix-length": 711,
+ "vlan-id-inner": 961,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "de537e8b-b42c-4543-a680-7b24cd96262c-jenkins",
+ "vlan-id-outer": 143
+ },
+ {
+ "resource-version": "1529889840726",
+ "neutron-network-id": "n8HSAX",
+ "neutron-subnet-id": "71QevzBBwqbhw",
+ "l3-interface-ipv6-prefix-length": 479,
+ "vlan-id-inner": 845,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "b425a520-6389-4382-aa0b-aa2585e8960c-jenkins",
+ "vlan-id-outer": 57
+ }
+ ],
+ "is-port-mirrored": false,
+ "resource-version": "1529889840623",
+ "is-ip-unnumbered": false,
+ "sriov-vfs": {
+ "sriov-vf": [
+ {
+ "vf-vlan-filter": "NzCY2ZFza",
+ "vf-vlan-strip": true,
+ "neutron-network-id": "XVyTFfI",
+ "vf-broadcast-allow": true,
+ "vf-mac-anti-spoof-check": true,
+ "vf-unknown-multicast-allow": true,
+ "pci-id": "8e034ca2-4f11-4c8e-98cf-d6463986fe4d-jenkins",
+ "vf-mirrors": "u0FdegnEMsC",
+ "resource-version": "1529889840690",
+ "vf-link-status": "CEiqnhy",
+ "vf-mac-filter": "9QXQosf6",
+ "vf-insert-stag": true,
+ "vf-vlan-anti-spoof-check": true,
+ "vf-unknown-unicast-allow": true
+ }
+ ]
+ },
+ "network-name": "ZOxPNuwY",
+ "management-option": "7NmUPH",
+ "interface-id": "Hq3BuQ7",
+ "interface-description": "5Sr3zVcb",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 284,
+ "resource-version": "1529889840713",
+ "neutron-network-id": "BGv8mmqI",
+ "neutron-subnet-id": "55SW",
+ "vlan-id-inner": 672,
+ "l3-interface-ipv4-address": "26e40e8b-8e00-43a4-9050-5b9eadc90305-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 946
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 623,
+ "resource-version": "1529889840707",
+ "neutron-network-id": "voGoxHzyuDW",
+ "neutron-subnet-id": "PYStGvpuliOY",
+ "vlan-id-inner": 224,
+ "l3-interface-ipv4-address": "20ff73f0-4169-43b9-b0c6-ceea0c54a24e-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 913
+ }
+ ]
+ },
+ {
+ "v6-wan-link-ip": "orgs2voeaiET",
+ "vlans": {
+ "vlan": [
+ {
+ "vlan-description": "AE75zek",
+ "vpn-key": "bka0W79",
+ "prov-status": "gF8zBYGKLFI1t",
+ "vlan-id-inner": 620,
+ "vlan-id-outer": 162,
+ "orchestration-status": "CzCJsuBNc",
+ "speed-value": "JQvUCFr",
+ "in-maint": true,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840757",
+ "neutron-network-id": "lrYktUQ4B",
+ "neutron-subnet-id": "87JiirHx",
+ "l3-interface-ipv6-prefix-length": 244,
+ "vlan-id-inner": 568,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "97f083b3-5cf3-414e-89a6-dd1b20ef06b8-jenkins",
+ "vlan-id-outer": 201
+ },
+ {
+ "resource-version": "1529889840763",
+ "neutron-network-id": "smMgUDmt",
+ "neutron-subnet-id": "WfemGm8N5",
+ "l3-interface-ipv6-prefix-length": 566,
+ "vlan-id-inner": 43,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "4dfd97ec-d11c-40ac-9bc0-a906b50b5095-jenkins",
+ "vlan-id-outer": 282
+ }
+ ],
+ "resource-version": "1529889840740",
+ "is-ip-unnumbered": false,
+ "speed-units": "zv1",
+ "vlan-interface": "7006e23b-aa18-491c-94f1-9ccbdb1216c1-jenkins",
+ "backdoor-connection": "XvPt0D7",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 345,
+ "resource-version": "1529889840745",
+ "neutron-network-id": "WkVtQi",
+ "neutron-subnet-id": "iiE",
+ "vlan-id-inner": 585,
+ "l3-interface-ipv4-address": "237dfc24-c581-460f-9e31-608ae9cf07db-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 752
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 664,
+ "resource-version": "1529889840751",
+ "neutron-network-id": "BMpMnD",
+ "neutron-subnet-id": "AgrOLB",
+ "vlan-id-inner": 523,
+ "l3-interface-ipv4-address": "3ec034d2-5c77-492c-8c63-a2ebda389e5d-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 884
+ }
+ ]
+ },
+ {
+ "vlan-description": "atAWwI4a3Z9nn",
+ "vpn-key": "lhN",
+ "prov-status": "xTREV",
+ "vlan-id-inner": 687,
+ "vlan-id-outer": 963,
+ "orchestration-status": "aZmqJkmVe",
+ "speed-value": "CxGo",
+ "in-maint": false,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840793",
+ "neutron-network-id": "vmmpW",
+ "neutron-subnet-id": "QmsUCT7Z9",
+ "l3-interface-ipv6-prefix-length": 869,
+ "vlan-id-inner": 444,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "f694a211-1144-4ac0-8a18-841e4e9b6496-jenkins",
+ "vlan-id-outer": 307
+ },
+ {
+ "resource-version": "1529889840788",
+ "neutron-network-id": "h3JpE02Qol",
+ "neutron-subnet-id": "1LP1wI",
+ "l3-interface-ipv6-prefix-length": 699,
+ "vlan-id-inner": 695,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "d382a20e-6c27-4e3f-a79a-670519ff8091-jenkins",
+ "vlan-id-outer": 162
+ }
+ ],
+ "resource-version": "1529889840770",
+ "is-ip-unnumbered": true,
+ "speed-units": "3lGVeAq",
+ "vlan-interface": "4ce368d2-ec9b-4e92-8b7f-031edcec30cc-jenkins",
+ "backdoor-connection": "3XjveRtVEEBud",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 996,
+ "resource-version": "1529889840776",
+ "neutron-network-id": "rXeE0QspfKY",
+ "neutron-subnet-id": "38sj3w",
+ "vlan-id-inner": 62,
+ "l3-interface-ipv4-address": "16a23c8d-1a92-49a9-b03b-09eec176d3eb-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 735
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 703,
+ "resource-version": "1529889840782",
+ "neutron-network-id": "4AyvZ5hNZ",
+ "neutron-subnet-id": "1ssFocSaqQo",
+ "vlan-id-inner": 616,
+ "l3-interface-ipv4-address": "b96e59ab-e272-4586-857f-b5b6ef8bf3c5-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 857
+ }
+ ]
+ }
+ ]
+ },
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "v6-wan-link-ip": "hxz",
+ "interface-name": "1bf29baf-8a7a-4bef-9e65-60afd4aa4bc5-jenkins",
+ "allowed-address-pairs": "m5q",
+ "prov-status": "2jq0q",
+ "macaddr": "RIoHQVpg",
+ "interface-role": "AOUF02ImxkTN",
+ "selflink": "tFX",
+ "in-maint": false,
+ "admin-status": "mgaWPPl3y3",
+ "is-port-mirrored": true,
+ "resource-version": "1529889840807",
+ "is-ip-unnumbered": false,
+ "network-name": "UMXmDlnia43zq",
+ "management-option": "Vlnc",
+ "interface-id": "mtfnhl6ONlg40",
+ "interface-description": "Ow5JhDaD"
+ },
+ {
+ "v6-wan-link-ip": "8N8zazXz1R",
+ "interface-name": "76ff110f-6967-4d27-bd9d-4d053f9c344b-jenkins",
+ "allowed-address-pairs": "bnrD6",
+ "prov-status": "pPxhpmA0mNMDW",
+ "macaddr": "IM8RYRdp",
+ "interface-role": "3gxROfeT",
+ "selflink": "YcZhmOgXU",
+ "in-maint": true,
+ "admin-status": "oSSwcVT7Z",
+ "is-port-mirrored": false,
+ "resource-version": "1529889840812",
+ "is-ip-unnumbered": true,
+ "network-name": "fqxZ6e1iSI",
+ "management-option": "e8iCRmtU",
+ "interface-id": "nYGg",
+ "interface-description": "7zDWMD0s2"
+ }
+ ]
+ },
+ "interface-name": "b654cb26-070e-437a-b04e-7f07d44fdc52-jenkins",
+ "allowed-address-pairs": "70JS",
+ "prov-status": "HH4Y",
+ "macaddr": "m0Xnah2pf1Bpy",
+ "interface-role": "naRsTm",
+ "selflink": "fC0AtzLXWIL",
+ "in-maint": true,
+ "admin-status": "HAWquxE",
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840839",
+ "neutron-network-id": "Gc3bhBf4bpJ0",
+ "neutron-subnet-id": "BysFFJ",
+ "l3-interface-ipv6-prefix-length": 348,
+ "vlan-id-inner": 170,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "0d4500e9-869e-4cb4-9cb4-3819d2c6bbbc-jenkins",
+ "vlan-id-outer": 383
+ },
+ {
+ "resource-version": "1529889840845",
+ "neutron-network-id": "FZObd3YO",
+ "neutron-subnet-id": "MJMH2LPtW3N",
+ "l3-interface-ipv6-prefix-length": 986,
+ "vlan-id-inner": 907,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "2b6c8e63-031b-45cd-b4c4-fe4bc9c73415-jenkins",
+ "vlan-id-outer": 150
+ }
+ ],
+ "is-port-mirrored": false,
+ "resource-version": "1529889840734",
+ "is-ip-unnumbered": true,
+ "sriov-vfs": {
+ "sriov-vf": [
+ {
+ "vf-vlan-filter": "81VYb1i",
+ "vf-vlan-strip": false,
+ "neutron-network-id": "5hrpHU",
+ "vf-broadcast-allow": true,
+ "vf-mac-anti-spoof-check": true,
+ "vf-unknown-multicast-allow": true,
+ "pci-id": "47a35b64-d6b5-438e-a36e-67527c7adacb-jenkins",
+ "vf-mirrors": "LVDF81V6wFJFi",
+ "resource-version": "1529889840801",
+ "vf-link-status": "j4G9oyAtL8W",
+ "vf-mac-filter": "loye",
+ "vf-insert-stag": false,
+ "vf-vlan-anti-spoof-check": false,
+ "vf-unknown-unicast-allow": false
+ }
+ ]
+ },
+ "network-name": "TTsan6YwMM",
+ "management-option": "Vm4JdgeI",
+ "interface-id": "bNt",
+ "interface-description": "m16u",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 322,
+ "resource-version": "1529889840827",
+ "neutron-network-id": "MTRM",
+ "neutron-subnet-id": "6rhZMmstG4i",
+ "vlan-id-inner": 134,
+ "l3-interface-ipv4-address": "f1964d77-7b60-4b52-af29-7e862b35eabc-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 150
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 936,
+ "resource-version": "1529889840833",
+ "neutron-network-id": "WierCB0r5",
+ "neutron-subnet-id": "FIhbraamzpd0O",
+ "vlan-id-inner": 395,
+ "l3-interface-ipv4-address": "43d2e200-525c-460e-b437-8abd201b6fca-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 688
+ }
+ ]
+ }
+ ]
+ },
+ "interface-name": "2ac48363-21fd-485a-8088-c8de995396a3-jenkins",
+ "speed-units": "lLgzNBkg",
+ "prov-status": "l299JsuJhY",
+ "interface-description": "G1C1H",
+ "interface-id": "w6FY"
+ }
+ ]
+ },
+ "equip-model": "e2IFGT",
+ "in-maint": false,
+ "p-interfaces": {
+ "p-interface": [
+ {
+ "equipment-identifier": "fLsqKh",
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "v6-wan-link-ip": "MBw16c7s",
+ "vlans": {
+ "vlan": [
+ {
+ "vlan-description": "Fa8BU8",
+ "vpn-key": "c3PkMMd",
+ "prov-status": "fJ3DOFSk7",
+ "vlan-id-inner": 402,
+ "vlan-id-outer": 34,
+ "orchestration-status": "eHkM4C",
+ "speed-value": "zSqye71RT",
+ "in-maint": false,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889839959",
+ "neutron-network-id": "Ee9qO6PQ7zi5",
+ "neutron-subnet-id": "l2A7T",
+ "l3-interface-ipv6-prefix-length": 684,
+ "vlan-id-inner": 209,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "8914f8ff-e0e7-4835-ad2a-cfa7f0dab948-jenkins",
+ "vlan-id-outer": 711
+ },
+ {
+ "resource-version": "1529889839965",
+ "neutron-network-id": "eOeaaX",
+ "neutron-subnet-id": "kv6",
+ "l3-interface-ipv6-prefix-length": 470,
+ "vlan-id-inner": 298,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "62e3e5aa-adff-48e3-8ec3-fc50ca37864d-jenkins",
+ "vlan-id-outer": 952
+ }
+ ],
+ "resource-version": "1529889839942",
+ "is-ip-unnumbered": true,
+ "speed-units": "tCdCihW7p4K",
+ "vlan-interface": "697fa57d-87b6-4ee8-a4cd-83ae7fde814b-jenkins",
+ "backdoor-connection": "jRx4Vij6fhbmU",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 934,
+ "resource-version": "1529889839953",
+ "neutron-network-id": "2augUNUhqiZ",
+ "neutron-subnet-id": "anWVuz",
+ "vlan-id-inner": 814,
+ "l3-interface-ipv4-address": "e72991d7-9397-49fe-8ff2-0b24f5da6601-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 120
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 544,
+ "resource-version": "1529889839947",
+ "neutron-network-id": "GLBUVmQ",
+ "neutron-subnet-id": "qJaRGA3xGQ05N",
+ "vlan-id-inner": 144,
+ "l3-interface-ipv4-address": "638b0014-0550-4f8f-a182-0f25c7a49094-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 860
+ }
+ ]
+ },
+ {
+ "vlan-description": "kpjS8p9",
+ "vpn-key": "K797abgqJPJ",
+ "prov-status": "VVjAwvGkYn6",
+ "vlan-id-inner": 145,
+ "vlan-id-outer": 472,
+ "orchestration-status": "U4bPZ",
+ "speed-value": "K3YJXZpVAWlNk",
+ "in-maint": false,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889839935",
+ "neutron-network-id": "2M6x",
+ "neutron-subnet-id": "FtZ6iJ72JPxOp",
+ "l3-interface-ipv6-prefix-length": 705,
+ "vlan-id-inner": 360,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "d46aee86-d8d1-4f50-95c0-dba97accf2b2-jenkins",
+ "vlan-id-outer": 91
+ },
+ {
+ "resource-version": "1529889839929",
+ "neutron-network-id": "CfzdGpL",
+ "neutron-subnet-id": "7NTTSE",
+ "l3-interface-ipv6-prefix-length": 342,
+ "vlan-id-inner": 423,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "ea3e330f-9868-4cbf-aa99-c57281cdbff8-jenkins",
+ "vlan-id-outer": 414
+ }
+ ],
+ "resource-version": "1529889839912",
+ "is-ip-unnumbered": false,
+ "speed-units": "eWavRsG",
+ "vlan-interface": "e270589c-0f82-4213-adff-7edb6eda511a-jenkins",
+ "backdoor-connection": "ONvEI4XvtvJN",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 384,
+ "resource-version": "1529889839917",
+ "neutron-network-id": "kNHGesT",
+ "neutron-subnet-id": "yA9FTecLecooy",
+ "vlan-id-inner": 553,
+ "l3-interface-ipv4-address": "4baec833-d46e-4141-a144-9a69d2995083-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 743
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 766,
+ "resource-version": "1529889839923",
+ "neutron-network-id": "lY4i8I2h",
+ "neutron-subnet-id": "nH360LQ",
+ "vlan-id-inner": 575,
+ "l3-interface-ipv4-address": "dbce2579-771e-45dd-9eeb-fcfd8abb59a3-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 659
+ }
+ ]
+ }
+ ]
+ },
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "v6-wan-link-ip": "VtXT",
+ "interface-name": "22ba20ad-4f1c-4530-ab9d-fc091051bd84-jenkins",
+ "allowed-address-pairs": "9mbMpE4l",
+ "prov-status": "H5E8157",
+ "macaddr": "BWuWkvhtW8",
+ "interface-role": "R1EKN",
+ "selflink": "hUEY5Uw6ZBH",
+ "in-maint": true,
+ "admin-status": "DF03UHHd8",
+ "is-port-mirrored": false,
+ "resource-version": "1529889839978",
+ "is-ip-unnumbered": false,
+ "network-name": "7W2QE34D",
+ "management-option": "Vkx",
+ "interface-id": "fGaA",
+ "interface-description": "i4i"
+ },
+ {
+ "v6-wan-link-ip": "BC0ksb1bI1EK",
+ "interface-name": "4c7fe9ad-f5e2-4cc3-8b03-792ae7289154-jenkins",
+ "allowed-address-pairs": "3oyqp9iyD7",
+ "prov-status": "C0p5fH6lfcAb",
+ "macaddr": "WK2Qd",
+ "interface-role": "w5sQ4P",
+ "selflink": "6h6qQjMR",
+ "in-maint": false,
+ "admin-status": "pYhXCCf83pvO",
+ "is-port-mirrored": false,
+ "resource-version": "1529889839984",
+ "is-ip-unnumbered": true,
+ "network-name": "GGToGGIWb",
+ "management-option": "XeKuav",
+ "interface-id": "zHWzodA2Dy8",
+ "interface-description": "uvVfwQuN"
+ }
+ ]
+ },
+ "interface-name": "7bd89b2e-e723-4d50-a4a2-4a0d1fe69069-jenkins",
+ "allowed-address-pairs": "JCAK8XN2PNw",
+ "prov-status": "qlSKW",
+ "macaddr": "QfkSxy1VuCour",
+ "interface-role": "nf1rP4iNKUP",
+ "selflink": "ZSWul0",
+ "in-maint": false,
+ "admin-status": "qMVSn68C3QONM",
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840003",
+ "neutron-network-id": "1fuU",
+ "neutron-subnet-id": "r2oLjsNWsep",
+ "l3-interface-ipv6-prefix-length": 97,
+ "vlan-id-inner": 251,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "a811422b-b69c-473d-ba0d-6d757d6ebfc7-jenkins",
+ "vlan-id-outer": 903
+ },
+ {
+ "resource-version": "1529889840009",
+ "neutron-network-id": "0HxL0QUeL",
+ "neutron-subnet-id": "7mSCgN",
+ "l3-interface-ipv6-prefix-length": 611,
+ "vlan-id-inner": 514,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "710b2053-4be6-44c7-a2db-833862f398c1-jenkins",
+ "vlan-id-outer": 441
+ }
+ ],
+ "is-port-mirrored": true,
+ "resource-version": "1529889839905",
+ "is-ip-unnumbered": false,
+ "sriov-vfs": {
+ "sriov-vf": [
+ {
+ "vf-vlan-filter": "9Be4",
+ "vf-vlan-strip": true,
+ "neutron-network-id": "OkbLwv534",
+ "vf-broadcast-allow": true,
+ "vf-mac-anti-spoof-check": false,
+ "vf-unknown-multicast-allow": true,
+ "pci-id": "40672a3c-11df-49d8-ba6c-4266366f81a6-jenkins",
+ "vf-mirrors": "LHRZR",
+ "resource-version": "1529889839973",
+ "vf-link-status": "dL3n6",
+ "vf-mac-filter": "wTYL",
+ "vf-insert-stag": true,
+ "vf-vlan-anti-spoof-check": false,
+ "vf-unknown-unicast-allow": false
+ }
+ ]
+ },
+ "network-name": "9zXzqY2",
+ "management-option": "zVscglva0VC",
+ "interface-id": "GND6v7N9BUKdL",
+ "interface-description": "H2OPAj",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 610,
+ "resource-version": "1529889839996",
+ "neutron-network-id": "RYKV1Q",
+ "neutron-subnet-id": "vr92NIO7V",
+ "vlan-id-inner": 159,
+ "l3-interface-ipv4-address": "d9597d04-1bc5-4d62-876f-ed30524bb46f-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 40
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 969,
+ "resource-version": "1529889839990",
+ "neutron-network-id": "TA6",
+ "neutron-subnet-id": "f5mhuX2bvOEso",
+ "vlan-id-inner": 269,
+ "l3-interface-ipv4-address": "86a9090a-f49c-4734-8a67-8b595e04f647-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 206
+ }
+ ]
+ },
+ {
+ "v6-wan-link-ip": "JErpT",
+ "vlans": {
+ "vlan": [
+ {
+ "vlan-description": "wLNn",
+ "vpn-key": "hHCbqshyhg",
+ "prov-status": "Y9420",
+ "vlan-id-inner": 121,
+ "vlan-id-outer": 663,
+ "orchestration-status": "t9S8rSP7p",
+ "speed-value": "i9cLXv",
+ "in-maint": false,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840042",
+ "neutron-network-id": "8jiEnSajGx",
+ "neutron-subnet-id": "FOVkSB",
+ "l3-interface-ipv6-prefix-length": 496,
+ "vlan-id-inner": 558,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "e83bed12-5dd7-4d9a-929f-9cf57d728376-jenkins",
+ "vlan-id-outer": 12
+ },
+ {
+ "resource-version": "1529889840047",
+ "neutron-network-id": "sdOb55dAzQt",
+ "neutron-subnet-id": "HqtvNrbOW",
+ "l3-interface-ipv6-prefix-length": 823,
+ "vlan-id-inner": 62,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "49d8a3d2-2f2e-4f2a-a236-2eedabcbae1f-jenkins",
+ "vlan-id-outer": 341
+ }
+ ],
+ "resource-version": "1529889840025",
+ "is-ip-unnumbered": false,
+ "speed-units": "0yC0mR",
+ "vlan-interface": "e1159280-5843-412c-9ac6-4b95c1a76f3b-jenkins",
+ "backdoor-connection": "ZYtmgZrUF6vzS",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 314,
+ "resource-version": "1529889840029",
+ "neutron-network-id": "8jHyNtYT7",
+ "neutron-subnet-id": "9NBJS3AORrVpW",
+ "vlan-id-inner": 788,
+ "l3-interface-ipv4-address": "9e56f7a7-1241-4cde-ab06-6166c4208454-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 627
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 586,
+ "resource-version": "1529889840036",
+ "neutron-network-id": "V5hCkUWfVQNH",
+ "neutron-subnet-id": "bNHGIvjnK",
+ "vlan-id-inner": 486,
+ "l3-interface-ipv4-address": "66eb2cfa-03c5-424d-a992-2e77bf31ddd0-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 230
+ }
+ ]
+ },
+ {
+ "vlan-description": "PMgsvKp7",
+ "vpn-key": "jrDeBGUBhtkBC",
+ "prov-status": "eMkpM1Nq",
+ "vlan-id-inner": 847,
+ "vlan-id-outer": 644,
+ "orchestration-status": "ermPPN",
+ "speed-value": "mbBs40CypPU4",
+ "in-maint": false,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840073",
+ "neutron-network-id": "TYINcC7C55H",
+ "neutron-subnet-id": "cMVQPrD",
+ "l3-interface-ipv6-prefix-length": 248,
+ "vlan-id-inner": 326,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "1c054bd3-9e68-48fd-bc6d-e3c3554a7dce-jenkins",
+ "vlan-id-outer": 110
+ },
+ {
+ "resource-version": "1529889840079",
+ "neutron-network-id": "ZAKaJQsTlgA",
+ "neutron-subnet-id": "DqmXwxPdIpKQ",
+ "l3-interface-ipv6-prefix-length": 655,
+ "vlan-id-inner": 57,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "3ae4f973-70d6-4ef3-b006-526e518192b9-jenkins",
+ "vlan-id-outer": 299
+ }
+ ],
+ "resource-version": "1529889840055",
+ "is-ip-unnumbered": false,
+ "speed-units": "zPO9liNdSX0",
+ "vlan-interface": "e3d61c90-c6a4-4fcb-93c0-2f568af7ab6f-jenkins",
+ "backdoor-connection": "jtS6nsN9EBxA",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 982,
+ "resource-version": "1529889840061",
+ "neutron-network-id": "2Y8",
+ "neutron-subnet-id": "vLDZaT",
+ "vlan-id-inner": 415,
+ "l3-interface-ipv4-address": "1bb8f77d-8ea7-4893-8c15-a43e3369c67d-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 960
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 104,
+ "resource-version": "1529889840067",
+ "neutron-network-id": "cSuTgMAjn3r",
+ "neutron-subnet-id": "sha47kCBHMpo",
+ "vlan-id-inner": 580,
+ "l3-interface-ipv4-address": "bcacf13b-0067-420d-953f-e22d84ee3af1-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 687
+ }
+ ]
+ }
+ ]
+ },
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "v6-wan-link-ip": "qTVCOp5ygayI0",
+ "interface-name": "9b13abff-cd24-4bed-8a74-e0e06308a5ce-jenkins",
+ "allowed-address-pairs": "IVhz",
+ "prov-status": "olrrQ6Ii",
+ "macaddr": "2iUmJTqseGCD",
+ "interface-role": "KFYUN3C",
+ "selflink": "WZoU",
+ "in-maint": false,
+ "admin-status": "VrOUU",
+ "is-port-mirrored": false,
+ "resource-version": "1529889840098",
+ "is-ip-unnumbered": true,
+ "network-name": "BJX",
+ "management-option": "lN4SRVrP",
+ "interface-id": "QL6",
+ "interface-description": "f0mnjC7ajOATc"
+ },
+ {
+ "v6-wan-link-ip": "TmD",
+ "interface-name": "4590458e-0cc9-4e5b-ae64-01410b33eea7-jenkins",
+ "allowed-address-pairs": "eGq6czv1yR",
+ "prov-status": "DAwBJiDRwvtCT",
+ "macaddr": "ZT3YwlcUJE",
+ "interface-role": "UMD",
+ "selflink": "yTmWD",
+ "in-maint": true,
+ "admin-status": "DxzN",
+ "is-port-mirrored": false,
+ "resource-version": "1529889840092",
+ "is-ip-unnumbered": true,
+ "network-name": "D3aCxtR7zv",
+ "management-option": "n3PD",
+ "interface-id": "iuHyae",
+ "interface-description": "95TF5HyDT"
+ }
+ ]
+ },
+ "interface-name": "a5d58888-7f18-4532-bb9f-cff44f21f764-jenkins",
+ "allowed-address-pairs": "UMBKF",
+ "prov-status": "UjcdQWRP",
+ "macaddr": "mVw",
+ "interface-role": "UP3MbarHtY5",
+ "selflink": "srP",
+ "in-maint": false,
+ "admin-status": "sgSdzaI",
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840123",
+ "neutron-network-id": "b5qrgF24RBQM",
+ "neutron-subnet-id": "1516aM83RE",
+ "l3-interface-ipv6-prefix-length": 841,
+ "vlan-id-inner": 60,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "209a1acb-31bb-454b-a803-1975e14a2b79-jenkins",
+ "vlan-id-outer": 47
+ },
+ {
+ "resource-version": "1529889840117",
+ "neutron-network-id": "swcjYuHNH1kLF",
+ "neutron-subnet-id": "6Is",
+ "l3-interface-ipv6-prefix-length": 341,
+ "vlan-id-inner": 472,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "a1a566eb-0f32-47b1-89c0-97b9e71a5bd1-jenkins",
+ "vlan-id-outer": 907
+ }
+ ],
+ "is-port-mirrored": false,
+ "resource-version": "1529889840017",
+ "is-ip-unnumbered": false,
+ "sriov-vfs": {
+ "sriov-vf": [
+ {
+ "vf-vlan-filter": "Mu5iYcFtXJO",
+ "vf-vlan-strip": false,
+ "neutron-network-id": "1NyV0W",
+ "vf-broadcast-allow": false,
+ "vf-mac-anti-spoof-check": false,
+ "vf-unknown-multicast-allow": false,
+ "pci-id": "a73b8fbc-51df-4856-a9b1-1fdab27eb1c2-jenkins",
+ "vf-mirrors": "Xzff495",
+ "resource-version": "1529889840087",
+ "vf-link-status": "e3o",
+ "vf-mac-filter": "weB9RW0kOj",
+ "vf-insert-stag": true,
+ "vf-vlan-anti-spoof-check": false,
+ "vf-unknown-unicast-allow": false
+ }
+ ]
+ },
+ "network-name": "EfhznvHgA9sc",
+ "management-option": "Z3tcQs1t",
+ "interface-id": "XJFnP9b",
+ "interface-description": "4EW",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 415,
+ "resource-version": "1529889840104",
+ "neutron-network-id": "f6P8vI0vF",
+ "neutron-subnet-id": "FFTJTHg",
+ "vlan-id-inner": 118,
+ "l3-interface-ipv4-address": "4bec049a-3389-4eac-a2aa-366fba5ce65e-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 854
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 182,
+ "resource-version": "1529889840110",
+ "neutron-network-id": "3DGUAT",
+ "neutron-subnet-id": "SOsxiS7G",
+ "vlan-id-inner": 955,
+ "l3-interface-ipv4-address": "7488692d-58df-41c8-90da-ad740c5ee1c4-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 44
+ }
+ ]
+ }
+ ]
+ },
+ "interface-name": "d3ee5116-2a24-4eec-ac0c-5bd4c0d8b591-jenkins",
+ "prov-status": "KNuQwh3R18IcL",
+ "interface-role": "n5Ggwbql",
+ "sriov-pfs": {
+ "sriov-pf": [
+ {
+ "resource-version": "1529889839900",
+ "pf-pci-id": "2415ba55-f754-43f3-8549-8367e12292df-jenkins"
+ }
+ ]
+ },
+ "selflink": "hlcIkDbgLsj5",
+ "speed-value": "eZ9SI",
+ "in-maint": false,
+ "interface-type": "2d47g",
+ "port-description": "zSexZ",
+ "resource-version": "1529889839896",
+ "inv-status": "GCqk",
+ "speed-units": "lhQBqM8rf2HXu"
+ },
+ {
+ "equipment-identifier": "cXNyuU8Lg6TK",
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "v6-wan-link-ip": "kGD",
+ "vlans": {
+ "vlan": [
+ {
+ "vlan-description": "rnsklwtzFgYY",
+ "vpn-key": "TKb",
+ "prov-status": "xQUPC1z",
+ "vlan-id-inner": 267,
+ "vlan-id-outer": 699,
+ "orchestration-status": "2T0C",
+ "speed-value": "S4xMNeI",
+ "in-maint": true,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840210",
+ "neutron-network-id": "CQWLp",
+ "neutron-subnet-id": "8MrdSbIszDA",
+ "l3-interface-ipv6-prefix-length": 707,
+ "vlan-id-inner": 344,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "ba6b944c-05e8-4cb1-959e-b42d5cb70c5a-jenkins",
+ "vlan-id-outer": 961
+ },
+ {
+ "resource-version": "1529889840205",
+ "neutron-network-id": "Hsw4nXwZLQ",
+ "neutron-subnet-id": "JW9lhSp55wX",
+ "l3-interface-ipv6-prefix-length": 325,
+ "vlan-id-inner": 702,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "695e343f-eaea-4a43-bfcb-3d67ec24e090-jenkins",
+ "vlan-id-outer": 232
+ }
+ ],
+ "resource-version": "1529889840187",
+ "is-ip-unnumbered": true,
+ "speed-units": "JhSHmjEpRvYYm",
+ "vlan-interface": "1520c860-c608-4696-a2f4-705b65f6046f-jenkins",
+ "backdoor-connection": "bLB",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 564,
+ "resource-version": "1529889840199",
+ "neutron-network-id": "5BczOGn",
+ "neutron-subnet-id": "eLBW1qhzO3",
+ "vlan-id-inner": 8,
+ "l3-interface-ipv4-address": "8496dd5a-3ad7-4557-8dd6-a433db32615d-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 658
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 228,
+ "resource-version": "1529889840192",
+ "neutron-network-id": "bEA",
+ "neutron-subnet-id": "Tw9wDLBP",
+ "vlan-id-inner": 215,
+ "l3-interface-ipv4-address": "b3482d39-db51-444e-813e-14118a752171-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 805
+ }
+ ]
+ },
+ {
+ "vlan-description": "n8bWn",
+ "vpn-key": "oRujs5y",
+ "prov-status": "SXiegHT",
+ "vlan-id-inner": 513,
+ "vlan-id-outer": 296,
+ "orchestration-status": "INf",
+ "speed-value": "IIbmsMCpmQ",
+ "in-maint": true,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840166",
+ "neutron-network-id": "hyxtLRv",
+ "neutron-subnet-id": "DA6JkUle",
+ "l3-interface-ipv6-prefix-length": 76,
+ "vlan-id-inner": 681,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "5a9be38a-b064-40f1-a253-314fded08cdf-jenkins",
+ "vlan-id-outer": 996
+ },
+ {
+ "resource-version": "1529889840171",
+ "neutron-network-id": "tQQTGDZQj",
+ "neutron-subnet-id": "XbHEt",
+ "l3-interface-ipv6-prefix-length": 266,
+ "vlan-id-inner": 3,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "fd2f49c0-8b02-466a-9395-37fb54037f16-jenkins",
+ "vlan-id-outer": 205
+ }
+ ],
+ "resource-version": "1529889840149",
+ "is-ip-unnumbered": false,
+ "speed-units": "oZUZAVfm64",
+ "vlan-interface": "710ec65a-0d70-45bc-afc8-6ed029670ec2-jenkins",
+ "backdoor-connection": "MzNnZT7R5X1pO",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 769,
+ "resource-version": "1529889840160",
+ "neutron-network-id": "qTcDiVF2ttvIW",
+ "neutron-subnet-id": "qIZMW4Jk512a",
+ "vlan-id-inner": 122,
+ "l3-interface-ipv4-address": "c3b954f9-3948-4d8b-a894-6eb7cc91f607-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 910
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 830,
+ "resource-version": "1529889840154",
+ "neutron-network-id": "fBBC",
+ "neutron-subnet-id": "oXETpyvUOs",
+ "vlan-id-inner": 91,
+ "l3-interface-ipv4-address": "cf5af1e4-3f86-4162-9f43-01ef659282d4-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 90
+ }
+ ]
+ }
+ ]
+ },
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "v6-wan-link-ip": "McYNumNy4",
+ "interface-name": "5ab57276-62ba-4fb8-a99a-f4cc64fe1f6b-jenkins",
+ "allowed-address-pairs": "TVGpW77UF8i",
+ "prov-status": "FRKsQoZx",
+ "macaddr": "pyKHSVQTgpnEw",
+ "interface-role": "lN90EX",
+ "selflink": "tWy30",
+ "in-maint": false,
+ "admin-status": "V6SYyFt",
+ "is-port-mirrored": false,
+ "resource-version": "1529889840224",
+ "is-ip-unnumbered": true,
+ "network-name": "8b3x",
+ "management-option": "IiJ4Ex",
+ "interface-id": "qgH",
+ "interface-description": "77c"
+ },
+ {
+ "v6-wan-link-ip": "BxSqzB3k",
+ "interface-name": "d7193628-997f-4cb8-9772-3ef82d08f7c3-jenkins",
+ "allowed-address-pairs": "wCxdxBIr",
+ "prov-status": "GXcP",
+ "macaddr": "QWcOomv4ZA91",
+ "interface-role": "l5eAS8RS",
+ "selflink": "O9RgzEEvn",
+ "in-maint": true,
+ "admin-status": "ug2XllNOh",
+ "is-port-mirrored": false,
+ "resource-version": "1529889840229",
+ "is-ip-unnumbered": true,
+ "network-name": "la6oQgvjY4Z5",
+ "management-option": "PGNlqnpH",
+ "interface-id": "8otuL737oC7",
+ "interface-description": "BqEJ3h"
+ }
+ ]
+ },
+ "interface-name": "57964a2a-8d5e-48af-9ac0-089af4d8c968-jenkins",
+ "allowed-address-pairs": "cwJk0af9GN3",
+ "prov-status": "CPok",
+ "macaddr": "0vMHIE",
+ "interface-role": "Kkyw",
+ "selflink": "OLNd",
+ "in-maint": false,
+ "admin-status": "0dyKQiCmX",
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840254",
+ "neutron-network-id": "uPOdktFWuZjH",
+ "neutron-subnet-id": "1Vy9Xgxjds",
+ "l3-interface-ipv6-prefix-length": 431,
+ "vlan-id-inner": 313,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "64e3996d-7b54-4e05-b07e-fb5f2f2966c8-jenkins",
+ "vlan-id-outer": 972
+ },
+ {
+ "resource-version": "1529889840247",
+ "neutron-network-id": "H29D9C2hy",
+ "neutron-subnet-id": "sD4RTy",
+ "l3-interface-ipv6-prefix-length": 800,
+ "vlan-id-inner": 597,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "a80bd4b0-93b9-421d-a7a1-0da425116a1a-jenkins",
+ "vlan-id-outer": 584
+ }
+ ],
+ "is-port-mirrored": false,
+ "resource-version": "1529889840143",
+ "is-ip-unnumbered": true,
+ "sriov-vfs": {
+ "sriov-vf": [
+ {
+ "vf-vlan-filter": "RNYicsjOHW39H",
+ "vf-vlan-strip": false,
+ "neutron-network-id": "pbj6W",
+ "vf-broadcast-allow": false,
+ "vf-mac-anti-spoof-check": false,
+ "vf-unknown-multicast-allow": true,
+ "pci-id": "ef272d07-37f2-4c42-934f-36b7ea9f40bb-jenkins",
+ "vf-mirrors": "Oc3iPkPk",
+ "resource-version": "1529889840218",
+ "vf-link-status": "fYgzXpWSskZ06",
+ "vf-mac-filter": "xgRUu",
+ "vf-insert-stag": true,
+ "vf-vlan-anti-spoof-check": false,
+ "vf-unknown-unicast-allow": false
+ }
+ ]
+ },
+ "network-name": "qlnWBvDxGh",
+ "management-option": "zvkV4w",
+ "interface-id": "doAsSV",
+ "interface-description": "rS4CU",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 665,
+ "resource-version": "1529889840235",
+ "neutron-network-id": "dQO32ksNO1i",
+ "neutron-subnet-id": "fIRPuXsfHl3RH",
+ "vlan-id-inner": 899,
+ "l3-interface-ipv4-address": "5c11ec1e-1d13-4f28-99f6-71fcfdb8f600-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 458
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 226,
+ "resource-version": "1529889840241",
+ "neutron-network-id": "8C2IrMoc",
+ "neutron-subnet-id": "6RGtdz",
+ "vlan-id-inner": 835,
+ "l3-interface-ipv4-address": "edf54c12-22e9-4ff3-9ae4-1b2ac66e6ac0-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 905
+ }
+ ]
+ },
+ {
+ "v6-wan-link-ip": "UBtvQADW",
+ "vlans": {
+ "vlan": [
+ {
+ "vlan-description": "iK8n",
+ "vpn-key": "hfhIuxo4",
+ "prov-status": "P2KBr",
+ "vlan-id-inner": 952,
+ "vlan-id-outer": 335,
+ "orchestration-status": "tVaURe9iKl",
+ "speed-value": "et4UkQPTAh8N",
+ "in-maint": false,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840323",
+ "neutron-network-id": "uCLrTQcl7",
+ "neutron-subnet-id": "dCqtBvKBlmX",
+ "l3-interface-ipv6-prefix-length": 613,
+ "vlan-id-inner": 117,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "230b181d-717f-43d7-9bb4-9ad1bf957a91-jenkins",
+ "vlan-id-outer": 427
+ },
+ {
+ "resource-version": "1529889840317",
+ "neutron-network-id": "yAk",
+ "neutron-subnet-id": "qXcN",
+ "l3-interface-ipv6-prefix-length": 396,
+ "vlan-id-inner": 964,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "d525c688-69c3-48df-b4ef-5f5a4c791598-jenkins",
+ "vlan-id-outer": 640
+ }
+ ],
+ "resource-version": "1529889840300",
+ "is-ip-unnumbered": false,
+ "speed-units": "dSElck",
+ "vlan-interface": "63adb4ad-4349-4bbf-8e16-62b1d245ac4a-jenkins",
+ "backdoor-connection": "FdE3",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 418,
+ "resource-version": "1529889840311",
+ "neutron-network-id": "qwlh3SoZoj",
+ "neutron-subnet-id": "7fAwEuJ",
+ "vlan-id-inner": 753,
+ "l3-interface-ipv4-address": "99bb541b-7614-4cda-a74f-acebdf50d60e-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 220
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 811,
+ "resource-version": "1529889840305",
+ "neutron-network-id": "wH1eb",
+ "neutron-subnet-id": "ncQ8T9",
+ "vlan-id-inner": 265,
+ "l3-interface-ipv4-address": "1f80bd34-aa39-400e-b8d9-a858cc4bec25-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 381
+ }
+ ]
+ },
+ {
+ "vlan-description": "AmUPyMpoz",
+ "vpn-key": "zS9eKhmKY",
+ "prov-status": "bW2IFjyyrb",
+ "vlan-id-inner": 852,
+ "vlan-id-outer": 777,
+ "orchestration-status": "sjwcTB",
+ "speed-value": "1tE5qyCpE",
+ "in-maint": true,
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840292",
+ "neutron-network-id": "j866pg4Pm",
+ "neutron-subnet-id": "6Wyki",
+ "l3-interface-ipv6-prefix-length": 307,
+ "vlan-id-inner": 182,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "f6d75e58-37d6-4b7e-acb8-2e99f9b4f3c6-jenkins",
+ "vlan-id-outer": 204
+ },
+ {
+ "resource-version": "1529889840286",
+ "neutron-network-id": "1PkEbG6dYqTfi",
+ "neutron-subnet-id": "JZh6Tirqre",
+ "l3-interface-ipv6-prefix-length": 110,
+ "vlan-id-inner": 655,
+ "is-floating": true,
+ "l3-interface-ipv6-address": "36dcfb46-a281-43ec-9f19-57ad77388b86-jenkins",
+ "vlan-id-outer": 260
+ }
+ ],
+ "resource-version": "1529889840269",
+ "is-ip-unnumbered": true,
+ "speed-units": "Vde",
+ "vlan-interface": "64aefea8-d550-4328-9528-c6c20ebdcc83-jenkins",
+ "backdoor-connection": "1IYINR4x",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 807,
+ "resource-version": "1529889840274",
+ "neutron-network-id": "IOCxD0A",
+ "neutron-subnet-id": "fmUBSv4xn",
+ "vlan-id-inner": 695,
+ "l3-interface-ipv4-address": "ca68fb8b-47f5-452b-9297-5bb1bf3df3cb-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 320
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 412,
+ "resource-version": "1529889840280",
+ "neutron-network-id": "825jJkD4",
+ "neutron-subnet-id": "xm9E",
+ "vlan-id-inner": 730,
+ "l3-interface-ipv4-address": "0e19582a-6f8b-4fb5-bf49-b8ee1d94b300-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 796
+ }
+ ]
+ }
+ ]
+ },
+ "l-interfaces": {
+ "l-interface": [
+ {
+ "v6-wan-link-ip": "fRVDB",
+ "interface-name": "1afbcfe1-fd3f-45e9-8c10-c03687bd155e-jenkins",
+ "allowed-address-pairs": "pt1w8Myf3CMX",
+ "prov-status": "aEeKbHcU13Bya",
+ "macaddr": "W6w1yt4XkZc",
+ "interface-role": "cqr1D",
+ "selflink": "0Q1th8cWl",
+ "in-maint": true,
+ "admin-status": "FyxEvTkdiprO",
+ "is-port-mirrored": true,
+ "resource-version": "1529889840342",
+ "is-ip-unnumbered": false,
+ "network-name": "NABSQ7",
+ "management-option": "4seC3CZ0zmyox",
+ "interface-id": "vM1",
+ "interface-description": "hML"
+ },
+ {
+ "v6-wan-link-ip": "wWDvY3k",
+ "interface-name": "e1f17f18-2415-4af9-b503-337117a3895a-jenkins",
+ "allowed-address-pairs": "PoPZQKwe5",
+ "prov-status": "lrbHN1Glz",
+ "macaddr": "z1z1PLeAU",
+ "interface-role": "MZW4",
+ "selflink": "8MXx36",
+ "in-maint": true,
+ "admin-status": "Togx",
+ "is-port-mirrored": false,
+ "resource-version": "1529889840336",
+ "is-ip-unnumbered": false,
+ "network-name": "IgN0B6",
+ "management-option": "kYE1hmpQcbv",
+ "interface-id": "RISQle6r",
+ "interface-description": "HxiEkqQeZOJ"
+ }
+ ]
+ },
+ "interface-name": "55595739-f1c1-40fd-8e02-ed26c8a5a273-jenkins",
+ "allowed-address-pairs": "Ku1FptLLsb",
+ "prov-status": "swt3YHhr68",
+ "macaddr": "SFuEED5Q4",
+ "interface-role": "j1Szdb",
+ "selflink": "TWML",
+ "in-maint": true,
+ "admin-status": "13qB1qn1IYJHY",
+ "l3-interface-ipv6-address-list": [
+ {
+ "resource-version": "1529889840360",
+ "neutron-network-id": "Q2jys",
+ "neutron-subnet-id": "qfV9kgabkzxT",
+ "l3-interface-ipv6-prefix-length": 408,
+ "vlan-id-inner": 856,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "33d879a4-cffc-4c9e-b3e3-ca8285904837-jenkins",
+ "vlan-id-outer": 343
+ },
+ {
+ "resource-version": "1529889840367",
+ "neutron-network-id": "lMt10eoK2AQoa",
+ "neutron-subnet-id": "1skENPqW",
+ "l3-interface-ipv6-prefix-length": 320,
+ "vlan-id-inner": 89,
+ "is-floating": false,
+ "l3-interface-ipv6-address": "86fac1bc-375d-4d9f-97e7-1e7bef843039-jenkins",
+ "vlan-id-outer": 203
+ }
+ ],
+ "is-port-mirrored": true,
+ "resource-version": "1529889840262",
+ "is-ip-unnumbered": false,
+ "sriov-vfs": {
+ "sriov-vf": [
+ {
+ "vf-vlan-filter": "ZzMNbVF3sT",
+ "vf-vlan-strip": false,
+ "neutron-network-id": "yThOSXDJtt",
+ "vf-broadcast-allow": false,
+ "vf-mac-anti-spoof-check": true,
+ "vf-unknown-multicast-allow": true,
+ "pci-id": "bf38b0ee-0d9e-4aac-b51d-4e0091063616-jenkins",
+ "vf-mirrors": "zRC0L4imSH",
+ "resource-version": "1529889840331",
+ "vf-link-status": "XMxqQi5QhOrW",
+ "vf-mac-filter": "bieb3t",
+ "vf-insert-stag": false,
+ "vf-vlan-anti-spoof-check": true,
+ "vf-unknown-unicast-allow": true
+ }
+ ]
+ },
+ "network-name": "QLvohj",
+ "management-option": "fCIqRUOOdh",
+ "interface-id": "iGkiFK",
+ "interface-description": "ERxXZI",
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-prefix-length": 153,
+ "resource-version": "1529889840348",
+ "neutron-network-id": "JehiIKkHvx",
+ "neutron-subnet-id": "Mj6TT",
+ "vlan-id-inner": 333,
+ "l3-interface-ipv4-address": "c8fe829f-04e1-448b-bebc-bd519b2750c8-jenkins",
+ "is-floating": true,
+ "vlan-id-outer": 145
+ },
+ {
+ "l3-interface-ipv4-prefix-length": 657,
+ "resource-version": "1529889840354",
+ "neutron-network-id": "PYwcY36hEY",
+ "neutron-subnet-id": "17Hs1AFpT",
+ "vlan-id-inner": 815,
+ "l3-interface-ipv4-address": "26764e8a-ad03-46e0-9031-4cbc400b1911-jenkins",
+ "is-floating": false,
+ "vlan-id-outer": 435
+ }
+ ]
+ }
+ ]
+ },
+ "interface-name": "dfa51737-16a5-4061-a295-bc5e51b31238-jenkins",
+ "prov-status": "KyURisF3pLj",
+ "interface-role": "IEn2AUkIiYlh",
+ "sriov-pfs": {
+ "sriov-pf": [
+ {
+ "resource-version": "1529889840138",
+ "pf-pci-id": "99c1731b-7ea5-4af0-9b49-fc447fc02a7f-jenkins"
+ }
+ ]
+ },
+ "selflink": "dCPBnieGuf",
+ "speed-value": "3kz6VhwJf",
+ "in-maint": true,
+ "interface-type": "sqBpLbc",
+ "port-description": "5kzHuoA",
+ "resource-version": "1529889840133",
+ "inv-status": "kH1",
+ "speed-units": "saqVmt9"
+ }
+ ]
+ },
+ "resource-version": "1529889839890",
+ "ram-in-megabytes": 886,
+ "ipaddress-v4-aim": "14Ku",
+ "management-option": "qBr",
+ "internet-topology": "eNTF",
+ "host-profile": "cd3AI9U2izq6"
+ }
+} \ No newline at end of file
diff --git a/src/test/resources/test/payloads/dmaapEvents/nos.json b/src/test/resources/test/payloads/dmaapEvents/nos.json
new file mode 100644
index 0000000..3efe88f
--- /dev/null
+++ b/src/test/resources/test/payloads/dmaapEvents/nos.json
@@ -0,0 +1,96 @@
+{
+ "cambria.partition": "AAI",
+ "event-header": {
+ "severity": "NORMAL",
+ "entity-type": "nos-server",
+ "top-entity-type": "cloud-region",
+ "entity-link": "/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/onap-cloud-owner/AAIAIC25/tenants/tenant/tenant-987654321-8991-ps2418/nos-servers/nos-server/nos-server-987654321-8991-ps2418",
+ "event-type": "AAI-EVENT",
+ "domain": "uINT1",
+ "action": "CREATE",
+ "sequence-number": "0",
+ "id": "90105aab-78f6-4d83-83b4-48488998a9bd",
+ "source-name": "SDNC",
+ "version": "v13",
+ "timestamp": "20180625-15:29:20:696"
+ },
+ "entity": {
+ "tenants": {
+ "tenant": [
+ {
+ "nos-servers": {
+ "nos-server": [
+ {
+ "nos-server-selflink": "example-nos-server-selflink-val-56832",
+ "relationship-list": {
+ "relationship": [
+ {
+ "related-to": "generic-vnf",
+ "relationship-data": [
+ {
+ "relationship-value": "generic-vnf-987654321-89911-ps2418",
+ "relationship-key": "generic-vnf.vnf-id"
+ }
+ ],
+ "related-link": "/aai/v13/network/generic-vnfs/generic-vnf/generic-vnf-987654321-89911-ps2418",
+ "relationship-label": "tosca.relationships.HostedOn",
+ "related-to-property": [
+ {
+ "property-key": "generic-vnf.vnf-name",
+ "property-value": "example-vnf-name-val-21594"
+ }
+ ]
+ },
+ {
+ "related-to": "generic-vnf",
+ "relationship-data": [
+ {
+ "relationship-value": "generic-vnf-987654321-89922-ps2418",
+ "relationship-key": "generic-vnf.vnf-id"
+ }
+ ],
+ "related-link": "/aai/v13/network/generic-vnfs/generic-vnf/generic-vnf-987654321-89922-ps2418",
+ "relationship-label": "tosca.relationships.HostedOn",
+ "related-to-property": [
+ {
+ "property-key": "generic-vnf.vnf-name",
+ "property-value": "example-vnf-name-val-21594"
+ }
+ ]
+ },
+ {
+ "related-to": "pserver",
+ "relationship-data": [
+ {
+ "relationship-value": "pserver-987654321-8991-ps2418",
+ "relationship-key": "pserver.hostname"
+ }
+ ],
+ "related-link": "/aai/v13/cloud-infrastructure/pservers/pserver/pserver-987654321-8991-ps2418",
+ "relationship-label": "tosca.relationships.HostedOn",
+ "related-to-property": [
+ {
+ "property-key": "pserver.pserver-name2"
+ }
+ ]
+ }
+ ]
+ },
+ "in-maint": true,
+ "vendor": "example-vendor-val-78053",
+ "resource-version": "1529940560508",
+ "nos-server-name": "example-nos-server-name-val-4811-nos-server-987654321-8991-ps2418",
+ "nos-server-id": "nos-server-987654321-8991-ps2418",
+ "prov-status": "example-prov-status-val-20734"
+ }
+ ]
+ },
+ "tenant-id": "tenant-987654321-8991-ps2418",
+ "tenant-name": "example-tenant-name-val-19302"
+ }
+ ]
+ },
+ "cloud-owner": "onap-cloud-owner",
+ "cloud-region-id": "AAIAIC25"
+ }
+} \ No newline at end of file
diff --git a/src/test/resources/test/payloads/dmaapEvents/vce.json b/src/test/resources/test/payloads/dmaapEvents/vce.json
new file mode 100644
index 0000000..adae7ee
--- /dev/null
+++ b/src/test/resources/test/payloads/dmaapEvents/vce.json
@@ -0,0 +1,81 @@
+{
+ "cambria.partition": "AAI",
+ "event-header": {
+ "severity": "NORMAL",
+ "entity-type": "vce",
+ "top-entity-type": "vce",
+ "entity-link": "/aai/v13/network/vces/vce/vce-987654321-311-ps2418",
+ "event-type": "AAI-EVENT",
+ "domain": "uINT1",
+ "action": "DELETE",
+ "sequence-number": "0",
+ "id": "b10f1221-1c3f-42d2-987b-3071818cb613",
+ "source-name": "FitNesse-Test-ps2418",
+ "version": "v13",
+ "timestamp": "20180627-16:35:28:464"
+ },
+ "entity": {
+ "entitlements": {
+ "entitlement": [
+ {
+ "resource-version": "1530117237423",
+ "group-uuid": "group-uuid-2-vce-987654321-311-ps2418",
+ "resource-uuid": "example-resource-uuid-val-8433"
+ }
+ ]
+ },
+ "service-id": "example-service-id-val-62283",
+ "vnf-id": "vce-987654321-311-ps2418",
+ "vnf-name2": "example-vnf-name2-val-9403",
+ "regional-resource-zone": "example-regional-resource-zone-val-78515",
+ "v6-vce-wan-address": "example-v6-vce-wan-address-val-36157",
+ "prov-status": "example-prov-status-val-30289",
+ "operational-status": "example-operational-status-val-52645",
+ "vpe-id": "example-vpe-id-val-22112",
+ "equipment-role": "example-equipment-role-val-15655",
+ "license-key": "example-license-key-val-94096",
+ "ipv4-oam-address": "example-ipv4-oam-address-val-38828",
+ "ipv4-loopback0-address": "example-ipv4-loopback0-address-val-22629",
+ "entitlement-resource-uuid": "example-entitlement-resource-uuid-val-545",
+ "vnf-type": "example-vnf-type-val-4945",
+ "orchestration-status": "example-orchestration-status-val-89335",
+ "licenses": {
+ "license": [
+ {
+ "resource-version": "1530117237414",
+ "group-uuid": "group-uuid-vce-987654321-311-ps2418",
+ "resource-uuid": "example-resource-uuid-val-72009"
+ }
+ ]
+ },
+ "heat-stack-id": "example-heat-stack-id-val-97607",
+ "resource-version": "1530117237387",
+ "mso-catalog-key": "example-mso-catalog-key-val-27829",
+ "vnf-name": "example-vnf-name-val-72342",
+ "port-groups": {
+ "port-group": [
+ {
+ "interface-role": "example-interface-role-val-37524",
+ "cvlan-tags": {
+ "cvlan-tag-entry": [
+ {
+ "resource-version": "1530117237399",
+ "cvlan-tag": 37491872
+ }
+ ]
+ },
+ "resource-version": "1530117237394",
+ "heat-stack-id": "example-heat-stack-id-val-90634",
+ "port-group-name": "example-port-group-name-val-2717",
+ "neutron-network-id": "example-neutron-network-id-val-27420",
+ "port-group-id": "example-port-group-id-val-16749",
+ "mso-catalog-key": "example-mso-catalog-key-val-96458",
+ "neutron-network-name": "example-neutron-network-name-val-98499",
+ "switch-name": "example-switch-name-val-78257",
+ "interface-id": "port-group-interface-id-vce-987654321-311-ps2418",
+ "orchestration-status": "example-orchestration-status-val-54586"
+ }
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/startSpring.bat b/startSpring.bat
new file mode 100644
index 0000000..9122fe2
--- /dev/null
+++ b/startSpring.bat
@@ -0,0 +1,4 @@
+@echo off
+title run Set debug and run ajsc for aai module
+CALL set-debug-port.bat
+START mvn spring-boot:run \ No newline at end of file