aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
104 files changed, 12993 insertions, 0 deletions
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