aboutsummaryrefslogtreecommitdiffstats
path: root/champ-service/src
diff options
context:
space:
mode:
authormichaere <michaere@amdocs.com>2018-03-05 16:33:32 +0000
committermichaere <michaere@amdocs.com>2018-03-07 11:17:22 +0000
commitc74f7b13b573386e70c10721fc391624ee792ed6 (patch)
treeb44995474ff938b4b03c9b234f95b71bc75d6b79 /champ-service/src
parent9fc28cff11a4b570618c0f533ce9de6209a5dd0c (diff)
Port champ-microservice project restructure
Includes project restructure and introduction of a parent pom. The original source folder and core functionality is now held within champ-lib, with champ-service forming the ajsc microservice from which it injects champ-lib core functionality. Issue-ID: AAI-813 Change-Id: I2ce0c4a70e485665276e7955572de23969deb706 Signed-off-by: michaere <michaere@amdocs.com>
Diffstat (limited to 'champ-service/src')
-rw-r--r--champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/conf/jaxrsBeans.groovy11
-rw-r--r--champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/docs/README.txt1
-rw-r--r--champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/lib/README.txt1
-rw-r--r--champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/champ.route4
-rw-r--r--champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/jaxrsExample.route5
-rw-r--r--champ-service/src/main/assemble/ajsc_module_assembly.xml66
-rw-r--r--champ-service/src/main/assemble/ajsc_props_assembly.xml23
-rw-r--r--champ-service/src/main/assemble/ajsc_runtime_assembly.xml44
-rw-r--r--champ-service/src/main/bin/start.sh94
-rw-r--r--champ-service/src/main/config/ajsc-chef.jksbin0 -> 5256 bytes
-rw-r--r--champ-service/src/main/config/ajsc-jetty.xml114
-rw-r--r--champ-service/src/main/config/ajsc-override-web.xml50
-rw-r--r--champ-service/src/main/config/ajscJetty.jksbin0 -> 3736 bytes
-rw-r--r--champ-service/src/main/config/cadi.properties28
-rw-r--r--champ-service/src/main/config/jul-redirect.properties13
-rw-r--r--champ-service/src/main/config/keyfile27
-rw-r--r--champ-service/src/main/config/runner-web.xml94
-rw-r--r--champ-service/src/main/docker/Dockerfile34
-rw-r--r--champ-service/src/main/java/org/onap/champ/ChampRESTAPI.java568
-rw-r--r--champ-service/src/main/java/org/onap/champ/async/ChampAsyncRequestProcessor.java327
-rw-r--r--champ-service/src/main/java/org/onap/champ/async/ChampAsyncResponsePublisher.java160
-rw-r--r--champ-service/src/main/java/org/onap/champ/entity/ChampObjectDeserializer.java67
-rw-r--r--champ-service/src/main/java/org/onap/champ/entity/ChampObjectSerializer.java54
-rw-r--r--champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipDeserializer.java73
-rw-r--r--champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipSerializer.java55
-rw-r--r--champ-service/src/main/java/org/onap/champ/event/GraphEvent.java245
-rw-r--r--champ-service/src/main/java/org/onap/champ/event/GraphEventEdge.java221
-rw-r--r--champ-service/src/main/java/org/onap/champ/event/GraphEventVertex.java187
-rw-r--r--champ-service/src/main/java/org/onap/champ/exception/ChampServiceException.java62
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/ChampDataService.java355
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/ChampThreadFactory.java47
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/ChampTransactionCache.java77
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/ChampUUIDService.java115
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/EchoService.java54
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/logging/ChampMsgs.java130
-rw-r--r--champ-service/src/main/java/org/onap/champ/service/logging/LoggingUtil.java92
-rw-r--r--champ-service/src/main/java/org/onap/champ/util/ChampProperties.java53
-rw-r--r--champ-service/src/main/java/org/onap/champ/util/ChampServiceConstants.java14
-rw-r--r--champ-service/src/main/resources/META-INF/services/javax.ws.rs.client.ClientBuilder1
-rw-r--r--champ-service/src/main/resources/logging/ChampMsgs.properties78
-rw-r--r--champ-service/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context1
-rw-r--r--champ-service/src/main/runtime/context/default#0.context1
-rw-r--r--champ-service/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json1
-rw-r--r--champ-service/src/main/runtime/shiroRole/ajscadmin.json1
-rw-r--r--champ-service/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json1
-rw-r--r--champ-service/src/main/runtime/shiroRole/contextadmin#default.json1
-rw-r--r--champ-service/src/main/runtime/shiroUser/ajsc.json1
-rw-r--r--champ-service/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json1
-rw-r--r--champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json1
-rw-r--r--champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json1
50 files changed, 3654 insertions, 0 deletions
diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/conf/jaxrsBeans.groovy b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/conf/jaxrsBeans.groovy
new file mode 100644
index 0000000..17d80a4
--- /dev/null
+++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/conf/jaxrsBeans.groovy
@@ -0,0 +1,11 @@
+beans{
+ xmlns cxf: "http://camel.apache.org/schema/cxf"
+ xmlns jaxrs: "http://cxf.apache.org/jaxrs"
+ xmlns util: "http://www.springframework.org/schema/util"
+
+ echoService(org.onap.champ.service.EchoService)
+
+ util.list(id: 'echoServices') {
+ ref(bean:'echoService')
+ }
+} \ No newline at end of file
diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/docs/README.txt b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/docs/README.txt
new file mode 100644
index 0000000..3707179
--- /dev/null
+++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/docs/README.txt
@@ -0,0 +1 @@
+Place any docs here that you want to access within the ajsc upon deployment of your service.
diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/lib/README.txt b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/lib/README.txt
new file mode 100644
index 0000000..639e21b
--- /dev/null
+++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/lib/README.txt
@@ -0,0 +1 @@
+3rd party JAR's needed by your jars (if any) for a ajsc deployment package go here... \ No newline at end of file
diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/champ.route b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/champ.route
new file mode 100644
index 0000000..cf8d115
--- /dev/null
+++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/champ.route
@@ -0,0 +1,4 @@
+<route xmlns="http://camel.apache.org/schema/spring" trace="true">
+ <from uri="att-dme2-servlet:///champ-service/v1/?matchOnUriPrefix=true" />
+ <to uri="cxfbean:champRestService" />
+</route> \ No newline at end of file
diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/jaxrsExample.route b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/jaxrsExample.route
new file mode 100644
index 0000000..a132030
--- /dev/null
+++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/jaxrsExample.route
@@ -0,0 +1,5 @@
+<route xmlns="http://camel.apache.org/schema/spring" trace="true">
+ <from uri="att-dme2-servlet:///echo-service/?matchOnUriPrefix=true" />
+ <to uri="cxfbean:echoServices" />
+</route>
+
diff --git a/champ-service/src/main/assemble/ajsc_module_assembly.xml b/champ-service/src/main/assemble/ajsc_module_assembly.xml
new file mode 100644
index 0000000..4ec4e28
--- /dev/null
+++ b/champ-service/src/main/assemble/ajsc_module_assembly.xml
@@ -0,0 +1,66 @@
+<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>${version}</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/routes/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/routes/</outputDirectory>
+ <includes>
+ <include>*.route</include>
+ </includes>
+
+ </fileSet>
+
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/docs/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/docs/</outputDirectory>
+ <includes>
+ <include>*.*</include>
+ <!-- <include>*.vm</include> -->
+ </includes>
+
+ </fileSet>
+
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/lib/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/lib/</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+
+ </fileSet>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/extJars/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/extJars/</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+
+ <!-- also try to grab outputs from the "jar" plugin's package phase -->
+ <fileSet>
+ <directory>${project.basedir}/target/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/lib/</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/conf/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/conf/</outputDirectory>
+ <includes>
+ <include>*.*</include>
+ </includes>
+
+ </fileSet>
+ </fileSets>
+
+</assembly>
+
diff --git a/champ-service/src/main/assemble/ajsc_props_assembly.xml b/champ-service/src/main/assemble/ajsc_props_assembly.xml
new file mode 100644
index 0000000..5b8a6fa
--- /dev/null
+++ b/champ-service/src/main/assemble/ajsc_props_assembly.xml
@@ -0,0 +1,23 @@
+<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>${version}_properties</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/props</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/props/</outputDirectory>
+ <includes>
+ <include>*.props</include>
+ </includes>
+
+ </fileSet>
+
+ </fileSets>
+
+</assembly>
+
diff --git a/champ-service/src/main/assemble/ajsc_runtime_assembly.xml b/champ-service/src/main/assemble/ajsc_runtime_assembly.xml
new file mode 100644
index 0000000..e37d366
--- /dev/null
+++ b/champ-service/src/main/assemble/ajsc_runtime_assembly.xml
@@ -0,0 +1,44 @@
+<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>runtimeEnvironment</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/context/</directory>
+ <outputDirectory>runtime/context/</outputDirectory>
+ <includes>
+ <include>*.context</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/serviceProperties/</directory>
+ <outputDirectory>runtime/serviceProperties/</outputDirectory>
+ <includes>
+ <include>*.props</include>
+ </includes>
+ </fileSet><fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/shiroRole</directory>
+ <outputDirectory>runtime/shiroRole/</outputDirectory>
+ <includes>
+ <include>*.json</include>
+ </includes>
+ </fileSet><fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/shiroUser</directory>
+ <outputDirectory>runtime/shiroUser/</outputDirectory>
+ <includes>
+ <include>*.json</include>
+ </includes>
+ </fileSet><fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/shiroUserRole</directory>
+ <outputDirectory>runtime/shiroUserRole</outputDirectory>
+ <includes>
+ <include>*.json</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly> \ No newline at end of file
diff --git a/champ-service/src/main/bin/start.sh b/champ-service/src/main/bin/start.sh
new file mode 100644
index 0000000..de8a4fb
--- /dev/null
+++ b/champ-service/src/main/bin/start.sh
@@ -0,0 +1,94 @@
+#!/bin/sh
+#
+# ============LICENSE_START==========================================
+# org.onap.aai
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2017 Amdocs
+# ===================================================================
+# 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.
+#
+
+
+BASEDIR="/opt/app/champ-service/"
+AJSC_HOME="$BASEDIR"
+AJSC_CONF_HOME="$AJSC_HOME/bundleconfig/"
+
+if [ -z "$CONFIG_HOME" ]; then
+ echo "CONFIG_HOME must be set in order to start up process"
+ exit 1
+fi
+
+if [ -z "$KEY_STORE_PASSWORD" ]; then
+ echo "KEY_STORE_PASSWORD must be set in order to start up process"
+ exit 1
+else
+ echo "KEY_STORE_PASSWORD=$KEY_STORE_PASSWORD\n" >> $AJSC_CONF_HOME/etc/sysprops/sys-props.properties
+fi
+
+if [ -z "$KEY_MANAGER_PASSWORD" ]; then
+ echo "KEY_MANAGER_PASSWORD must be set in order to start up process"
+ exit 1
+else
+ echo "KEY_MANAGER_PASSWORD=$KEY_MANAGER_PASSWORD\n" >> $AJSC_CONF_HOME/etc/sysprops/sys-props.properties
+fi
+
+# Add any spring bean configuration files to the Gizmo deployment
+if [ -n "$SERVICE_BEANS" ]; then
+ echo "Adding the following dynamic service beans to the deployment: "
+ mkdir -p /tmp/champ-service/v1/conf
+ for f in `ls $SERVICE_BEANS`
+ do
+ cp $SERVICE_BEANS/$f /tmp/champ-service/v1/conf
+ echo "Adding dynamic service bean $SERVICE_BEANS/$f"
+ done
+ jar uf /opt/app/champ-service/services/champ-service_v1.zip* -C /tmp/ champ-service
+ rm -rf /tmp/champ-service
+fi
+
+CLASSPATH="$AJSC_HOME/lib/*"
+CLASSPATH="$CLASSPATH:$AJSC_HOME/extJars/"
+CLASSPATH="$CLASSPATH:$AJSC_HOME/etc/"
+
+# Check to see if the provided implementation exists in the image and add it to the classpath
+for file in $( find ${BASEDIR}graph-deps/* -maxdepth 0 -type d ); do
+ CURRIMPL=$(echo $file | cut -d"/" -f6)
+ if [ "x$GRAPHIMPL" = "x$CURRIMPL" ]; then
+ CLASSPATH_GRAPHIMPL=$file
+ echo "Setting up graph implementation of $GRAPHIMPL"
+ else
+ SUPPORTED_GRAPHIMPL="$SUPPORTED_GRAPHIMPL $CURRIMPL"
+ fi
+done
+if [ -n "$CLASSPATH_GRAPHIMPL" ]; then
+ cp $CLASSPATH_GRAPHIMPL/* $AJSC_HOME/extJars/
+else
+ echo "Configured graph implementation '$GRAPHIMPL' is not supported. Acceptable implementations are one of: $SUPPORTED_GRAPHIMPL"
+ exit 1
+fi
+
+PROPS="-DAJSC_HOME=$AJSC_HOME"
+PROPS="$PROPS -DAJSC_CONF_HOME=$BASEDIR/bundleconfig/"
+PROPS="$PROPS -Dlogback.configurationFile=$BASEDIR/bundleconfig/etc/logback.xml"
+PROPS="$PROPS -DAJSC_SHARED_CONFIG=$AJSC_CONF_HOME"
+PROPS="$PROPS -DAJSC_SERVICE_NAMESPACE=champ-service"
+PROPS="$PROPS -DAJSC_SERVICE_VERSION=v1"
+PROPS="$PROPS -Dserver.port=9522"
+PROPS="$PROPS -DCONFIG_HOME=$CONFIG_HOME"
+JVM_MAX_HEAP=${MAX_HEAP:-1024}
+
+echo $CLASSPATH
+
+exec java -Xmx${JVM_MAX_HEAP}m $PROPS -classpath $CLASSPATH com.att.ajsc.runner.Runner context=// sslport=9522
diff --git a/champ-service/src/main/config/ajsc-chef.jks b/champ-service/src/main/config/ajsc-chef.jks
new file mode 100644
index 0000000..aeca770
--- /dev/null
+++ b/champ-service/src/main/config/ajsc-chef.jks
Binary files differ
diff --git a/champ-service/src/main/config/ajsc-jetty.xml b/champ-service/src/main/config/ajsc-jetty.xml
new file mode 100644
index 0000000..98cc02e
--- /dev/null
+++ b/champ-service/src/main/config/ajsc-jetty.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<!-- Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. -->
+<Configure id="ajsc-server" class="org.eclipse.jetty.server.Server">
+ <!-- DO NOT REMOVE!!!! This is setting up the AJSC Context -->
+ <New id="ajscContext" class="org.eclipse.jetty.webapp.WebAppContext">
+ <Set name="contextPath"><SystemProperty name="AJSC_CONTEXT_PATH" /></Set>
+ <Set name="extractWAR">true</Set>
+ <Set name="tempDirectory"><SystemProperty name="AJSC_TEMP_DIR" /></Set>
+ <Set name="war"><SystemProperty name="AJSC_WAR_PATH" /></Set>
+ <Set name="descriptor"><SystemProperty name="AJSC_HOME" />/etc/runner-web.xml</Set>
+ <Set name="overrideDescriptor"><SystemProperty name="AJSC_HOME" />/etc/ajsc-override-web.xml</Set>
+ <Set name="throwUnavailableOnStartupException">true</Set>
+ <Set name="servletHandler">
+ <New class="org.eclipse.jetty.servlet.ServletHandler">
+ <Set name="startWithUnavailable">false</Set>
+ </New>
+ </Set>
+ <Set name="extraClasspath"><SystemProperty name="AJSC_HOME" />/extJars/champ-service.jar,<SystemProperty name="AJSC_HOME" />/extJars/json-20160212.jar,<SystemProperty name="AJSC_HOME" />/extJars/javax.ws.rs-api-2.0.1.jar,<SystemProperty name="AJSC_HOME" />/extJars/jersey-client-2.23.jar</Set>
+ </New>
+
+ <Set name="handler">
+ <New id="Contexts"
+ class="org.eclipse.jetty.server.handler.ContextHandlerCollection">
+ <Set name="Handlers">
+ <Array type="org.eclipse.jetty.webapp.WebAppContext">
+ <Item>
+ <Ref refid="ajscContext" />
+ </Item>
+ </Array>
+ </Set>
+ </New>
+ </Set>
+
+ <Call name="addBean">
+ <Arg>
+ <New id="DeploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager">
+ <Set name="contexts">
+ <Ref refid="Contexts" />
+ </Set>
+ <Call id="extAppHotDeployProvider" name="addAppProvider">
+ <Arg>
+ <New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
+ <Set name="monitoredDirName"><SystemProperty name="AJSC_HOME" />/extApps</Set>
+ <Set name="scanInterval">10</Set>
+ <Set name="extractWars">true</Set>
+ </New>
+ </Arg>
+ </Call>
+ </New>
+ </Arg>
+ </Call>
+
+ <New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
+ <Set name="keyStorePath">file:<SystemProperty name="CONFIG_HOME" />/auth/tomcat_keystore</Set>
+ <Set name="KeyStorePassword">
+ <Call class="org.eclipse.jetty.util.security.Password" name="deobfuscate">
+ <Arg><SystemProperty name="KEY_STORE_PASSWORD" /></Arg>
+ </Call>
+ </Set>
+ <Set name="KeyManagerPassword">
+ <Call class="org.eclipse.jetty.util.security.Password" name="deobfuscate">
+ <Arg><SystemProperty name="KEY_MANAGER_PASSWORD" /></Arg>
+ </Call>
+ </Set>
+ <Set name="needClientAuth">true</Set>
+ <Set name="wantClientAuth">true</Set>
+ </New>
+
+ <Call id="sslConnector" name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.server.ServerConnector">
+ <Arg name="server">
+ <Ref refid="ajsc-server" />
+ </Arg>
+ <Arg name="factories">
+ <Array type="org.eclipse.jetty.server.ConnectionFactory">
+ <Item>
+ <New class="org.eclipse.jetty.server.SslConnectionFactory">
+ <Arg name="next">http/1.1</Arg>
+ <Arg name="sslContextFactory">
+ <Ref refid="sslContextFactory" />
+ </Arg>
+ </New>
+ </Item>
+ <Item>
+ <New class="org.eclipse.jetty.server.HttpConnectionFactory">
+ <Arg name="config">
+ <New class="org.eclipse.jetty.server.HttpConfiguration">
+ <Call name="addCustomizer">
+ <Arg>
+ <New class="org.eclipse.jetty.server.SecureRequestCustomizer" />
+ </Arg>
+ </Call>
+ </New>
+ </Arg>
+ </New>
+ </Item>
+ </Array>
+ </Arg>
+ <Set name="port"><SystemProperty name="AJSC_HTTPS_PORT" default="9522" /></Set>
+ <Set name="idleTimeout">30000</Set>
+ </New>
+ </Arg>
+ </Call>
+
+ <Get name="ThreadPool">
+ <Set name="minThreads"><SystemProperty name="AJSC_JETTY_ThreadCount_MIN" /></Set>
+ <Set name="maxThreads"><SystemProperty name="AJSC_JETTY_ThreadCount_MAX" /></Set>
+ <Set name="idleTimeout"><SystemProperty name="AJSC_JETTY_IDLETIME_MAX" /></Set>
+ <Set name="detailedDump">false</Set>
+ </Get>
+
+</Configure>
diff --git a/champ-service/src/main/config/ajsc-override-web.xml b/champ-service/src/main/config/ajsc-override-web.xml
new file mode 100644
index 0000000..8e02d6d
--- /dev/null
+++ b/champ-service/src/main/config/ajsc-override-web.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ metadata-complete="false" version="3.0">
+
+ <filter-mapping>
+ <filter-name>InterceptorFilter</filter-name>
+ <url-pattern>/services/*</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>InterceptorFilter</filter-name>
+ <url-pattern>/rest/*</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <servlet-mapping>
+ <servlet-name>ManagementServlet</servlet-name>
+ <url-pattern>/mgmt</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>RestletServlet</servlet-name>
+ <url-pattern>/rest/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>CamelServlet</servlet-name>
+ <url-pattern>/services/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>jsp</servlet-name>
+ <url-pattern>*.jsp</url-pattern>
+ <url-pattern>*.jspf</url-pattern>
+ <url-pattern>*.jspx</url-pattern>
+ <url-pattern>*.xsp</url-pattern>
+ <url-pattern>*.JSP</url-pattern>
+ <url-pattern>*.JSPF</url-pattern>
+ <url-pattern>*.JSPX</url-pattern>
+ <url-pattern>*.XSP</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>default</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app> \ No newline at end of file
diff --git a/champ-service/src/main/config/ajscJetty.jks b/champ-service/src/main/config/ajscJetty.jks
new file mode 100644
index 0000000..48cdbff
--- /dev/null
+++ b/champ-service/src/main/config/ajscJetty.jks
Binary files differ
diff --git a/champ-service/src/main/config/cadi.properties b/champ-service/src/main/config/cadi.properties
new file mode 100644
index 0000000..cc527ed
--- /dev/null
+++ b/champ-service/src/main/config/cadi.properties
@@ -0,0 +1,28 @@
+#This properties file is used for defining AAF properties related to the CADI framework. This file is used for running AAF framework
+hostname=mywebserver.att.com
+
+#Setting csp_domain to PROD will allow for testing using your attuid and password through GLO.
+csp_domain=PROD
+csp_devl_localhost=true
+
+basic_realm=csp.att.com
+#basic_realm=aaf.att.com
+basic_warn=TRUE
+
+cadi_loglevel=WARN
+cadi_keyfile=target/swm/package/nix/dist_files/appl/champ-service/etc/keyfile
+
+# Configure AAF
+#These are dummy values add appropriate values required
+aaf_url=url
+
+#AJSC - MECHID
+#These are dummy values add appropriate values required
+aaf_id=dummyid@ajsc.att.com
+aaf_password=enc:277edqJCjT0RlUI3BtbDQa-3Ha-CQGd
+aaf_timeout=5000
+aaf_clean_interval=30000
+aaf_user_expires=5000
+aaf_high_count=1000
+
+
diff --git a/champ-service/src/main/config/jul-redirect.properties b/champ-service/src/main/config/jul-redirect.properties
new file mode 100644
index 0000000..8b6624d
--- /dev/null
+++ b/champ-service/src/main/config/jul-redirect.properties
@@ -0,0 +1,13 @@
+
+# Bridge JUL->slf4j Logging Configuration File
+#
+# This file bridges the JUL logging infrastructure into
+# SLF4J so JUL logs go to logback implementation provided
+# in this project. SLF4J also captures log4j and has
+# other framework options as well providing a common
+# logging infrastructure for capturing all logs from different
+# libraries using different frameworks in one place.
+
+# Global properties
+handlers=org.slf4j.bridge.SLF4JBridgeHandler
+.level= ALL
diff --git a/champ-service/src/main/config/keyfile b/champ-service/src/main/config/keyfile
new file mode 100644
index 0000000..882e86a
--- /dev/null
+++ b/champ-service/src/main/config/keyfile
@@ -0,0 +1,27 @@
+ZuIwp0TkyVPDeX1Up-8JtkMWvjsCpoiu1_VKeWrtrvxunvAke8_tiFyHPPyb2nkhepFYj6tXzpfS
+rGz5XF_TH9NbsKaP8u0HV5clz2WriYQRvHS85vjY7hXxkpFuLb7zkLAPqTyIDpj7FiW61NzsRUAq
+TM8jH16jr7mBNnb56w24mNGOwznMPcIZKcjgZU1ekaPDFpWyhQElU7Y0q_94P_Gkk45r66Hj22sU
+OiOaaftmudZlswLw8-8Zaakqf2yW9HjMVfuYCwSodBHCW5rdB3Ctb5W36rnD_AQco3Ky2PgPmqvk
+QkJYuUHpbuDqVHqLOajlKSIGMTIqAIBg51fRaaONtD-Q5xzY8E5wO1YWTLKcP5tsNvUpzM8Wu3NS
+ynpGpUcvlTqWWsGzTbzOyamyKkdNdx97sSqjM25Zh1-ps48h6cddGYWpab7SUvqRCS11QBUyLTry
+2iwTEHMhHRIbo7PO99ALQfuq9gI1zKGfurJdvLBeBaFs5SCF0AiCZ3WcDO8Rv3HpxVZ2_ShbDxb0
+eMoO6SotXu51fj8Y3-WqsfZziQyEsHyqpg5uQ6yUtz01h5YHLEoVuotF1U4agmQR6kEkYk-wNOiZ
+v-8gaA9gtbLoAdKhuKFxQgQLNMf6GzVzZNujbmDzLoZAP_mXAv29aBPaf64Ugzv-Oa5GZdBgD-Xd
+_pahML-ionw99r0TnkpShYmDqMKhMdjaP3m87WIAZkIB-L-VTyKcEsJ4340VSzCOsv3waiM0S89u
+4cMcG5y-PLY8IoipIlLUPTWD3SjcQ9DV1Dt3T5KjdWLsj48D3W4K4e9PB8yxs0gtUjgVUR2_xEir
+G5eDO9Ac1eHFWGDFFP0SgG-TbHJUKlvy9mwLzmU0fC3xPjhqmIr-v0HxF7HN-tmb1LHDorno8tSN
+u7kUGcKSchIiFfvkd066crUb2mH7PnXTaWmAjyVj9VsBExFUYEdpHMAV4sAP9-RxZGDRt46UhrDK
+QZvvNhBVyOEjHPHWI4vl1r1v8HNH1_2jZu5DVJWyHWR56aCo1lhFH9_X6UAHUHbnXViDONZOVXlT
+9-WD0tk2zJGuwrhdZDAnPnAmjfwbwbpnr5Hmex1i1JiD7WVyP1kbfoej2TmdiYbxr9oBYaGQ29JI
+aHod7MQCLtvL1z5XgnDPLZ4y3_9SbqHKYbNa8UgZkTLF5EacGThYVFDLA9cbafHDtR1kMGE3vv4D
+EJ-0pAYTOGmKlVI7DwNyKsY9JTyudrxTqhOxi9jgcJNWiUaNe9yhL8Pyc2YBqUTTYhh_a2d1rvkZ
+0Gh1crviVxqBrIkRKaMRXZ4f1vDLz-3NvG_vwPOo8WRFo5nGmSdTw7CjBaigJ_cYCfDhoP11pEnw
+cndsZNcHs-v05LlxeIIMDD_f5Bvz-il_DLA4eK2HqgLdxh8ziSDl2azk14MJY4amzz6reEXUuKLV
+RsZGf_jbDGKhE2HuDQ5ovoLOi4OqE1oRuqh-dGxitrYouP2SN1l_1tCEMRth86FMV-6AQtZsvdUo
+y9MtQ7e35atjA8nHtgADlDTmJBKQiUHUsOZ77p1qp17HAFMovUkc739opfEYnKUn6Itpw5Ipm_Is
+ra6chJUfMpOFof5rb5OjqFAN27c_-mPo1lQU3ndYlKGh_n5V8ufX6v2Yri8WzOPf6hjVYotkmoMP
+NPAICDCB8W5ddBjsopzLVVEtaXDu9Qj6-zf77hT4iQ7rBd2Ner8iLqN3Kis0dvkNM3_uH8onau1G
+Y_YYw7PPSZyd2S_7Dd6G-IG4ayO6e5DD6oUwwekyiQI_3rTXNa_wldGxqW9u818010ekE4Qdlfcj
+beIn7fAeaOjReZ87hRgWyMs-EgTVHw8RL3yI_O6VvRTVRONRF1Y4C_-IYa8z-bfrwXx3BBd9TTgb
+EnS9wVOyC2OgUN6BhPLGLhxzkJ05nEjizXEc9t5EPYoSRwesajGGrrG_0-qWbuU5hKLPLkyeJLHb
+5HXOTVsrUR59Vov2M3_EswkxcImblox3k3VS2yihZMGyfqLzZIUXgd8ufkevKKU6DxwacGTb \ No newline at end of file
diff --git a/champ-service/src/main/config/runner-web.xml b/champ-service/src/main/config/runner-web.xml
new file mode 100644
index 0000000..5f65183
--- /dev/null
+++ b/champ-service/src/main/config/runner-web.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ metadata-complete="false" version="3.0">
+
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>/WEB-INF/spring-servlet.xml,
+ classpath:applicationContext.xml
+ </param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>spring.profiles.default</param-name>
+ <param-value>nooauth</param-value>
+ </context-param>
+
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>ManagementServlet</servlet-name>
+ <servlet-class>ajsc.ManagementServlet</servlet-class>
+ </servlet>
+
+
+ <filter>
+ <filter-name>InterceptorFilter</filter-name>
+ <filter-class>ajsc.filters.InterceptorFilter</filter-class>
+ <init-param>
+ <param-name>preProcessor_interceptor_config_file</param-name>
+ <param-value>/etc/PreProcessorInterceptors.properties</param-value>
+ </init-param>
+ <init-param>
+ <param-name>postProcessor_interceptor_config_file</param-name>
+ <param-value>/etc/PostProcessorInterceptors.properties</param-value>
+ </init-param>
+
+ </filter>
+
+ <servlet>
+ <servlet-name>RestletServlet</servlet-name>
+ <servlet-class>ajsc.restlet.RestletSpringServlet</servlet-class>
+ <init-param>
+ <param-name>org.restlet.component</param-name>
+ <param-value>restletComponent</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <servlet-name>CamelServlet</servlet-name>
+ <servlet-class>ajsc.servlet.AjscCamelServlet</servlet-class>
+ </servlet>
+
+
+ <filter>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
+ </filter>
+
+ <servlet>
+ <servlet-name>spring</servlet-name>
+ <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+<!-- <servlet-mapping>
+ <servlet-name>spring</servlet-name>
+ <url-pattern>/</url-pattern>
+ </servlet-mapping>-->
+
+<!-- BEGIN jsp -->
+
+ <servlet id="jsp">
+ <servlet-name>jsp</servlet-name>
+ <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
+ </servlet>
+
+
+
+
+
+ <!-- BEGIN static content -->
+ <servlet>
+ <servlet-name>default</servlet-name>
+ <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
+ <init-param>
+ <param-name>dirAllowed</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ </servlet>
+ <!-- END static content -->
+</web-app>
diff --git a/champ-service/src/main/docker/Dockerfile b/champ-service/src/main/docker/Dockerfile
new file mode 100644
index 0000000..cf299a2
--- /dev/null
+++ b/champ-service/src/main/docker/Dockerfile
@@ -0,0 +1,34 @@
+FROM ubuntu:14.04
+
+ARG MICRO_HOME=/opt/app/champ-service
+ARG BIN_HOME=$MICRO_HOME/bin
+ARG GRAPHLIB_HOME=$MICRO_HOME/graph-deps
+
+RUN apt-get update
+
+# Install and setup java8
+RUN apt-get update && apt-get install -y software-properties-common
+RUN sudo -E add-apt-repository ppa:openjdk-r/ppa && apt-get update && apt-get install -y openjdk-8-jdk
+ENV JAVA_HOME usr/lib/jvm/java-8-openjdk-amd64
+RUN export JAVA_HOME
+
+# Build up the deployment folder structure
+RUN mkdir -p $MICRO_HOME
+ADD swm/package/nix/dist_files/appl/champ-service/* $MICRO_HOME/
+RUN mkdir -p $GRAPHLIB_HOME
+ADD graph-deps $GRAPHLIB_HOME
+RUN mkdir -p $BIN_HOME
+COPY *.sh $BIN_HOME
+RUN chmod 755 $BIN_HOME/*
+RUN ln -s /logs $MICRO_HOME/logs
+
+# Create the aai user
+RUN mkdir /opt/aaihome && \
+ groupadd -g 492381 aaiadmin && \
+ useradd -r -u 341790 -g 492381 -ms /bin/bash -d /opt/aaihome/aaiadmin aaiadmin && \
+ chown -R aaiadmin:aaiadmin $MICRO_HOME
+USER aaiadmin
+
+EXPOSE 9522 9522
+
+CMD ["/opt/app/champ-service/bin/start.sh"]
diff --git a/champ-service/src/main/java/org/onap/champ/ChampRESTAPI.java b/champ-service/src/main/java/org/onap/champ/ChampRESTAPI.java
new file mode 100644
index 0000000..3d7e074
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/ChampRESTAPI.java
@@ -0,0 +1,568 @@
+package org.onap.champ;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Timer;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.aai.champcore.ChampTransaction;
+import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
+import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException;
+import org.onap.aai.champcore.exceptions.ChampTransactionException;
+import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
+import org.onap.aai.champcore.model.ChampObject;
+import org.onap.aai.champcore.model.ChampRelationship;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.champ.async.ChampAsyncRequestProcessor;
+import org.onap.champ.entity.ChampObjectDeserializer;
+import org.onap.champ.entity.ChampObjectSerializer;
+import org.onap.champ.entity.ChampRelationshipDeserializer;
+import org.onap.champ.entity.ChampRelationshipSerializer;
+import org.onap.champ.exception.ChampServiceException;
+import org.onap.champ.service.ChampDataService;
+import org.onap.champ.service.logging.ChampMsgs;
+import org.onap.champ.service.logging.LoggingUtil;
+import org.onap.champ.util.ChampProperties;
+import org.onap.champ.util.ChampServiceConstants;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+@Path(value = "/")
+public class ChampRESTAPI {
+
+ private ObjectMapper mapper;
+
+ private ChampDataService champDataService;
+ private String TRANSACTION_METHOD = "method";
+ private Timer timer;
+
+ private Logger logger = LoggerFactory.getInstance().getLogger(ChampRESTAPI.class);
+ Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(ChampRESTAPI.class.getName());
+ private static Logger metricsLogger = LoggerFactory.getInstance().getMetricsLogger(ChampRESTAPI.class.getName());
+
+ public ChampRESTAPI(ChampDataService champDataService, ChampAsyncRequestProcessor champAsyncRequestProcessor) {
+ this.champDataService = champDataService;
+
+ // Async request handling is optional.
+ if (champAsyncRequestProcessor != null) {
+ timer = new Timer("ChampAsyncRequestProcessor-1");
+ timer.schedule(champAsyncRequestProcessor, champAsyncRequestProcessor.getRequestPollingTimeSeconds(),
+ champAsyncRequestProcessor.getRequestPollingTimeSeconds());
+ }
+
+ mapper = new ObjectMapper();
+ SimpleModule module = new SimpleModule();
+ module.addSerializer(ChampObject.class, new ChampObjectSerializer());
+ module.addDeserializer(ChampObject.class, new ChampObjectDeserializer());
+ module.addSerializer(ChampRelationship.class, new ChampRelationshipSerializer());
+ module.addDeserializer(ChampRelationship.class, new ChampRelationshipDeserializer());
+ mapper.registerModule(module);
+ }
+
+ @GET
+ @Path("echo")
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response echo() {
+ return Response.ok().entity("alive").build();
+ }
+
+ @GET
+ @Path("objects/{objectId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getObject(@PathParam("objectId") String objectId, @QueryParam("transactionId") String tId,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, objectId);
+
+ Response response = null;
+ ChampObject retrieved;
+
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ retrieved = champDataService.getObject(objectId, Optional.ofNullable(transaction));
+ if (retrieved == null) {
+ response = Response.status(Status.NOT_FOUND).entity(objectId + " not found").build();
+ } else {
+ response = Response.status(Status.OK).entity(mapper.writeValueAsString(retrieved)).build();
+ }
+
+ } catch (JsonProcessingException e) {
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } finally {
+ logger.debug(response.getEntity().toString());
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+
+ return response;
+ }
+
+ @DELETE
+ @Path("objects/{objectId}")
+ public Response deleteObject(@PathParam("objectId") String objectId, @QueryParam("transactionId") String tId,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, objectId);
+ ChampObject retrieved;
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ champDataService.deleteObject(objectId, Optional.ofNullable(transaction));
+
+ response = Response.status(Status.OK).build();
+ } catch (ChampObjectNotExistsException e) {
+ response = Response.status(Status.NOT_FOUND).entity(objectId + " not found").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (ChampTransactionException | ChampUnmarshallingException e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "DELETE",
+ Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @POST
+ @Path("objects")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response postObject(String champObj, @QueryParam("transactionId") String tId, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, champObj);
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ ChampObject champObject = mapper.readValue(champObj, ChampObject.class);
+
+ ChampObject created = champDataService.storeObject(champObject, Optional.ofNullable(transaction));
+ response = Response.status(Status.CREATED).entity(mapper.writeValueAsString(created)).build();
+ } catch (IOException e) {
+ response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "POST",
+ Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @PUT
+ @Path("objects/{objectId}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response putObject(@PathParam("objectId") String objectId, String champObj,
+ @QueryParam("transactionId") String tId, @Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, objectId + " " + champObj);
+
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+
+ ChampObject co = mapper.readValue(champObj, ChampObject.class);
+ // check if key is present or if it equals the key that is in the URI
+ ChampObject updated = champDataService.replaceObject(co, objectId, Optional.ofNullable(transaction));
+
+ response = Response.status(Status.OK).entity(mapper.writeValueAsString(updated)).build();
+ } catch (IOException e) {
+ response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "PUT", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @GET
+ @Path("objects/relationships/{oId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getEdges(@PathParam("oId") String oId, @QueryParam("transactionId") String tId,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ List<ChampRelationship> retrieved;
+ Optional<ChampObject> rObject;
+ Response response = null;
+ ChampTransaction transaction = null;
+ try {
+
+ retrieved = champDataService.getRelationshipsByObject(oId, Optional.ofNullable(transaction));
+ response = Response.status(Status.OK).entity(mapper.writeValueAsString(retrieved)).build();
+ } catch (JsonProcessingException e) {
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @GET
+ @Path("objects/filter/")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response filterObject(@Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ String propertiesKey = ChampProperties.get(ChampServiceConstants.CHAMP_COLLECTION_PROPERTIES_KEY);
+ List<ChampObject> objects;
+ Map<String, Object> filter = new HashMap<>();
+
+ for (Map.Entry<String, List<String>> e : uriInfo.getQueryParameters().entrySet()) {
+ if (!e.getKey().equals(propertiesKey)) {
+ filter.put(e.getKey(), e.getValue().get(0));
+ }
+ }
+
+ HashSet<String> properties;
+ if (uriInfo.getQueryParameters().containsKey(propertiesKey)) {
+ properties = new HashSet<>(uriInfo.getQueryParameters().get(propertiesKey));
+ } else {
+ properties = new HashSet<>();
+ }
+
+ Response response = null;
+ try {
+ objects = champDataService.queryObjects(filter, properties);
+ response = Response.status(Status.OK).type(MediaType.APPLICATION_JSON).entity(mapper.writeValueAsString(objects))
+ .build();
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (ChampServiceException e1) {
+ response = Response.status(e1.getHttpStatus()).entity(e1.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @GET
+ @Path("relationships/{rId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getRelationship(@PathParam("rId") String rId, @QueryParam("transactionId") String tId,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, rId);
+ ChampRelationship retrieved;
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ retrieved = champDataService.getRelationship(rId, Optional.ofNullable(transaction));
+ if (retrieved == null) {
+ response = Response.status(Status.NOT_FOUND).entity(rId + " not found").build();
+ return response;
+ }
+ response = Response.status(Status.OK).entity(mapper.writeValueAsString(retrieved)).build();
+
+ } catch (IOException e) {
+ response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @POST
+ @Path("relationships")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response postRelationships(String relationship, @QueryParam("transactionId") String tId,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, relationship);
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ ChampRelationship r = mapper.readValue(relationship, ChampRelationship.class);
+
+ ChampRelationship created = champDataService.storeRelationship(r, Optional.ofNullable(transaction));
+
+ response = Response.status(Status.CREATED).entity(mapper.writeValueAsString(created)).build();
+ } catch (IOException e) {
+ response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "POST",
+ Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @PUT
+ @Path("relationships/{rId}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response updateRelationship(@PathParam("rId") String rId, String relationship,
+ @QueryParam("transactionId") String tId, @Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, relationship);
+
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ ChampRelationship r = mapper.readValue(relationship, ChampRelationship.class);
+ ChampRelationship updated = champDataService.updateRelationship(r, rId, Optional.ofNullable(transaction));
+
+ response = Response.status(Status.OK).entity(mapper.writeValueAsString(updated)).build();
+ } catch (IOException e) {
+ response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "PUT", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @DELETE
+ @Path("relationships/{relationshipId}")
+ public Response deleteRelationship(@PathParam("relationshipId") String relationshipId,
+ @QueryParam("transactionId") String tId, @Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, relationshipId);
+
+ Response response = null;
+ try {
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+ if (tId != null && transaction == null) {
+ throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST);
+ }
+ champDataService.deleteRelationship(relationshipId, Optional.ofNullable(transaction));
+ response = Response.status(Status.OK).build();
+
+ } catch (ChampRelationshipNotExistsException e) {
+ response = Response.status(Status.NOT_FOUND).entity(relationshipId + " not found").build();
+ } catch (ChampServiceException ce) {
+ response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
+ } catch (ChampTransactionException | ChampUnmarshallingException e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "DELETE",
+ Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @GET
+ @Path("relationships/filter/")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response filterMethod(@Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ List<ChampRelationship> list;
+ Map<String, Object> filter = new HashMap<>();
+ for (Map.Entry<String, List<String>> e : uriInfo.getQueryParameters().entrySet()) {
+ filter.put(e.getKey(), e.getValue().get(0));
+ }
+ Response response = null;
+ try {
+ list = champDataService.queryRelationships(filter);
+ response = Response.status(Status.OK).type(MediaType.APPLICATION_JSON).entity(mapper.writeValueAsString(list))
+ .build();
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (ChampServiceException e1) {
+ response = Response.status(e1.getHttpStatus()).entity(e1.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @POST
+ @Path("transaction")
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response openTransaction(@Context HttpHeaders headers, @Context UriInfo uriInfo,
+ @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ Status s;
+ String transaction = champDataService.openTransaction();
+
+ s = Status.OK;
+ Response response = Response.status(s).entity(transaction).build();
+ logger.info(ChampMsgs.PROCESS_EVENT, "Opened Transaction with ID: " + transaction, s.toString());
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "POST", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ return response;
+ }
+
+ @GET
+ @Path("transaction/{tId}")
+ public Response getSpecificTransaction(@PathParam("tId") String tId, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+
+ Response response = null;
+ ChampTransaction transaction = champDataService.getTransaction(tId);
+ if (transaction == null) {
+ response = Response.status(Status.NOT_FOUND).entity("transaction " + tId + " not found").build();
+ return response;
+ }
+
+ try {
+ response = Response.status(Status.OK).entity(mapper.writeValueAsString(tId + " is OPEN")).build();
+ } catch (JsonProcessingException e) {
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+ @PUT
+ @Path("transaction/{tId}")
+ @Produces(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response updateTransaction(String t, @PathParam("tId") String tId, @Context HttpHeaders headers,
+ @Context UriInfo uriInfo, @Context HttpServletRequest req) {
+ LoggingUtil.initMdcContext(req, headers);
+ long startTimeInMs = System.currentTimeMillis();
+ logger.info(ChampMsgs.INCOMING_REQUEST, tId, "COMMIT/ROLLBACK");
+
+ Response response = null;
+ try {
+ JSONObject jsonObj = new JSONObject(t);
+ String method = jsonObj.getString(this.TRANSACTION_METHOD);
+
+ if (method.equals("commit")) {
+ champDataService.commitTransaction(tId);
+ response = Response.status(Status.OK).entity("COMMITTED").build();
+
+ } else if (method.equals("rollback")) {
+ champDataService.rollbackTransaction(tId);
+ response = Response.status(Status.OK).entity("ROLLED BACK").build();
+ } else {
+ response = Response.status(Status.BAD_REQUEST).entity("Invalid Method: " + method).build();
+ return response;
+ }
+
+ } catch (ChampTransactionException e) {
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (JSONException e) {
+ response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
+ } catch (ChampServiceException e) {
+ response = Response.status(e.getHttpStatus()).entity(e.getMessage()).build();
+ } catch (Exception e) {
+ response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ LoggingUtil.logInternalError(logger, e);
+ } finally {
+ LoggingUtil.logRestRequest(logger, auditLogger, req, response);
+ metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "PUT", Long.toString(System.currentTimeMillis() - startTimeInMs));
+ }
+ return response;
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/async/ChampAsyncRequestProcessor.java b/champ-service/src/main/java/org/onap/champ/async/ChampAsyncRequestProcessor.java
new file mode 100644
index 0000000..af2ab20
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/async/ChampAsyncRequestProcessor.java
@@ -0,0 +1,327 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * 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 and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.champ.async;
+
+import java.util.Optional;
+import java.util.TimerTask;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import javax.naming.OperationNotSupportedException;
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.aai.champcore.ChampTransaction;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.champ.ChampRESTAPI;
+import org.onap.champ.event.GraphEvent;
+import org.onap.champ.event.GraphEvent.GraphEventResult;
+import org.onap.champ.event.GraphEventEdge;
+import org.onap.champ.event.GraphEventVertex;
+import org.onap.champ.exception.ChampServiceException;
+import org.onap.champ.service.ChampDataService;
+import org.onap.champ.service.ChampThreadFactory;
+import org.onap.champ.service.logging.ChampMsgs;
+
+import org.onap.aai.event.api.EventConsumer;
+
+/**
+ * This Class polls the Graph events from request topic perform the necessary
+ * CRUD operation by calling champDAO and queues up the response to be consumed
+ * by response handler.
+ */
+public class ChampAsyncRequestProcessor extends TimerTask {
+
+ private Logger logger = LoggerFactory.getInstance().getLogger(ChampAsyncRequestProcessor.class);
+
+ private ChampDataService champDataService;
+
+ /**
+ * Number of events that can be queued up.
+ */
+ private Integer requestProcesserQueueSize;
+
+ /**
+ * Number of event publisher worker threads.
+ */
+ private Integer requestProcesserPoolSize;
+
+ /**
+ * Number of event publisher worker threads.
+ */
+ private Integer requestPollingTimeSeconds;
+
+ /**
+ * Internal queue where outgoing events will be buffered until they can be
+ * serviced by.
+ **/
+ private BlockingQueue<GraphEvent> requestProcesserEventQueue;
+
+ /**
+ * Pool of worker threads that do the work of publishing the events to the
+ * event bus.
+ */
+ private ThreadPoolExecutor requestProcesserPool;
+
+ private ChampAsyncResponsePublisher champAsyncResponsePublisher;
+
+ private EventConsumer asyncRequestConsumer;
+
+ private static final Integer DEFAULT_ASYNC_REQUEST_PROCESS_QUEUE_CAPACITY = 10000;
+
+ private static final Integer DEFAULT_ASYNC_REQUEST_PROCESS_THREAD_POOL_SIZE = 10;
+ private static final Integer DEFAULT_ASYNC_REQUEST_PROCESS_POLLING_SECOND = 30000;
+ private static final String CHAMP_GRAPH_REQUEST_PROCESS_THREAD_NAME = "ChampAsyncGraphRequestEventProcessor";
+ Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(ChampRESTAPI.class.getName());
+
+ public ChampAsyncRequestProcessor(ChampDataService champDataService,
+ ChampAsyncResponsePublisher champAsyncResponsePublisher, EventConsumer asyncRequestConsumer) {
+
+ this.requestProcesserQueueSize = DEFAULT_ASYNC_REQUEST_PROCESS_QUEUE_CAPACITY;
+
+ this.requestProcesserPoolSize = DEFAULT_ASYNC_REQUEST_PROCESS_THREAD_POOL_SIZE;
+
+ this.requestPollingTimeSeconds = DEFAULT_ASYNC_REQUEST_PROCESS_POLLING_SECOND;
+ requestProcesserEventQueue = new ArrayBlockingQueue<GraphEvent>(requestProcesserQueueSize);
+ requestProcesserPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(requestProcesserPoolSize,
+ new ChampThreadFactory(CHAMP_GRAPH_REQUEST_PROCESS_THREAD_NAME));
+
+ for (int i = 0; i < requestProcesserPoolSize; i++) {
+ requestProcesserPool.submit(new ChampProcessorWorker());
+ }
+
+ this.champDataService = champDataService;
+ this.champAsyncResponsePublisher = champAsyncResponsePublisher;
+ this.asyncRequestConsumer = asyncRequestConsumer;
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ "ChampAsyncRequestProcessor initialized SUCCESSFULLY! with event consumer "
+ + asyncRequestConsumer.getClass().getName());
+ }
+
+
+
+ public ChampAsyncRequestProcessor(ChampDataService champDataService,
+ ChampAsyncResponsePublisher champAsyncResponsePublisher, EventConsumer asyncRequestConsumer,
+ Integer requestProcesserQueueSize, Integer requestProcesserPoolSize, Integer requestPollingTimeSeconds) {
+
+ this.requestProcesserQueueSize = requestProcesserQueueSize;
+
+ this.requestProcesserPoolSize = requestProcesserPoolSize;
+
+ this.requestPollingTimeSeconds = requestPollingTimeSeconds;
+
+ requestProcesserEventQueue = new ArrayBlockingQueue<GraphEvent>(requestProcesserQueueSize);
+ requestProcesserPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(requestProcesserPoolSize,
+ new ChampThreadFactory(CHAMP_GRAPH_REQUEST_PROCESS_THREAD_NAME));
+
+ for (int i = 0; i < requestProcesserPoolSize; i++) {
+ requestProcesserPool.submit(new ChampProcessorWorker());
+ }
+
+ this.champDataService = champDataService;
+ this.champAsyncResponsePublisher = champAsyncResponsePublisher;
+ this.asyncRequestConsumer = asyncRequestConsumer;
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ "ChampAsyncRequestProcessor initialized SUCCESSFULLY! with event consumer "
+ + asyncRequestConsumer.getClass().getName());
+ }
+
+ private class ChampProcessorWorker implements Runnable {
+
+ @Override
+ public void run() {
+
+ while (true) {
+
+ GraphEvent event = null;
+ try {
+ // Get the next event to be published from the queue.
+ event = requestProcesserEventQueue.take();
+ } catch (InterruptedException e) {
+ // Restore the interrupted status.
+ Thread.currentThread().interrupt();
+ }
+
+ // Parse the event and call champ Dao to process , Create the
+ // response event and put it on response queue
+ event.setResult(GraphEventResult.SUCCESS);
+
+ // Check if this request is part of an ongoing DB transaction
+ ChampTransaction transaction = champDataService.getTransaction(event.getDbTransactionId());
+ if ( (event.getDbTransactionId() != null) && (transaction == null) ) {
+ event.setResult(GraphEventResult.FAILURE);
+ event.setErrorMessage("Database transactionId " + event.getDbTransactionId() + " not found");
+ event.setHttpErrorStatus(Status.BAD_REQUEST);
+ }
+
+ if (event.getResult() != GraphEventResult.FAILURE) {
+ try {
+ if (event.getVertex() != null) {
+
+ switch (event.getOperation()) {
+ case CREATE:
+ event.setVertex(GraphEventVertex.fromChampObject(
+ champDataService.storeObject(event.getVertex().toChampObject(), Optional.ofNullable(transaction)),
+ event.getVertex().getModelVersion()));
+ break;
+
+ case UPDATE:
+ event.setVertex(GraphEventVertex.fromChampObject(
+ champDataService.replaceObject(event.getVertex().toChampObject(), event.getVertex().getId(), Optional.ofNullable(transaction)),
+ event.getVertex().getModelVersion()));
+ break;
+ case DELETE:
+ champDataService.deleteObject(event.getVertex().getId(), Optional.ofNullable(transaction));
+ break;
+ default:
+ // log error
+ }
+ } else if (event.getEdge() != null) {
+ switch (event.getOperation()) {
+ case CREATE:
+ event.setEdge(GraphEventEdge.fromChampRelationship(
+ champDataService.storeRelationship(event.getEdge().toChampRelationship(), Optional.ofNullable(transaction)),
+ event.getEdge().getModelVersion()));
+ break;
+
+ case UPDATE:
+ event.setEdge(GraphEventEdge.fromChampRelationship(champDataService
+ .updateRelationship(event.getEdge().toChampRelationship(), event.getEdge().getId(), Optional.ofNullable(transaction)),
+ event.getEdge().getModelVersion()));
+
+ break;
+ case DELETE:
+ champDataService.deleteRelationship(event.getEdge().getId(), Optional.ofNullable(transaction));
+ break;
+ default:
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR,
+ "Invalid operation for event transactionId: " + event.getTransactionId());
+ }
+
+ } else {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR,
+ "Invalid payload for event transactionId: " + event.getTransactionId());
+ }
+ } catch (ChampServiceException champException) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, champException.getMessage());
+ event.setResult(GraphEventResult.FAILURE);
+ event.setErrorMessage(champException.getMessage());
+ event.setHttpErrorStatus(champException.getHttpStatus());
+
+ } catch (Exception ex) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, ex.getMessage());
+ event.setResult(GraphEventResult.FAILURE);
+ event.setErrorMessage(ex.getMessage());
+ event.setHttpErrorStatus(Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ if (event.getResult().equals(GraphEventResult.SUCCESS)) {
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ "Event processed of type: " + event.getObjectType() + " with key: " + event.getObjectKey()
+ + " , transaction-id: " + event.getTransactionId() + " , operation: "
+ + event.getOperation().toString() + " , result: " + event.getResult());
+ } else {
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ "Event processed of type: " + event.getObjectType() + " with key: " + event.getObjectKey()
+ + " , transaction-id: " + event.getTransactionId() + " , operation: "
+ + event.getOperation().toString() + " , result: " + event.getResult() + " , error: "
+ + event.getErrorMessage());
+ }
+
+ champAsyncResponsePublisher.publishResponseEvent(event);
+
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, "Listening for graph events");
+
+ if (asyncRequestConsumer == null) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, "Unable to initialize ChampAsyncRequestProcessor");
+ }
+
+ Iterable<String> events = null;
+ try {
+ events = asyncRequestConsumer.consume();
+ } catch (Exception e) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, e.getMessage());
+ return;
+ }
+
+ if (events == null || !events.iterator().hasNext()) {
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, "No events recieved");
+
+ }
+
+ for (String event : events) {
+ try {
+ GraphEvent requestEvent = GraphEvent.fromJson(event);
+ auditLogger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ "Event received of type: " + requestEvent.getObjectType() + " with key: " + requestEvent.getObjectKey()
+ + " , transaction-id: " + requestEvent.getTransactionId() + " , operation: "
+ + requestEvent.getOperation().toString());
+ logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ "Event received of type: " + requestEvent.getObjectType() + " with key: " + requestEvent.getObjectKey()
+ + " , transaction-id: " + requestEvent.getTransactionId() + " , operation: "
+ + requestEvent.getOperation().toString());
+ logger.debug(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, "Event received with payload:" + event);
+
+ // Try to submit the event to be published to the event bus.
+ if (!requestProcesserEventQueue.offer(requestEvent)) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR,
+ "Event could not be published to the event bus due to: Internal buffer capacity exceeded.");
+ }
+
+ } catch (Exception e) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, e.getMessage());
+ }
+ }
+
+ try {
+ asyncRequestConsumer.commitOffsets();
+ } catch(OperationNotSupportedException e) {
+ //Dmaap doesnt support commit with offset
+ logger.debug(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_WARN, e.getMessage());
+ }
+ catch (Exception e) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_WARN, e.getMessage());
+ }
+
+ }
+
+
+
+ public Integer getRequestPollingTimeSeconds() {
+ return requestPollingTimeSeconds;
+ }
+
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/async/ChampAsyncResponsePublisher.java b/champ-service/src/main/java/org/onap/champ/async/ChampAsyncResponsePublisher.java
new file mode 100644
index 0000000..8c31a53
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/async/ChampAsyncResponsePublisher.java
@@ -0,0 +1,160 @@
+/**
+ * ============LICENSE_START=======================================================
+ *
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * 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 and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.champ.async;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.champ.event.GraphEvent;
+import org.onap.champ.event.GraphEvent.GraphEventResult;
+import org.onap.champ.service.ChampThreadFactory;
+import org.onap.champ.service.logging.ChampMsgs;
+
+import org.onap.aai.event.api.EventPublisher;
+
+public class ChampAsyncResponsePublisher {
+
+ private EventPublisher asyncResponsePublisher;
+
+ /**
+ * Number of events that can be queued up.
+ */
+ private Integer responsePublisherQueueSize;
+
+ /**
+ * Number of event publisher worker threads.
+ */
+ private Integer responsePublisherPoolSize;
+
+ /**
+ * Internal queue where outgoing events will be buffered.
+ **/
+ private BlockingQueue<GraphEvent> responsePublisherEventQueue;
+
+ /**
+ * Pool of worker threads that do the work of publishing the events to the
+ * event bus.
+ */
+ private ThreadPoolExecutor responsePublisherPool;
+
+ private static final Integer DEFAULT_ASYNC_RESPONSE_PUBLISH_QUEUE_CAPACITY = 10000;
+
+ private static final Integer DEFAULT_ASYNC_RESPONSE_PUBLISH_THREAD_POOL_SIZE = 10;
+ private static final String CHAMP_GRAPH_RESPONSE_PUBLISH_THREAD_NAME = "ChampAsyncGraphResponseEventPublisher";
+
+ private static Logger logger = LoggerFactory.getInstance().getLogger(ChampAsyncRequestProcessor.class.getName());
+
+ public ChampAsyncResponsePublisher(EventPublisher asyncResponsePublisher, Integer responsePublisherQueueSize,
+ Integer responsePublisherPoolSize) {
+ this.responsePublisherQueueSize = responsePublisherQueueSize;
+
+ this.responsePublisherPoolSize = responsePublisherPoolSize;
+
+ responsePublisherEventQueue = new ArrayBlockingQueue<GraphEvent>(responsePublisherQueueSize);
+ responsePublisherPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(responsePublisherPoolSize,
+ new ChampThreadFactory(CHAMP_GRAPH_RESPONSE_PUBLISH_THREAD_NAME));
+
+ for (int i = 0; i < responsePublisherPoolSize; i++) {
+ responsePublisherPool.submit(new GizmoResponsePublisherWorker());
+ }
+ this.asyncResponsePublisher = asyncResponsePublisher;
+
+ logger.info(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO,
+ "ChampAsyncResponsePublisher initialized SUCCESSFULLY! with event publisher "
+ + asyncResponsePublisher.getClass().getName());
+ }
+
+ public ChampAsyncResponsePublisher(EventPublisher asyncResponsePublisher) {
+ responsePublisherQueueSize = DEFAULT_ASYNC_RESPONSE_PUBLISH_QUEUE_CAPACITY;
+
+ responsePublisherPoolSize = DEFAULT_ASYNC_RESPONSE_PUBLISH_THREAD_POOL_SIZE;
+
+ responsePublisherEventQueue = new ArrayBlockingQueue<GraphEvent>(responsePublisherQueueSize);
+ responsePublisherPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(responsePublisherPoolSize,
+ new ChampThreadFactory(CHAMP_GRAPH_RESPONSE_PUBLISH_THREAD_NAME));
+
+ for (int i = 0; i < responsePublisherPoolSize; i++) {
+ responsePublisherPool.submit(new GizmoResponsePublisherWorker());
+ }
+ this.asyncResponsePublisher = asyncResponsePublisher;
+
+ logger.info(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO,
+ "CrudAsyncResponsePublisher initialized SUCCESSFULLY! with event publisher "
+ + asyncResponsePublisher.getClass().getName());
+ }
+
+ public void publishResponseEvent(GraphEvent event) {
+ responsePublisherEventQueue.offer(event);
+
+ }
+
+ private class GizmoResponsePublisherWorker implements Runnable {
+
+ @Override
+ public void run() {
+
+ while (true) {
+
+ GraphEvent event = null;
+ try {
+
+ // Get the next event to be published from the queue.
+ event = responsePublisherEventQueue.take();
+
+ } catch (InterruptedException e) {
+
+ // Restore the interrupted status.
+ Thread.currentThread().interrupt();
+ }
+ // Publish the response
+
+ try {
+ event.setTimestamp(System.currentTimeMillis());
+ asyncResponsePublisher.sendSync(event.toJson());
+ if (event.getResult().equals(GraphEventResult.SUCCESS)) {
+ logger.info(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO,
+ "Response published for Event of type: " + event.getObjectType() + " with key: " + event.getObjectKey()
+ + " , transaction-id: " + event.getTransactionId() + " , operation: "
+ + event.getOperation().toString() + " , result: " + event.getResult());
+ } else {
+ logger.info(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO,
+ "Response published for Event of type: " + event.getObjectType() + " with key: " + event.getObjectKey()
+ + " , transaction-id: " + event.getTransactionId() + " , operation: "
+ + event.getOperation().toString() + " , result: " + event.getResult() + " , error: "
+ + event.getErrorMessage());
+ }
+ } catch (Exception ex) {
+ logger.error(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_ERROR, ex.getMessage());
+ }
+
+ }
+ }
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/entity/ChampObjectDeserializer.java b/champ-service/src/main/java/org/onap/champ/entity/ChampObjectDeserializer.java
new file mode 100644
index 0000000..cee7763
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/entity/ChampObjectDeserializer.java
@@ -0,0 +1,67 @@
+/**
+ * ============LICENSE_START==========================================
+ * org.onap.aai
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.entity;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onap.aai.champcore.model.ChampObject;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+public class ChampObjectDeserializer extends StdDeserializer<ChampObject> {
+
+ private static final long serialVersionUID = -3625275249560680339L;
+
+ public ChampObjectDeserializer() {
+ this(null);
+ }
+
+ protected ChampObjectDeserializer(Class<ChampObject> t) {
+ super(t);
+ }
+
+ public ChampObject deserialize(JsonParser jparser, DeserializationContext dctx)
+ throws IOException, JsonProcessingException {
+
+ JsonNode node = jparser.getCodec().readTree(jparser);
+ JsonNode type = node.get("type");
+ JsonNode key = node.get("key");
+ Map<String, Object> props = new HashMap<>();
+ JsonNode propNode = node.get("properties");
+ propNode.fields().forEachRemaining((x)->props.put(x.getKey(), x.getValue().asText()));
+
+ ChampObject.Builder builder = new ChampObject.Builder(type.asText()).properties(props);
+
+ if(key != null){
+ builder.key(key.asText());
+ }
+
+ return builder.build();
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/entity/ChampObjectSerializer.java b/champ-service/src/main/java/org/onap/champ/entity/ChampObjectSerializer.java
new file mode 100644
index 0000000..c43b6bf
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/entity/ChampObjectSerializer.java
@@ -0,0 +1,54 @@
+/**
+ * ============LICENSE_START==========================================
+ * org.onap.aai
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.entity;
+
+import java.io.IOException;
+
+import org.onap.aai.champcore.model.ChampObject;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+public class ChampObjectSerializer extends StdSerializer<ChampObject> {
+
+ private static final long serialVersionUID = -4057960968983473983L;
+
+ public ChampObjectSerializer() {
+ this(null);
+ }
+
+ protected ChampObjectSerializer(Class<ChampObject> t) {
+ super(t);
+ }
+
+ public void serialize(ChampObject co, JsonGenerator jgen, SerializerProvider ser)
+ throws IOException, JsonGenerationException {
+ jgen.writeStartObject();
+ jgen.writeStringField("key", co.getKeyValue().toString());
+ jgen.writeStringField("type", co.getType());
+ jgen.writeObjectField("properties", co.getProperties());
+ jgen.writeEndObject();
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipDeserializer.java b/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipDeserializer.java
new file mode 100644
index 0000000..63b9e0c
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipDeserializer.java
@@ -0,0 +1,73 @@
+/**
+ * ============LICENSE_START==========================================
+ * org.onap.aai
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.entity;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+import org.onap.aai.champcore.model.ChampObject;
+import org.onap.aai.champcore.model.ChampRelationship;
+
+public class ChampRelationshipDeserializer extends StdDeserializer<ChampRelationship> {
+
+ private static final long serialVersionUID = -3625275249560680339L;
+
+ public ChampRelationshipDeserializer() {
+ this(null);
+ }
+
+ protected ChampRelationshipDeserializer(Class<ChampRelationship> t) {
+ super(t);
+ }
+
+ public ChampRelationship deserialize(JsonParser jparser, DeserializationContext dctx)
+ throws IOException, JsonProcessingException {
+
+ JsonNode node = jparser.getCodec().readTree(jparser);
+ JsonNode type = node.get("type");
+ JsonNode key = node.get("key");
+ Map<String, Object> props = new HashMap<>();
+ JsonNode propNode = node.get("properties");
+ propNode.fields().forEachRemaining((x)->props.put(x.getKey(), x.getValue().asText()));
+
+ JsonNode srcNode = node.get("source");
+ JsonNode targetNode = node.get("target");
+
+ ChampObject src = jparser.getCodec ().treeToValue ( srcNode, ChampObject.class );
+ ChampObject target = jparser.getCodec ().treeToValue ( targetNode, ChampObject.class );
+
+ ChampRelationship.Builder builder = new ChampRelationship.Builder(src, target, type.asText()).properties(props);
+
+ if(key != null){
+ builder.key(key.asText());
+ }
+
+ return builder.build();
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipSerializer.java b/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipSerializer.java
new file mode 100644
index 0000000..5d21aa5
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipSerializer.java
@@ -0,0 +1,55 @@
+/**
+ * ============LICENSE_START==========================================
+ * org.onap.aai
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.entity;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import org.onap.aai.champcore.model.ChampRelationship;
+
+import java.io.IOException;
+
+public class ChampRelationshipSerializer extends StdSerializer<ChampRelationship> {
+
+ private static final long serialVersionUID = -4057960968983473983L;
+
+ public ChampRelationshipSerializer() {
+ this(null);
+ }
+
+ protected ChampRelationshipSerializer(Class<ChampRelationship> t) {
+ super(t);
+ }
+
+ public void serialize( ChampRelationship cr, JsonGenerator jgen, SerializerProvider ser)
+ throws IOException, JsonGenerationException {
+ jgen.writeStartObject();
+ jgen.writeStringField("key", cr.getKeyValue().toString());
+ jgen.writeStringField("type", cr.getType());
+ jgen.writeObjectField("properties", cr.getProperties());
+ jgen.writeObjectField ("source", cr.getSource());
+ jgen.writeObjectField ("target", cr.getTarget ());
+ jgen.writeEndObject();
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/event/GraphEvent.java b/champ-service/src/main/java/org/onap/champ/event/GraphEvent.java
new file mode 100644
index 0000000..d649a3e
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/event/GraphEvent.java
@@ -0,0 +1,245 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * 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 and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.champ.event;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.champ.exception.ChampServiceException;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.annotations.SerializedName;
+
+public class GraphEvent {
+
+ public enum GraphEventOperation {
+ CREATE, UPDATE, DELETE
+ }
+
+ public enum GraphEventResult {
+ SUCCESS, FAILURE
+ }
+
+ private GraphEventOperation operation;
+
+ @SerializedName("transaction-id")
+ private String transactionId;
+
+ @SerializedName("database-transaction-id")
+ private String dbTransactionId;
+
+ private long timestamp;
+
+ private GraphEventVertex vertex;
+
+ private GraphEventEdge edge;
+
+ private GraphEventResult result;
+
+ @SerializedName("error-message")
+ private String errorMessage;
+
+ private Status httpErrorStatus;
+
+ /**
+ * Marshaller/unmarshaller for converting to/from JSON.
+ */
+ private static final Gson gson = new GsonBuilder().disableHtmlEscaping()
+ .setPrettyPrinting().create();
+
+ public static Builder builder(GraphEventOperation operation) {
+ return new Builder(operation);
+ }
+
+ public GraphEventOperation getOperation() {
+ return operation;
+ }
+
+ public String getTransactionId() {
+ return transactionId;
+ }
+
+ public String getDbTransactionId() {
+ return dbTransactionId;
+ }
+
+ public void setDbTransactionId(String id) {
+ dbTransactionId = id;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public GraphEventVertex getVertex() {
+ return vertex;
+ }
+
+ public GraphEventEdge getEdge() {
+ return edge;
+ }
+
+ public GraphEventResult getResult() {
+ return result;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setResult(GraphEventResult result) {
+ this.result = result;
+ }
+
+
+ public Status getHttpErrorStatus() {
+ return httpErrorStatus;
+ }
+
+ public void setHttpErrorStatus(Status httpErrorStatus) {
+ this.httpErrorStatus = httpErrorStatus;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+ public void setVertex(GraphEventVertex vertex) {
+ this.vertex = vertex;
+ }
+
+ public void setEdge(GraphEventEdge edge) {
+ this.edge = edge;
+ }
+
+ /**
+ * Unmarshalls this Vertex object into a JSON string.
+ *
+ * @return - A JSON format string representation of this Vertex.
+ */
+ public String toJson() {
+ return gson.toJson(this);
+ }
+
+ /**
+ * Marshalls the provided JSON string into a Vertex object.
+ *
+ * @param json - The JSON string to produce the Vertex from.
+ * @return - A Vertex object.
+ * @throws SpikeException
+ */
+ public static GraphEvent fromJson(String json) throws ChampServiceException {
+
+ try {
+
+ // Make sure that we were actually provided a non-empty string
+ // before we
+ // go any further.
+ if (json == null || json.isEmpty()) {
+ throw new ChampServiceException("Empty or null JSON string.", Status.BAD_REQUEST);
+ }
+
+ // Marshall the string into a Vertex object.
+ return gson.fromJson(json, GraphEvent.class);
+
+ } catch (Exception ex) {
+ throw new ChampServiceException("Unable to parse JSON string: ", Status.BAD_REQUEST);
+ }
+ }
+
+ @Override
+ public String toString() {
+
+ return toJson();
+ }
+
+ public String getObjectKey() {
+ if (this.getVertex() != null) {
+ return this.getVertex().getId();
+ } else if (this.getEdge() != null) {
+ return this.getEdge().getId();
+ }
+
+ return null;
+ }
+
+ public String getObjectType() {
+ if (this.getVertex() != null) {
+ return "vertex->" + this.getVertex().getType();
+ } else if (this.getEdge() != null) {
+ return "edge->" + this.getEdge().getType();
+ }
+
+ return null;
+ }
+
+ public static class Builder {
+
+ GraphEvent event = null;
+
+ public Builder(GraphEventOperation operation) {
+ event = new GraphEvent();
+ event.operation = operation;
+ }
+
+ public Builder vertex(GraphEventVertex vertex) {
+ event.vertex = vertex;
+ return this;
+ }
+
+ public Builder edge(GraphEventEdge edge) {
+ event.edge = edge;
+ return this;
+ }
+
+ public Builder result(GraphEventResult result) {
+ event.result = result;
+ return this;
+ }
+
+ public Builder errorMessage(String errorMessage) {
+ event.errorMessage = errorMessage;
+ return this;
+ }
+
+ public Builder httpErrorStatus(Status httpErrorStatus) {
+ event.httpErrorStatus = httpErrorStatus;
+ return this;
+ }
+
+ public GraphEvent build() {
+
+ event.timestamp = System.currentTimeMillis();
+ event.transactionId = java.util.UUID.randomUUID().toString();
+
+ return event;
+ }
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/event/GraphEventEdge.java b/champ-service/src/main/java/org/onap/champ/event/GraphEventEdge.java
new file mode 100644
index 0000000..1ab4804
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/event/GraphEventEdge.java
@@ -0,0 +1,221 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * 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 and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.champ.event;
+
+import java.util.Map;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.aai.champcore.model.ChampObject;
+import org.onap.aai.champcore.model.ChampRelationship;
+import org.onap.champ.exception.ChampServiceException;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.reflect.TypeToken;
+
+/**
+ * This class provides a generic representation of an Edge as provided by the
+ * graph data store.
+ */
+public class GraphEventEdge {
+
+ /**
+ * The unique identifier used to identify this edge in the graph data store.
+ */
+ @SerializedName("key")
+ private String id;
+
+ @SerializedName("schema-version")
+ private String modelVersion;
+
+ /**
+ * Type label assigned to this vertex.
+ */
+ private String type;
+
+ /**
+ * Source vertex for our edge.
+ */
+ private GraphEventVertex source;
+
+ /**
+ * Target vertex for our edge.
+ */
+ private GraphEventVertex target;
+
+ /**
+ * Map of all of the properties assigned to this vertex.
+ */
+ private JsonElement properties;
+
+ /**
+ * Marshaller/unmarshaller for converting to/from JSON.
+ */
+ private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
+
+ public GraphEventEdge(String id, String modelVersion, String type, GraphEventVertex source,
+ GraphEventVertex target, JsonElement properties) {
+ this.id = id;
+ this.modelVersion = modelVersion;
+ this.type = type;
+ this.source = source;
+ this.target = target;
+ this.properties = properties;
+ }
+
+ public GraphEventEdge() {
+
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public GraphEventVertex getSource() {
+ return source;
+ }
+
+ public void setSource(GraphEventVertex source) {
+ this.source = source;
+ }
+
+ public GraphEventVertex getTarget() {
+ return target;
+ }
+
+ public void setTarget(GraphEventVertex target) {
+ this.target = target;
+ }
+
+ public JsonElement getProperties() {
+ return properties;
+ }
+
+ public void setProperties(JsonElement properties) {
+ this.properties = properties;
+ }
+
+ public String getModelVersion() {
+ return modelVersion;
+ }
+
+ public void setModelVersion(String modelVersion) {
+ this.modelVersion = modelVersion;
+ }
+
+ /**
+ * Unmarshalls this Edge object into a JSON string.
+ *
+ * @return - A JSON format string representation of this Edge.
+ */
+ public String toJson() {
+ return gson.toJson(this);
+ }
+
+ /**
+ * Marshalls the provided JSON string into a Edge object.
+ *
+ * @param json - The JSON string to produce the Edge from.
+ * @return - A Edge object.
+ * @throws SpikeException
+ */
+ public static GraphEventEdge fromJson(String json) throws ChampServiceException {
+
+ try {
+
+ // Make sure that we were actually provided a non-empty string
+ // before we
+ // go any further.
+ if (json == null || json.isEmpty()) {
+ throw new ChampServiceException("Unable to parse JSON string: ", Status.BAD_REQUEST);
+ }
+
+ // Marshall the string into an Edge object.
+ return gson.fromJson(json, GraphEventEdge.class);
+
+ } catch (Exception ex) {
+ throw new ChampServiceException("Unable to parse JSON string: ", Status.BAD_REQUEST);
+ }
+ }
+
+ public static GraphEventEdge fromChampRelationship(ChampRelationship edge, String modelVersion) {
+
+ java.lang.reflect.Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
+ JsonObject props = gson.toJsonTree(edge.getProperties(), mapType).getAsJsonObject();
+
+ GraphEventEdge graphEventEdge = new GraphEventEdge(edge.getKey().orElse("").toString(), modelVersion,
+ edge.getType(), new GraphEventVertex(edge.getSource().getKey().orElse("").toString(), null,
+ edge.getSource().getType(), null), new GraphEventVertex(edge.getTarget().getKey().orElse("").toString(),
+ null, edge.getTarget().getType(), null), props);
+
+ return graphEventEdge;
+
+ }
+
+ public ChampRelationship toChampRelationship() {
+ ChampObject sourceChampObject=null;
+ ChampObject targetChampObject=null;
+ if (this.getSource() != null) {
+ sourceChampObject = new ChampObject.Builder(this.getSource().getType()).key(this.getSource().getId())
+ .build();
+ }
+ if (this.getTarget() != null) {
+ targetChampObject = new ChampObject.Builder(this.getTarget().getType()).key(this.getTarget().getId())
+ .build();
+ }
+
+ ChampRelationship.Builder builder = new ChampRelationship.Builder(sourceChampObject, targetChampObject, type);
+ if(this.getId()!=null && !this.getId().isEmpty()){
+ builder.key(this.getId());
+ }
+
+
+ if (this.getProperties() != null) {
+ java.lang.reflect.Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
+ Map<String, Object> propertiesMap = gson.fromJson(this.getProperties(), mapType);
+ for (String key : propertiesMap.keySet()) {
+ builder.property(key, propertiesMap.get(key));
+ }
+ }
+ return builder.build();
+
+ }
+}
diff --git a/champ-service/src/main/java/org/onap/champ/event/GraphEventVertex.java b/champ-service/src/main/java/org/onap/champ/event/GraphEventVertex.java
new file mode 100644
index 0000000..553ba46
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/event/GraphEventVertex.java
@@ -0,0 +1,187 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * 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 and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.champ.event;
+
+import java.util.Map;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.aai.champcore.model.ChampObject;
+import org.onap.champ.exception.ChampServiceException;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.reflect.TypeToken;
+
+/**
+ * This class provides a generic representation of a Vertex as provided by the
+ * graph data store.
+ */
+public class GraphEventVertex {
+
+ /**
+ * The unique identifier used to identify this vertex in the graph data
+ * store.
+ */
+ @SerializedName("key")
+ private String id;
+
+ @SerializedName("schema-version")
+ private String modelVersion;
+
+ /**
+ * Type label assigned to this vertex.
+ */
+ private String type;
+
+ /**
+ * Map of all of the properties assigned to this vertex.
+ */
+ private JsonElement properties;
+
+ /**
+ * Marshaller/unmarshaller for converting to/from JSON.
+ */
+ private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
+
+ public GraphEventVertex(String id, String modelVersion, String type, JsonElement properties) {
+ this.id = id;
+ this.modelVersion = modelVersion;
+ this.type = type;
+ this.properties = properties;
+ }
+
+ public GraphEventVertex() {
+
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+
+ public JsonElement getProperties() {
+ return properties;
+ }
+
+ public void setProperties(JsonElement properties) {
+ this.properties = properties;
+ }
+
+ public String getModelVersion() {
+ return modelVersion;
+ }
+
+ public void setModelVersion(String modelVersion) {
+ this.modelVersion = modelVersion;
+ }
+
+ /**
+ * Unmarshalls this Vertex object into a JSON string.
+ *
+ * @return - A JSON format string representation of this Vertex.
+ */
+ public String toJson() {
+ return gson.toJson(this);
+ }
+
+ /**
+ * Marshalls the provided JSON string into a Vertex object.
+ *
+ * @param json - The JSON string to produce the Vertex from.
+ * @return - A Vertex object.
+ * @throws SpikeException
+ */
+ public static GraphEventVertex fromJson(String json) throws ChampServiceException {
+
+ try {
+
+ // Make sure that we were actually provided a non-empty string
+ // before we
+ // go any further.
+ if (json == null || json.isEmpty()) {
+ throw new ChampServiceException("Empty or null JSON string.", Status.BAD_REQUEST);
+ }
+
+ // Marshall the string into a Vertex object.
+ return gson.fromJson(json, GraphEventVertex.class);
+
+ } catch (Exception ex) {
+ throw new ChampServiceException("Unable to parse JSON string: ", Status.BAD_REQUEST);
+ }
+ }
+
+ @Override
+ public String toString() {
+
+ return toJson();
+ }
+
+
+ public static GraphEventVertex fromChampObject(ChampObject champObject, String modelVersion) {
+
+ java.lang.reflect.Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
+ JsonObject props = gson.toJsonTree(champObject.getProperties(), mapType).getAsJsonObject();
+ GraphEventVertex graphEventVertex = new GraphEventVertex(champObject.getKey().orElse("").toString(),
+ modelVersion, champObject.getType(), props);
+ return graphEventVertex;
+
+ }
+
+
+ public ChampObject toChampObject() {
+ ChampObject.Builder builder = new ChampObject.Builder(this.getType());
+ if(this.getId()!=null && !this.getId().isEmpty()){
+ builder.key(this.getId());
+ }
+
+ if (this.getProperties() != null) {
+ java.lang.reflect.Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
+ Map<String, Object> propertiesMap = gson.fromJson(this.getProperties(), mapType);
+ for (String key : propertiesMap.keySet()) {
+ builder.property(key, propertiesMap.get(key));
+ }
+ }
+
+ return builder.build();
+
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/exception/ChampServiceException.java b/champ-service/src/main/java/org/onap/champ/exception/ChampServiceException.java
new file mode 100644
index 0000000..6e5e8c2
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/exception/ChampServiceException.java
@@ -0,0 +1,62 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.exception;
+
+import javax.ws.rs.core.Response.Status;
+
+public class ChampServiceException extends Exception {
+
+ private static final long serialVersionUID = 8162385108397238865L;
+
+ private Status httpStatus;
+
+ public ChampServiceException() {
+ }
+
+ public ChampServiceException(String message, Status httpStatus) {
+ super(message);
+ this.setHttpStatus(httpStatus);
+ }
+
+ public ChampServiceException(Throwable cause) {
+ super(cause);
+ }
+
+ public ChampServiceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ChampServiceException(String message, Throwable cause, boolean enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
+ public Status getHttpStatus() {
+ return httpStatus;
+ }
+
+ public void setHttpStatus(Status httpStatus) {
+ this.httpStatus = httpStatus;
+ }
+}
diff --git a/champ-service/src/main/java/org/onap/champ/service/ChampDataService.java b/champ-service/src/main/java/org/onap/champ/service/ChampDataService.java
new file mode 100644
index 0000000..7826fa2
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/ChampDataService.java
@@ -0,0 +1,355 @@
+package org.onap.champ.service;
+
+import org.onap.aai.champcore.ChampGraph;
+import org.onap.aai.champcore.ChampTransaction;
+import org.onap.aai.champcore.exceptions.ChampMarshallingException;
+import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
+import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException;
+import org.onap.aai.champcore.exceptions.ChampSchemaViolationException;
+import org.onap.aai.champcore.exceptions.ChampTransactionException;
+import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
+import org.onap.aai.champcore.model.ChampElement;
+import org.onap.aai.champcore.model.ChampObject;
+import org.onap.aai.champcore.model.ChampRelationship;
+import org.onap.aai.champcore.model.fluent.object.ObjectBuildOrPropertiesStep;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.champ.exception.ChampServiceException;
+import org.onap.champ.service.logging.ChampMsgs;
+import org.onap.champ.util.ChampProperties;
+import org.onap.champ.util.ChampServiceConstants;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.ws.rs.core.Response.Status;
+
+public class ChampDataService {
+ private ChampUUIDService champUUIDService;
+
+ private ChampGraph graphImpl;
+ private ChampTransactionCache cache;
+ private static final String KEY_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_KEY_NAME);
+ private static final String SOT_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_SOT_NAME);
+ private static final String CREATED_TS_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_CREATED_TS_NAME);
+ private static final String LAST_MOD_TS_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_LAST_MOD_TS_NAME);
+ private Logger logger = LoggerFactory.getInstance().getLogger(ChampDataService.class);
+
+
+ public ChampDataService(ChampUUIDService champUUIDService, ChampGraph graphImpl, ChampTransactionCache cache) {
+
+ this.champUUIDService = champUUIDService;
+ this.graphImpl = graphImpl;
+ this.cache = cache;
+ }
+
+ public ChampObject getObject(String id, Optional<ChampTransaction> transaction) throws ChampServiceException {
+
+ Optional<ChampObject> retrieved = Optional.empty();
+ try {
+ retrieved = champUUIDService.getObjectbyUUID(id, transaction.orElse(null));
+ } catch (ChampUnmarshallingException | ChampTransactionException e) {
+ throw new ChampServiceException("Error: " + e.getMessage(), Status.INTERNAL_SERVER_ERROR);
+ }
+ if (retrieved.isPresent()) {
+ return (ChampObject) champUUIDService.populateUUIDKey(retrieved.get());
+ } else {
+ return null;
+ }
+ }
+
+ public ChampObject storeObject(ChampObject object, Optional<ChampTransaction> transaction)
+ throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException,
+ ChampTransactionException, ChampServiceException {
+
+ if (object.getProperty(KEY_NAME).isPresent() || object.getKey().isPresent()) {
+ throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+
+ champUUIDService.populateUUIDProperty(object, java.util.UUID.randomUUID().toString());
+ addTimestamps(object, null);
+ ChampObject created = graphImpl.storeObject(object, transaction);
+ return (ChampObject) champUUIDService.populateUUIDKey(created);
+ }
+
+ public ChampObject replaceObject(ChampObject object, String objectId, Optional<ChampTransaction> transaction)
+ throws ChampServiceException, ChampUnmarshallingException, ChampTransactionException, ChampMarshallingException,
+ ChampSchemaViolationException, ChampObjectNotExistsException {
+ if (object.getKey().isPresent() && (!object.getKeyValue().equals(objectId))) {
+ throw new ChampServiceException("Object Id in the URI doesn't match the body.", Status.BAD_REQUEST);
+ }
+
+ if (object.getProperty(KEY_NAME).isPresent() && !object.getProperty(KEY_NAME).get().toString().equals(objectId)) {
+ throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+
+ Optional<ChampObject> retrieved = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null));
+ if (!retrieved.isPresent()) {
+ throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND);
+ }
+ ObjectBuildOrPropertiesStep payloadBuilder = ChampObject.create().from(object).withKey(retrieved.get().getKey().get())
+ .withProperty(KEY_NAME, objectId);
+ if (retrieved.get().getProperty(SOT_NAME).isPresent()){
+ payloadBuilder = payloadBuilder.withProperty(SOT_NAME, retrieved.get().getProperty(SOT_NAME).get());
+ }
+
+ if (object.getProperty(CREATED_TS_NAME).isPresent() && retrieved.get().getProperty(CREATED_TS_NAME).isPresent()) {
+ // the timestamps in object are parsed as strings regardless of how the input json is. Convert retrieved to string for easy comparison
+ if (!retrieved.get().getProperty(CREATED_TS_NAME).get().toString().equals(object.getProperty(CREATED_TS_NAME).get())) {
+ throw new ChampServiceException(CREATED_TS_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+ }
+
+ if (object.getProperty(LAST_MOD_TS_NAME).isPresent() && retrieved.get().getProperty(LAST_MOD_TS_NAME).isPresent()) {
+ if (!retrieved.get().getProperty(LAST_MOD_TS_NAME).get().toString().equals(object.getProperty(LAST_MOD_TS_NAME).get())) {
+ throw new ChampServiceException(LAST_MOD_TS_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+ }
+
+ ChampObject payload = payloadBuilder.build();
+ addTimestamps(payload, (Long)retrieved.get().getProperty(CREATED_TS_NAME).orElse(null));
+ ChampObject updated = graphImpl.replaceObject(payload, transaction);
+ return (ChampObject) champUUIDService.populateUUIDKey(updated);
+ }
+
+ public void deleteObject(String objectId, Optional<ChampTransaction> transaction) throws ChampServiceException,
+ ChampObjectNotExistsException, ChampTransactionException, ChampUnmarshallingException {
+ Optional<ChampObject> retrieved = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null));
+ if (!retrieved.isPresent()) {
+ throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND);
+ }
+ Stream<ChampRelationship> relationships = graphImpl.retrieveRelationships(retrieved.get(), transaction);
+
+ if (relationships.count() > 0) {
+ throw new ChampServiceException("Attempt to delete vertex with id " + objectId + " which has incident edges.",
+ Status.BAD_REQUEST);
+ }
+ graphImpl.deleteObject(retrieved.get().getKey().get(), transaction);
+
+ }
+
+ public ChampRelationship storeRelationship(ChampRelationship r, Optional<ChampTransaction> transaction)
+ throws ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException,
+ ChampRelationshipNotExistsException, ChampUnmarshallingException, ChampTransactionException,
+ ChampServiceException {
+
+ if (r.getSource() == null || !r.getSource().getKey().isPresent() || r.getTarget() == null
+ || !r.getTarget().getKey().isPresent()) {
+ logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Source/Target Object key must be provided");
+ throw new ChampServiceException("Source/Target Object key must be provided", Status.BAD_REQUEST);
+ }
+
+ if (r.getProperty(KEY_NAME).isPresent() || r.getKey().isPresent()) {
+ logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "key or " + KEY_NAME + " not allowed while creating new Objects");
+ throw new ChampServiceException("key or " + KEY_NAME + " not allowed while creating new Objects", Status.BAD_REQUEST);
+
+ }
+
+ Optional<ChampObject> source = champUUIDService.getObjectbyUUID(r.getSource().getKey().get().toString(),
+ transaction.orElse(null));
+ Optional<ChampObject> target = champUUIDService.getObjectbyUUID(r.getTarget().getKey().get().toString(),
+ transaction.orElse(null));
+
+ if (!source.isPresent() || !target.isPresent()) {
+ logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Source/Target object not found");
+ throw new ChampServiceException("Source/Target object not found", Status.BAD_REQUEST);
+ }
+
+ champUUIDService.populateUUIDProperty(r, java.util.UUID.randomUUID().toString());
+
+ ChampRelationship payload = new ChampRelationship.Builder(source.get(), target.get(), r.getType())
+ .properties(r.getProperties()).build();
+ addTimestamps(payload, null);
+ ChampRelationship created = graphImpl.storeRelationship(payload, transaction);
+ return (ChampRelationship) champUUIDService.populateUUIDKey(created);
+ }
+
+ public ChampRelationship updateRelationship(ChampRelationship r, String rId, Optional<ChampTransaction> transaction)
+ throws ChampServiceException, ChampUnmarshallingException, ChampTransactionException, ChampMarshallingException,
+ ChampSchemaViolationException, ChampRelationshipNotExistsException {
+ if (r.getKey().isPresent() && (!r.getKeyValue().equals(rId))) {
+
+ throw new ChampServiceException("Relationship Id in the URI \"" + rId + "\" doesn't match the URI in the body"
+ + " \"" + r.getKeyValue() + "\"", Status.BAD_REQUEST);
+
+ }
+
+ if (r.getProperty(KEY_NAME).isPresent() && !r.getProperty(KEY_NAME).get().toString().equals(rId)) {
+ throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+
+ Optional<ChampRelationship> retrieved = champUUIDService.getRelationshipbyUUID(rId, transaction.orElse(null));
+ if (!retrieved.isPresent()) {
+ throw new ChampServiceException(rId + " not found", Status.NOT_FOUND);
+ }
+ // check if key is present or if it equals the key that is in the URI
+ if (r.getSource() == null || !r.getSource().getKey().isPresent() || r.getTarget() == null
+ || !r.getTarget().getKey().isPresent()) {
+ throw new ChampServiceException("Source/Target Object key must be provided", Status.BAD_REQUEST);
+ }
+ ChampObject source = retrieved.get().getSource();
+ ChampObject target = retrieved.get().getTarget();
+
+ if (!source.getProperty(KEY_NAME).get().toString().equals(r.getSource().getKey().get().toString())
+ || !target.getProperty(KEY_NAME).get().toString().equals(r.getTarget().getKey().get().toString())) {
+ throw new ChampServiceException("Source/Target cannot be updated", Status.BAD_REQUEST);
+ }
+
+ if (r.getProperty(CREATED_TS_NAME).isPresent() && retrieved.get().getProperty(CREATED_TS_NAME).isPresent()) {
+ if (!retrieved.get().getProperty(CREATED_TS_NAME).get().toString().equals(r.getProperty(CREATED_TS_NAME).get())) {
+ throw new ChampServiceException(CREATED_TS_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+ }
+
+ if (r.getProperty(LAST_MOD_TS_NAME).isPresent() && retrieved.get().getProperty(LAST_MOD_TS_NAME).isPresent()) {
+ if (!retrieved.get().getProperty(LAST_MOD_TS_NAME).get().toString().equals(r.getProperty(LAST_MOD_TS_NAME).get())) {
+ throw new ChampServiceException(LAST_MOD_TS_NAME + " can't be updated", Status.BAD_REQUEST);
+ }
+ }
+
+ ChampRelationship payload = new ChampRelationship.Builder(source, target, r.getType())
+ .key(retrieved.get().getKey().get()).properties(r.getProperties()).property(KEY_NAME, rId).build();
+ addTimestamps(payload, (Long)retrieved.get().getProperty(CREATED_TS_NAME).orElse(null));
+ ChampRelationship updated = graphImpl.replaceRelationship(payload, transaction);
+ return (ChampRelationship) champUUIDService.populateUUIDKey(updated);
+ }
+
+ public void deleteRelationship(String relationshipId, Optional<ChampTransaction> transaction)
+ throws ChampServiceException, ChampRelationshipNotExistsException, ChampTransactionException,
+ ChampUnmarshallingException {
+ Optional<ChampRelationship> retrieved = champUUIDService.getRelationshipbyUUID(relationshipId,
+ transaction.orElse(null));
+ if (!retrieved.isPresent()) {
+ throw new ChampServiceException(relationshipId + " not found", Status.NOT_FOUND);
+ }
+
+ graphImpl.deleteRelationship(retrieved.get(), transaction);
+
+ }
+
+
+ public List<ChampRelationship> getRelationshipsByObject(String objectId, Optional<ChampTransaction> transaction)
+ throws ChampServiceException {
+ try {
+ Optional<ChampObject> retrievedObject = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null));
+ if (!retrievedObject.isPresent()) {
+ throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND);
+ }
+ List<ChampRelationship> relations = new ArrayList<ChampRelationship>();
+
+ Stream<ChampRelationship> retrieved = graphImpl.retrieveRelationships(retrievedObject.get(), transaction);
+ relations = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList()));
+ return relations;
+ } catch (ChampObjectNotExistsException e) {
+ throw new ChampServiceException(" obj not found", Status.NOT_FOUND);
+ } catch (ChampUnmarshallingException | ChampTransactionException e) {
+ throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+ /**
+ * Gets the ChampObjects that pass filter
+ * @param filter key/value pairs that must be present in the returned objects
+ * @param properties properties that will show up in the object
+ * @return
+ * @throws ChampServiceException
+ */
+ public List<ChampObject> queryObjects(Map<String, Object> filter, HashSet<String> properties) throws ChampServiceException {
+ try {
+
+ Stream<ChampObject> retrieved = graphImpl.queryObjects(filter);
+ List<ChampObject> objects = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList()));
+
+ if (!properties.contains("all")) {
+ for (ChampObject champObject : objects) {
+ champObject.dropProperties(properties);
+ }
+ }
+
+ return objects;
+ } catch (ChampTransactionException e) {
+ throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ public List<ChampRelationship> queryRelationships(Map<String, Object> filter) throws ChampServiceException {
+ try {
+ List<ChampRelationship> relations = new ArrayList<ChampRelationship>();
+ Stream<ChampRelationship> retrieved;
+
+ retrieved = graphImpl.queryRelationships(filter);
+
+ relations = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList()));
+ return relations;
+ } catch (ChampTransactionException e) {
+ throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ public ChampRelationship getRelationship(String id, Optional<ChampTransaction> transaction)
+ throws ChampServiceException {
+
+ Optional<ChampRelationship> retrieved = Optional.empty();
+ try {
+ retrieved = champUUIDService.getRelationshipbyUUID(id, transaction.orElse(null));
+ } catch (ChampUnmarshallingException | ChampTransactionException e) {
+ throw new ChampServiceException("Error: " + e.getMessage(), Status.INTERNAL_SERVER_ERROR);
+ }
+ if (retrieved.isPresent()) {
+ return (ChampRelationship) champUUIDService.populateUUIDKey(retrieved.get());
+ } else {
+ return null;
+ }
+ }
+
+ public String openTransaction() {
+ ChampTransaction transaction = graphImpl.openTransaction();
+ String transacId = transaction.id();
+ cache.put(transacId, transaction);
+ return transacId;
+
+ }
+
+ public void commitTransaction(String tId) throws ChampServiceException, ChampTransactionException {
+ ChampTransaction transaction = cache.get(tId);
+ if (transaction == null) {
+ throw new ChampServiceException("Transaction Not found: " + tId, Status.NOT_FOUND);
+ }
+ graphImpl.commitTransaction(transaction);
+ cache.invalidate(tId);
+ cache.invalidate(transaction.id());
+
+ }
+
+ public void rollbackTransaction(String tId) throws ChampServiceException, ChampTransactionException {
+ ChampTransaction transaction = cache.get(tId);
+ if (transaction == null) {
+ throw new ChampServiceException("Transaction Not found: " + tId, Status.NOT_FOUND);
+ }
+ graphImpl.rollbackTransaction(transaction);
+ cache.invalidate(tId);
+ cache.invalidate(transaction.id());
+
+ }
+
+ public ChampTransaction getTransaction(String id) {
+ return cache.get(id);
+ }
+
+ private void addTimestamps(ChampElement e, Long oldCreated) {
+ Long timestamp = System.currentTimeMillis();
+
+ if (oldCreated == null) {
+ e.getProperties().put(CREATED_TS_NAME, timestamp);
+ } else {
+ e.getProperties().put(CREATED_TS_NAME, oldCreated);
+ }
+
+ e.getProperties().put(LAST_MOD_TS_NAME, timestamp);
+ }
+}
diff --git a/champ-service/src/main/java/org/onap/champ/service/ChampThreadFactory.java b/champ-service/src/main/java/org/onap/champ/service/ChampThreadFactory.java
new file mode 100644
index 0000000..25fe65e
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/ChampThreadFactory.java
@@ -0,0 +1,47 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * 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 and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.onap.champ.service;
+
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Thread factory for workers.
+ */
+public class ChampThreadFactory implements ThreadFactory {
+
+ private AtomicInteger threadNumber = new AtomicInteger(1);
+
+ private String threadPrefix;
+
+
+ public ChampThreadFactory(String threadPrefix) {
+ this.threadPrefix = threadPrefix;
+ }
+
+ public Thread newThread(Runnable runnable) {
+ return new Thread(runnable, threadPrefix + "-" + threadNumber.getAndIncrement());
+ }
+}
diff --git a/champ-service/src/main/java/org/onap/champ/service/ChampTransactionCache.java b/champ-service/src/main/java/org/onap/champ/service/ChampTransactionCache.java
new file mode 100644
index 0000000..bb95147
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/ChampTransactionCache.java
@@ -0,0 +1,77 @@
+
+package org.onap.champ.service;
+
+import java.util.concurrent.TimeUnit;
+
+import org.onap.aai.champcore.ChampGraph;
+import org.onap.aai.champcore.ChampTransaction;
+import org.onap.aai.champcore.exceptions.ChampTransactionException;
+import org.onap.champ.service.logging.ChampMsgs;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.RemovalCause;
+import com.google.common.cache.RemovalListener;
+import com.google.common.cache.RemovalNotification;
+
+/**
+ * Self expiring Cache to hold request transactionIds . Events are expired
+ * automatically after configured interval
+ */
+public class ChampTransactionCache {
+ private static Logger logger = LoggerFactory.getInstance().getLogger(ChampTransactionCache
+ .class.getName());
+
+
+ private ChampGraph graphImpl;
+ private Cache<String, ChampTransaction> cache;
+
+
+
+ public ChampTransactionCache(long txTimeOutInSec,ChampGraph graphImpl) {
+ CacheBuilder builder = CacheBuilder.newBuilder().expireAfterWrite(txTimeOutInSec, TimeUnit.SECONDS)
+ .removalListener(new RemovalListener() {
+
+ public void onRemoval(RemovalNotification notification) {
+ if(notification.getCause()==RemovalCause.EXPIRED){
+ logger.info(ChampMsgs.CHAMP_TX_CACHE, "Following transaction: "+notification.getKey()+" is being evicted from cache due to timeout of " + txTimeOutInSec+" seconds");
+ try {
+ graphImpl.rollbackTransaction((ChampTransaction) notification.getValue());
+ logger.info(ChampMsgs.CHAMP_TX_CACHE, "Transaction rolledback successfully :" + notification.getKey());
+ } catch (ChampTransactionException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ });
+ cache = builder.build();
+
+ this.graphImpl = graphImpl;
+
+ }
+
+ public void put(String txId, ChampTransaction tx) {
+ cache.put(txId, tx);
+
+ }
+
+ public ChampTransaction get(String txId) {
+ if (txId==null)
+ return null;
+ if(cache.getIfPresent(txId)==null){
+ //cleanup cache so that removalListener is called
+ cache.cleanUp();
+ }
+ return cache.getIfPresent(txId);
+ }
+
+ public void invalidate(String txId) {
+ cache.invalidate(txId);
+ }
+
+
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/service/ChampUUIDService.java b/champ-service/src/main/java/org/onap/champ/service/ChampUUIDService.java
new file mode 100644
index 0000000..39c775b
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/ChampUUIDService.java
@@ -0,0 +1,115 @@
+package org.onap.champ.service;
+
+import org.onap.aai.champcore.ChampGraph;
+import org.onap.aai.champcore.ChampTransaction;
+import org.onap.aai.champcore.exceptions.ChampTransactionException;
+import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
+import org.onap.aai.champcore.model.ChampElement;
+import org.onap.aai.champcore.model.ChampObject;
+import org.onap.aai.champcore.model.ChampRelationship;
+import org.onap.champ.exception.ChampServiceException;
+import org.onap.champ.util.ChampProperties;
+import org.onap.champ.util.ChampServiceConstants;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+public class ChampUUIDService {
+ private ChampGraph graphImpl;
+ private static final String KEY_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_KEY_NAME);
+
+
+ public ChampUUIDService(ChampGraph graphImpl) {
+ this.graphImpl = graphImpl;
+ }
+
+ public List populateUUIDKey(List<ChampElement> elements) {
+ {
+ List response = new ArrayList();
+ for (ChampElement e : elements) {
+ ChampElement item = populateUUIDKey(e);
+ if (item != null) {
+ response.add(item);
+ }
+ }
+ return response;
+ }
+
+ }
+
+ public ChampElement populateUUIDKey(ChampElement e) {
+ {
+ ChampElement response = null;
+
+ if (e.isObject()) {
+ if (e.asObject().getProperty(KEY_NAME).isPresent()) {
+ response = (ChampObject.create().from(e.asObject())
+ .withKey(e.asObject().getProperty(KEY_NAME).get().toString()).build());
+ }
+ } else {
+ if (e.asRelationship().getProperty(KEY_NAME).isPresent()
+ && e.asRelationship().getSource().getProperty(KEY_NAME).isPresent()
+ && e.asRelationship().getTarget().getProperty(KEY_NAME).isPresent()) {
+ ChampObject source = ChampObject.create().from(e.asRelationship().getSource())
+ .withKey(e.asRelationship().getSource().getProperty(KEY_NAME).get().toString()).build();
+ ChampObject target = ChampObject.create().from(e.asRelationship().getTarget())
+ .withKey(e.asRelationship().getTarget().getProperty(KEY_NAME).get().toString()).build();
+ ChampRelationship rel = new ChampRelationship.Builder(source, target, e.asRelationship().getType())
+ .key(e.asRelationship().getProperty(KEY_NAME).get().toString())
+ .properties(e.asRelationship().getProperties()).build();
+ response = rel;
+ }
+
+ }
+
+ return response;
+ }
+
+ }
+
+ public void populateUUIDProperty(ChampElement e, String uuid) {
+ e.getProperties().put(KEY_NAME, uuid);
+ }
+
+
+ public Optional<ChampObject> getObjectbyUUID(String uuid, ChampTransaction transaction)
+ throws ChampUnmarshallingException, ChampTransactionException, ChampServiceException {
+ Optional<ChampObject> response = Optional.empty();
+
+ Stream<ChampObject> s;
+ Map<String, Object> filter = new HashMap<>();
+ filter.put(KEY_NAME, uuid);
+
+ s = graphImpl.queryObjects(filter, Optional.ofNullable(transaction));
+ Object[] objs = s.toArray();
+ if (objs.length == 0) {
+ return response;
+ }
+ response = graphImpl.retrieveObject(((ChampObject) objs[0]).getKey().get(), Optional.ofNullable(transaction));
+ return response;
+ }
+
+ public Optional<ChampRelationship> getRelationshipbyUUID(String uuid, ChampTransaction transaction)
+ throws ChampUnmarshallingException, ChampTransactionException, ChampServiceException {
+ Optional<ChampRelationship> response = Optional.empty();
+
+
+ Stream<ChampRelationship> s;
+ Map<String, Object> filter = new HashMap<>();
+ filter.put(KEY_NAME, uuid);
+
+ s = graphImpl.queryRelationships(filter, Optional.ofNullable(transaction));
+ Object[] objs = s.toArray();
+ if (objs.length == 0) {
+ return response;
+ }
+ response = graphImpl.retrieveRelationship(((ChampRelationship) objs[0]).getKey().get(),
+ Optional.ofNullable(transaction));
+ return response;
+ }
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/service/EchoService.java b/champ-service/src/main/java/org/onap/champ/service/EchoService.java
new file mode 100644
index 0000000..c8236b1
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/EchoService.java
@@ -0,0 +1,54 @@
+/**
+ * ============LICENSE_START==========================================
+ * org.onap.aai
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.service;
+
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+
+public class EchoService {
+
+ private static Logger logger = LoggerFactory.getInstance()
+ .getLogger(EchoService.class.getName());
+ private static Logger auditLogger = LoggerFactory.getInstance()
+ .getAuditLogger(EchoService.class.getName());
+
+ @GET
+ @Path("echo/{input}")
+ @Produces("text/plain")
+ public String ping(@PathParam("input") String input,
+ @Context HttpHeaders headers,
+ @Context UriInfo info,
+ @Context HttpServletRequest req) {
+
+ return "Hello, " + input + ".";
+ }
+} \ No newline at end of file
diff --git a/champ-service/src/main/java/org/onap/champ/service/logging/ChampMsgs.java b/champ-service/src/main/java/org/onap/champ/service/logging/ChampMsgs.java
new file mode 100644
index 0000000..2ddbff4
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/logging/ChampMsgs.java
@@ -0,0 +1,130 @@
+/**
+ * ============LICENSE_START==========================================
+ * org.onap.aai
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.service.logging;
+
+import com.att.eelf.i18n.EELFResourceManager;
+import org.onap.aai.cl.eelf.LogMessageEnum;
+
+public enum ChampMsgs implements LogMessageEnum {
+
+ /**
+ * Received request {0} {1} from {2}. Sending response: {3}
+ *
+ * <p>
+ * Arguments: {0} = operation {1} = target URL {2} = source {3} = response
+ * code
+ */
+ PROCESS_REST_REQUEST,
+ /**
+ * Processed event {0}. Result: {1}.
+ *
+ * Arguments: {0} = event {1} = result
+ */
+ PROCESS_EVENT,
+
+ /**
+ * Query: {0}
+ * Arguments: {0} = query
+ */
+ QUERY,
+
+ /**
+ * Arguments: {0} = transactionID, {1} = request
+ */
+ INCOMING_REQUEST,
+
+ /**
+ * Arguments: {0} = HTTP request type, {1} = time to process in milliseconds
+ */
+ PROCESSED_REQUEST,
+
+ /**
+ * Arguments: {0} = transaction ID
+ */
+ TRANSACTION_NOT_FOUND,
+
+ /**
+ * Arguments: {0} = request, {1} = Error
+ */
+ BAD_REQUEST,
+
+ /**
+ * Arguments: {0} = Info
+ */
+ CHAMP_TX_CACHE,
+
+ /**
+ * Any info log related to CHAMP_ASYNC_REQUEST_PROCESSOR_INFO
+ *
+ * <p>Arguments:
+ * {0} - Info.
+ */
+ CHAMP_ASYNC_REQUEST_PROCESSOR_INFO,
+ CHAMP_ASYNC_REQUEST_PROCESSOR_WARN,
+
+ /**
+ * Any error log related to CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR
+ *
+ * <p>Arguments:
+ * {0} - Error.
+ */
+ CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR,
+
+ /**
+ * Any info log related to CHAMP_DATA_SERVICE_INFO
+ *
+ * <p>Arguments:
+ * {0} - Info.
+ */
+ CHAMP_DATA_SERVICE_INFO,
+
+ /**
+ * Any error log related to CHAMP_DATA_SERVICE_INFO
+ *
+ * <p>Arguments:
+ * {0} - Error.
+ */
+ CHAMP_DATA_SERVICE_ERROR,
+
+
+ /**
+ * Any info log related to CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO
+ *
+ * <p>Arguments:
+ * {0} - Info.
+ */
+ CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO,
+
+ /**
+ * Any error log related to CHAMP_ASYNC_RESPONSE_PUBLISHER_ERROR
+ *
+ * <p>Arguments:
+ * {0} - Error.
+ */
+ CHAMP_ASYNC_RESPONSE_PUBLISHER_ERROR;
+ /**
+ * Static initializer to ensure the resource bundles for this class are loaded...
+ */
+ static {
+ EELFResourceManager.loadMessageBundle("logging/ChampMsgs");
+ }
+}
diff --git a/champ-service/src/main/java/org/onap/champ/service/logging/LoggingUtil.java b/champ-service/src/main/java/org/onap/champ/service/logging/LoggingUtil.java
new file mode 100644
index 0000000..b7f0e77
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/service/logging/LoggingUtil.java
@@ -0,0 +1,92 @@
+/**
+ * ============LICENSE_START=======================================================
+ * Gizmo
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property.
+ * Copyright © 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+package org.onap.champ.service.logging;
+
+import org.onap.aai.cl.api.LogFields;
+import org.onap.aai.cl.api.LogLine;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.mdc.MdcContext;
+
+import org.slf4j.MDC;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+public class LoggingUtil {
+ /**
+ * Initializes mdc context.
+ */
+ public static void initMdcContext(HttpServletRequest httpReq, HttpHeaders headers) {
+ String fromIp = httpReq.getRemoteAddr();
+ String fromAppId = "";
+ String transId = null;
+
+ if (headers.getRequestHeaders().getFirst("X-FromAppId") != null) {
+ fromAppId = headers.getRequestHeaders().getFirst("X-FromAppId");
+ }
+
+ if ((headers.getRequestHeaders().getFirst("X-TransactionId") == null)
+ || headers.getRequestHeaders().getFirst("X-TransactionId").isEmpty()) {
+ transId = java.util.UUID.randomUUID().toString();
+ } else {
+ transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ }
+
+ MdcContext.initialize(transId, "ChampService", "", fromAppId, fromIp);
+ }
+
+ /**
+ * Logs the rest request.
+ */
+ public static void logRestRequest(Logger logger, Logger auditLogger, HttpServletRequest req, Response response) {
+ String respStatusString = "";
+ if (Response.Status.fromStatusCode(response.getStatus()) != null) {
+ respStatusString = Response.Status.fromStatusCode(response.getStatus()).toString();
+ }
+
+ // Generate error log
+ logger.info(ChampMsgs.PROCESS_REST_REQUEST, req.getMethod(), req.getRequestURL().toString(),
+ req.getRemoteHost(), Integer.toString(response.getStatus()));
+
+ // Generate audit log.
+ auditLogger.info(ChampMsgs.PROCESS_REST_REQUEST,
+ new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, response.getStatus())
+ .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, respStatusString),
+ (req != null) ? req.getMethod() : "Unknown", (req != null) ? req.getRequestURL().toString() : "Unknown",
+ (req != null) ? req.getRemoteHost() : "Unknown", Integer.toString(response.getStatus()) + " payload: "
+ + (response.getEntity() == null ? "" : response.getEntity().toString()));
+ MDC.clear();
+ }
+
+ public static void logInternalError(Logger logger, Exception ex) {
+ StringWriter writer = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(writer);
+ ex.printStackTrace(printWriter);
+ logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Internal error: " + ex.getMessage() + "\n" + writer.toString());
+ }
+}
diff --git a/champ-service/src/main/java/org/onap/champ/util/ChampProperties.java b/champ-service/src/main/java/org/onap/champ/util/ChampProperties.java
new file mode 100644
index 0000000..178da97
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/util/ChampProperties.java
@@ -0,0 +1,53 @@
+package org.onap.champ.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+public class ChampProperties {
+
+ private static Properties properties;
+
+ static {
+ properties = new Properties();
+ File file = new File(ChampServiceConstants.CHAMP_CONFIG_FILE);
+ try {
+ properties.load(new FileInputStream(file));
+ } catch (IOException e) {
+ e.printStackTrace();
+ Runtime.getRuntime().halt(1);
+ }
+ }
+
+ public static String get(String key) {
+ return properties.getProperty(key);
+ }
+
+ public static String get(String key, String defaultValue) {
+ return properties.getProperty(key, defaultValue);
+ }
+
+ public static void put(String key, String value) {
+ properties.setProperty(key, value);
+ FileOutputStream fileOut = null;
+ try {
+ fileOut = new FileOutputStream(new File(ChampServiceConstants.CHAMP_CONFIG_FILE));
+ properties.store(fileOut, "Added property: " + key);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+
+ try {
+ fileOut.close();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ }
+
+
+}
diff --git a/champ-service/src/main/java/org/onap/champ/util/ChampServiceConstants.java b/champ-service/src/main/java/org/onap/champ/util/ChampServiceConstants.java
new file mode 100644
index 0000000..94a9972
--- /dev/null
+++ b/champ-service/src/main/java/org/onap/champ/util/ChampServiceConstants.java
@@ -0,0 +1,14 @@
+package org.onap.champ.util;
+
+public class ChampServiceConstants {
+ public static final String CHAMP_FILESEP = (System.getProperty("file.separator") == null) ? "/"
+ : System.getProperty("file.separator");
+
+ public static final String CHAMP_SPECIFIC_CONFIG = System.getProperty("CONFIG_HOME") + CHAMP_FILESEP;
+ public static final String CHAMP_CONFIG_FILE = CHAMP_SPECIFIC_CONFIG + "champ-api.properties";
+ public static final String CHAMP_KEY_NAME = "keyName";
+ public static final String CHAMP_SOT_NAME = "sourceOfTruthName";
+ public static final String CHAMP_CREATED_TS_NAME = "createdTsName";
+ public static final String CHAMP_LAST_MOD_TS_NAME = "lastModTsName";
+ public static final String CHAMP_COLLECTION_PROPERTIES_KEY = "collectionPropertiesKey";
+} \ No newline at end of file
diff --git a/champ-service/src/main/resources/META-INF/services/javax.ws.rs.client.ClientBuilder b/champ-service/src/main/resources/META-INF/services/javax.ws.rs.client.ClientBuilder
new file mode 100644
index 0000000..48b9fa5
--- /dev/null
+++ b/champ-service/src/main/resources/META-INF/services/javax.ws.rs.client.ClientBuilder
@@ -0,0 +1 @@
+org.glassfish.jersey.client.JerseyClientBuilder \ No newline at end of file
diff --git a/champ-service/src/main/resources/logging/ChampMsgs.properties b/champ-service/src/main/resources/logging/ChampMsgs.properties
new file mode 100644
index 0000000..776b178
--- /dev/null
+++ b/champ-service/src/main/resources/logging/ChampMsgs.properties
@@ -0,0 +1,78 @@
+#Resource key=Error Code|Message text|Resolution text |Description text
+#######
+#Newlines can be utilized to add some clarity ensuring continuing line
+#has atleast one leading space
+#ResourceKey=\
+# ERR0000E\
+# Sample error msg txt\
+# Sample resolution msg\
+# Sample description txt
+#
+######
+#Error code classification category
+#000 Info/Debug
+#100 Permission errors
+#200 Availability errors/Timeouts
+#300 Data errors
+#400 Schema Interface type/validation errors
+#500 Business process errors
+#900 Unknown errors
+#
+########################################################################
+PROCESS_REST_REQUEST=\
+ CS0005I|\
+ Received request {0} {1} from {2}. Sending response: {3}|\
+ None. Received the specified REST request from the source specified.|\
+ Received the specified REST request from the source specified, and the CHAMP service sent the specified response.
+
+PROCESS_EVENT=\
+ CS0001I|\
+ Processed event {0} Result: {1}
+
+QUERY=\
+ CS0002I|\
+ Query Recieved: {0}
+
+INCOMING_REQUEST=\
+ CS0003I|\
+ Incoming Request with Transaction ID {0} and request {1}
+
+PROCESSED_REQUEST=\
+ CS0004I|\
+ Processed Champ {0} request in {1} ms
+
+TRANSACTION_NOT_FOUND=\
+ CS0001E|\
+ Transaction with ID {0} was not found.
+
+BAD_REQUEST=\
+ CS0002E|\
+ Bad Request {0}. Error is {1}
+
+CHAMP_TX_CACHE=\
+ CS0006I|\
+ ChampTransactionCache: {0}
+CHAMP_DATA_SERVICE_ERROR=\
+ CRD0510E|\
+ ChampDataService Error: {0}
+CHAMP_DATA_CACHE_INFO=\
+ CRD0511I|\
+ ChampDataService: {0}
+CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR=\
+ CRD0512E|\
+ ChampAsyncRequestProcessor Error: {0}
+CHAMP_ASYNC_REQUEST_PROCESSOR_WARN=\
+ CRD0514E|\
+ ChampAsyncRequestProcessor Warning: {0}
+CHAMP_ASYNC_REQUEST_PROCESSOR_INFO=\
+ CRD0512I|\
+ ChampAsyncRequestProcessor: {0}
+CHAMP_ASYNC_RESPONSE_PUBLISHER_ERROR=\
+ CRD0513E|\
+ ChampAsyncRequestProcessor Error: {0}
+CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO=\
+ CRD0513I|\
+ ChampAsyncRequestProcessor: {0}
+
+
+
diff --git a/champ-service/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context b/champ-service/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context
new file mode 100644
index 0000000..8514196
--- /dev/null
+++ b/champ-service/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context
@@ -0,0 +1 @@
+{"context":{"contextClass":"ajsc.Context","contextId":"__module_ajsc_namespace_name__:__module_ajsc_namespace_version__","contextName":"__module_ajsc_namespace_name__","contextVersion":"__module_ajsc_namespace_version__","description":"__module_ajsc_namespace_name__ Context"}} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/context/default#0.context b/champ-service/src/main/runtime/context/default#0.context
new file mode 100644
index 0000000..d1b5ab4
--- /dev/null
+++ b/champ-service/src/main/runtime/context/default#0.context
@@ -0,0 +1 @@
+{"context":{"contextClass":"ajsc.Context","contextId":"default:0","contextName":"default","contextVersion":"0","description":"Default Context"}} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json b/champ-service/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json
new file mode 100644
index 0000000..d0954cf
--- /dev/null
+++ b/champ-service/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json
@@ -0,0 +1 @@
+{"deploymentPackage":{"Class":"ajsc.DeploymentPackage","Id":"__module.ajsc.namespace.name__:__module_ajsc_namespace_version__","namespace":"__module_ajsc_namespace_name__","namespaceVersion":"__module_ajsc_namespace_version__","description":"__module_ajsc_namespace_name__ __module_ajsc_namespace_version__ - default description","userId":"ajsc"}} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroRole/ajscadmin.json b/champ-service/src/main/runtime/shiroRole/ajscadmin.json
new file mode 100644
index 0000000..f5e981e
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroRole/ajscadmin.json
@@ -0,0 +1 @@
+{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"ajscadmin","name":"ajscadmin","permissions":"[ajscadmin:*, ajsc:*]"} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json b/champ-service/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json
new file mode 100644
index 0000000..2dae9f5
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json
@@ -0,0 +1 @@
+{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"contextadmin:__module_ajsc_namespace_name__","name":"contextadmin:__module_ajsc_namespace_name__","permissions":"[]"} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroRole/contextadmin#default.json b/champ-service/src/main/runtime/shiroRole/contextadmin#default.json
new file mode 100644
index 0000000..5de814e
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroRole/contextadmin#default.json
@@ -0,0 +1 @@
+{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"contextadmin:default","name":"contextadmin:default","permissions":"[]"} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroUser/ajsc.json b/champ-service/src/main/runtime/shiroUser/ajsc.json
new file mode 100644
index 0000000..f4c7855
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroUser/ajsc.json
@@ -0,0 +1 @@
+{"shiroUserClass":"ajsc.auth.ShiroUser","shiroUserId":"ajsc","passwordHash":"9471697417008c880720ba54c6038791ad7e98f3b88136fe34f4d31a462dd27a","permissions":"[*:*]","username":"ajsc"} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json b/champ-service/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json
new file mode 100644
index 0000000..cb8d483
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json
@@ -0,0 +1 @@
+{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:ajscadmin","roleId":"ajscadmin","userId":"ajsc"} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json b/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json
new file mode 100644
index 0000000..95d2361
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json
@@ -0,0 +1 @@
+{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:contextadmin:__module_ajsc_namespace_name__","roleId":"contextadmin:__module_ajsc_namespace_name__","userId":"ajsc"} \ No newline at end of file
diff --git a/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json b/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json
new file mode 100644
index 0000000..2bd5063
--- /dev/null
+++ b/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json
@@ -0,0 +1 @@
+{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:contextadmin:default","roleId":"contextadmin:default","userId":"ajsc"} \ No newline at end of file