Adding services engine module 39/50639/6
authorwaqas.ikram <waqas.ikram@ericsson.com>
Wed, 6 Jun 2018 10:04:36 +0000 (11:04 +0100)
committerwaqas.ikram <waqas.ikram@ericsson.com>
Wed, 6 Jun 2018 15:03:06 +0000 (16:03 +0100)
Change-Id: I68bbe6d95d17cfcdda204d1ee3eec3b92d12ebd4
Issue-ID: POLICY-859
Signed-off-by: waqas.ikram <waqas.ikram@ericsson.com>
158 files changed:
auth/cli-editor/pom.xml
pom.xml
services/pom.xml [new file with mode: 0644]
services/services-engine/pom.xml [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/engdep/EngDepMessageListener.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/engdep/EngDepMessagingService.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/engdep/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEvent.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventConsumer.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventConverter.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventException.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventList.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventProducer.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventProtocolConverter.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventReceiver.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventRuntimeException.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexPeriodicEventGenerator.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/PeeredReference.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/SynchronousEventCache.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/EventConsumerFactory.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/EventProducerFactory.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/EventProtocolFactory.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/apexprotocolplugin/Apex2ApexEventConverter.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/apexprotocolplugin/ApexEventProtocolParameters.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/apexprotocolplugin/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/enevent/ApexEvent2EnEventConverter.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/enevent/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/eventrequestor/EventRequestorCarrierTechnologyParameters.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/eventrequestor/EventRequestorConsumer.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/eventrequestor/EventRequestorProducer.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/eventrequestor/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/FILECarrierTechnologyParameters.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/ApexFileEventConsumer.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/CharacterDelimitedTextBlockReader.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/HeaderDelimitedTextBlockReader.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/TextBlock.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/TextBlockReader.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/TextBlockReaderFactory.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/producer/ApexFileEventProducer.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/producer/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/jsonprotocolplugin/Apex2JSONEventConverter.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/jsonprotocolplugin/JSONEventProtocolParameters.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/jsonprotocolplugin/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivator.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivatorException.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivatorRuntimeException.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexCommandLineArguments.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexEngineServiceHandler.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexEventMarshaller.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexEventUnmarshaller.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexMain.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/ApexEventListener.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/EngineService.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/EngineServiceEventInterface.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EnEventListenerImpl.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EngineServiceImpl.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EngineWorker.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterException.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterHandler.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterRuntimeException.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterValidator.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameters.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/carriertechnology/CarrierTechnologyParameters.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/carriertechnology/CarrierTechnologyParametersJSONAdapter.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/carriertechnology/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/engineservice/EngineServiceParameters.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/engineservice/EngineServiceParametersJSONAdapter.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/engineservice/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventhandler/EventHandlerParameters.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventhandler/EventHandlerPeeredMode.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventhandler/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/EventProtocolParameters.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/EventProtocolParametersJSONAdapter.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/EventProtocolTextCharDelimitedParameters.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/EventProtocolTextTokenDelimitedParameters.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/package-info.java [new file with mode: 0644]
services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/package-info.java [new file with mode: 0644]
services/services-engine/src/main/resources/version.txt [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/event/JSONEventGenerator.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/event/TestJSONEventHandler.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/event/TestJSONTaggedEventConsumer.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/event/TestPluginFactories.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/main/TestApexCommandLineArguments.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/ContextParameterTests.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/ExecutorParameterTests.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/ParameterTests.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/ProducerConsumerTests.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/SyncParameterTests.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperCarrierTechnologyParameters.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperDistributorParameters.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperEventProducer.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperEventSubscriber.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperExecutorParameters.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperTokenDelimitedEventConverter.java [new file with mode: 0644]
services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperTokenDelimitedEventProtocolParameters.java [new file with mode: 0644]
services/services-engine/src/test/resources/logback-test.xml [new file with mode: 0644]
services/services-engine/src/test/resources/main/DummyModelFile.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/badParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/blankParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/empty.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/factoryGoodParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/goodParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/noParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/prodConsBadCTParClass.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/prodConsBadEPParClass.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/prodConsBadFileName.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/prodConsMismatchCTParClass.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/prodConsMismatchEPParClass.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/prodConsNoCT.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/prodConsNoCTParClass.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/prodConsNoEP.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/prodConsNoEPParClass.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/prodConsOKFileName.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/prodConsWrongTypeCTParClass.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/prodConsWrongTypeEPParClass.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceContextBadClassDistParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceContextBadClassLockParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceContextBadClassParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceContextBadClassPersistParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceContextBadParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceContextBadPluginClassParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceContextBadPluginNameParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceContextNoParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceContextOKDefaultParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceContextOKDistParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceContextOKFlushParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceContextOKFullParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceExecutorBadParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceExecutorBadPluginNameParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceExecutorBadPluginValueBlankParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceExecutorBadPluginValueObjectParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceExecutorBadPluginValueParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceExecutorEmptyParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceExecutorNoExecutorParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/serviceExecutorNoParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/superDooperParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncBadParamsBadPeers.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncBadParamsBadTimeout.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncBadParamsInvalidTimeout.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncBadParamsNoSyncWithPeer.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncBadParamsNotSyncWithPeer.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncBadParamsUnpairedTimeout.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncGoodParams.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncGoodParamsBothTimeout.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncGoodParamsConsumerTimeout.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncGoodParamsProducerTimeout.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncMismatchedPeers.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncUnusedConsumerPeers.json [new file with mode: 0644]
services/services-engine/src/test/resources/parameters/syncUnusedProducerPeers.json [new file with mode: 0644]
services/services-engine/src/test/resources/policymodels/SamplePolicyModelMVEL.json [new file with mode: 0644]

index 1f1863d..0252fed 100644 (file)
@@ -41,7 +41,7 @@
         <dependency>
             <groupId>commons-cli</groupId>
             <artifactId>commons-cli</artifactId>
-            <version>1.4</version>
+            <version>${version.commons-cli}</version>
         </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 2fd8a0a..aa84f24 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -40,6 +40,7 @@
         <encoding>UTF-8</encoding>
         <file.encoding>UTF-8</file.encoding>
         <version.derby>10.13.1.1</version.derby>
+        <version.commons-cli>1.4</version.commons-cli>
     </properties>
 
     <distributionManagement>
         <module>context</module>
         <module>core</module>
         <module>auth</module>
+        <module>services</module>
         <module>plugins</module>
     </modules>
 </project>
\ No newline at end of file
diff --git a/services/pom.xml b/services/pom.xml
new file mode 100644 (file)
index 0000000..031dd9c
--- /dev/null
@@ -0,0 +1,40 @@
+<!--
+  ============LICENSE_START=======================================================
+   Copyright (C) 2018 Ericsson. 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.
+
+  SPDX-License-Identifier: Apache-2.0
+  ============LICENSE_END=========================================================
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.onap.policy.apex-pdp</groupId>
+        <artifactId>apex-pdp</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.onap.policy.apex-pdp.services</groupId>
+    <artifactId>services</artifactId>
+    <packaging>pom</packaging>
+
+    <name>${project.artifactId}</name>
+    <description>The main services of Apex, deployment independent.</description>
+
+    <modules>
+        <module>services-engine</module>
+    </modules>
+</project>
\ No newline at end of file
diff --git a/services/services-engine/pom.xml b/services/services-engine/pom.xml
new file mode 100644 (file)
index 0000000..cde5d3b
--- /dev/null
@@ -0,0 +1,81 @@
+<!--
+  ============LICENSE_START=======================================================
+   Copyright (C) 2018 Ericsson. 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.
+
+  SPDX-License-Identifier: Apache-2.0
+  ============LICENSE_END=========================================================
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.onap.policy.apex-pdp.services</groupId>
+        <artifactId>services</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>services-engine</artifactId>
+    <name>${project.artifactId}</name>
+    <description>External services provided by the Apex policy execution engine</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.core</groupId>
+            <artifactId>core-engine</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.core</groupId>
+            <artifactId>core-infrastructure</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.core</groupId>
+            <artifactId>core-protocols</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.context</groupId>
+            <artifactId>context-test</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-cli</groupId>
+            <artifactId>commons-cli</artifactId>
+            <version>${version.commons-cli}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <!-- Output the version of Apex -->
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/version.txt</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>false</filtering>
+                <excludes>
+                    <exclude>**/version.txt</exclude>
+                </excludes>
+            </resource>
+        </resources>
+    </build>
+</project>
\ No newline at end of file
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/engdep/EngDepMessageListener.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/engdep/EngDepMessageListener.java
new file mode 100644 (file)
index 0000000..311e3b6
--- /dev/null
@@ -0,0 +1,364 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.engdep;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.TimeUnit;
+
+import org.java_websocket.WebSocket;
+import org.onap.policy.apex.core.infrastructure.messaging.MessageHolder;
+import org.onap.policy.apex.core.infrastructure.messaging.MessageListener;
+import org.onap.policy.apex.core.infrastructure.messaging.impl.ws.messageblock.MessageBlock;
+import org.onap.policy.apex.core.infrastructure.messaging.util.MessagingUtils;
+import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities;
+import org.onap.policy.apex.core.protocols.Message;
+import org.onap.policy.apex.core.protocols.engdep.EngDepAction;
+import org.onap.policy.apex.core.protocols.engdep.messages.EngineServiceInfoResponse;
+import org.onap.policy.apex.core.protocols.engdep.messages.GetEngineInfo;
+import org.onap.policy.apex.core.protocols.engdep.messages.GetEngineServiceInfo;
+import org.onap.policy.apex.core.protocols.engdep.messages.GetEngineStatus;
+import org.onap.policy.apex.core.protocols.engdep.messages.Response;
+import org.onap.policy.apex.core.protocols.engdep.messages.StartEngine;
+import org.onap.policy.apex.core.protocols.engdep.messages.StartPeriodicEvents;
+import org.onap.policy.apex.core.protocols.engdep.messages.StopEngine;
+import org.onap.policy.apex.core.protocols.engdep.messages.StopPeriodicEvents;
+import org.onap.policy.apex.core.protocols.engdep.messages.UpdateModel;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.service.engine.runtime.EngineService;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import com.google.common.eventbus.Subscribe;
+
+/**
+ * The listener interface for receiving engDepMessage events. The class that is interested in
+ * processing a engDepMessage event implements this interface, and the object created with that
+ * class is registered with a component using the component's <code>addEngDepMessageListener</code>
+ * method. When the engDepMessage event occurs, that object's appropriate method is invoked.
+ *
+ * This class uses a queue to buffer incoming messages. When the listener is called, it places the
+ * incoming message on the queue. A thread runs which removes the messages from the queue and
+ * forwards them to the Apex engine.
+ *
+ * @author Sajeevan Achuthan (sajeevan.achuthan@ericsson.com)
+ */
+public class EngDepMessageListener implements MessageListener<Message>, Runnable {
+    private static final int LISTENER_STOP_WAIT_INTERVAL = 10;
+
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(EngDepMessageListener.class);
+
+    // The timeout to wait between queue poll timeouts in milliseconds
+    private static final long QUEUE_POLL_TIMEOUT = 50;
+
+    // The Apex service itself
+    private final EngineService apexService;
+
+    // The message listener thread and stopping flag
+    private Thread messageListenerThread;
+    private boolean stopOrderedFlag = false;
+
+    // The message queue is used to hold messages prior to forwarding to Apex
+    private final BlockingQueue<MessageBlock<Message>> messageQueue = new LinkedBlockingDeque<>();
+
+    /**
+     * Instantiates a new EngDep message listener for listening for messages coming in from the
+     * Deployment client. The <code>apexService</code> is the Apex service to send the messages
+     * onto.
+     *
+     * @param apexService the Apex engine service
+     */
+    protected EngDepMessageListener(final EngineService apexService) {
+        this.apexService = apexService;
+    }
+
+    /**
+     * This method is an implementation of the message listener. It receives a message and places it
+     * on the queue for processing by the message listening thread.
+     *
+     * @param data the data
+     * @see org.onap.policy.apex.core.infrastructure.messaging.MessageListener#onMessage
+     *      (org.onap.policy.apex.core.infrastructure.messaging.impl.ws.data.Data)
+     */
+    @Subscribe
+    @Override
+    public void onMessage(final MessageBlock<Message> data) {
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("message received from client application {} port {}",
+                    data.getConnection().getRemoteSocketAddress().getAddress(),
+                    data.getConnection().getRemoteSocketAddress().getPort());
+        }
+        messageQueue.add(data);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.core.infrastructure.messaging.MessageListener#onMessage(java.lang.
+     * String)
+     */
+    @Override
+    public void onMessage(final String messageString) {
+        throw new UnsupportedOperationException("String messages are not supported on the EngDep protocol");
+    }
+
+    /**
+     * This method gets a new message listening thread from the thread factory and starts it.
+     */
+    public void startProcessorThread() {
+        LOGGER.entry();
+        messageListenerThread = new Thread(this);
+        messageListenerThread.setDaemon(true);
+        messageListenerThread.start();
+        LOGGER.exit();
+    }
+
+    /**
+     * Stops the message listening threads.
+     */
+    public void stopProcessorThreads() {
+        LOGGER.entry();
+        stopOrderedFlag = true;
+
+        while (messageListenerThread.isAlive()) {
+            ThreadUtilities.sleep(LISTENER_STOP_WAIT_INTERVAL);
+        }
+        LOGGER.exit();
+    }
+
+    /**
+     * Runs the message listening thread. Here, the messages come in on the message queue and are
+     * processed one by one
+     */
+    @Override
+    public void run() {
+        // Take messages off the queue and forward them to the Apex engine
+        while (messageListenerThread.isAlive() && !stopOrderedFlag) {
+            try {
+                final MessageBlock<Message> data = messageQueue.poll(QUEUE_POLL_TIMEOUT, TimeUnit.MILLISECONDS);
+                if (data != null) {
+                    final List<Message> messages = data.getMessages();
+                    for (final Message message : messages) {
+                        handleMessage(message, data.getConnection());
+                    }
+                }
+            } catch (final InterruptedException e) {
+                LOGGER.debug("message listener execution has been interrupted");
+                break;
+            }
+        }
+    }
+
+    /**
+     * This method handles EngDep messages as they come in. It uses the inevitable switch statement
+     * to handle the messages.
+     *
+     * @param message the incoming EngDep message
+     * @param webSocket the web socket on which the message came in
+     */
+    private void handleMessage(final Message message, final WebSocket webSocket) {
+        LOGGER.entry(webSocket.getRemoteSocketAddress().toString());
+        if (message.getAction() == null) {
+            // This is a response message
+            return;
+        }
+
+        try {
+            LOGGER.debug("Manager action {} being applied to engine", message.getAction());
+
+            // Get and check the incoming action for validity
+            EngDepAction enDepAction = null;
+            if (message.getAction() instanceof EngDepAction) {
+                enDepAction = (EngDepAction) message.getAction();
+            } else {
+                throw new ApexException(message.getAction().getClass().getName()
+                        + "action on received message invalid, action must be of type \"EnDepAction\"");
+            }
+
+            // Handle each incoming message using the inevitable switch statement for the EngDep
+            // protocol
+            switch (enDepAction) {
+                case GET_ENGINE_SERVICE_INFO:
+                    final GetEngineServiceInfo engineServiceInformationMessage = (GetEngineServiceInfo) message;
+                    LOGGER.debug("getting engine service information for engine service " + apexService.getKey().getID()
+                            + " . . .");
+                    // Send a reply with the engine service information
+                    sendServiceInfoReply(webSocket, engineServiceInformationMessage, apexService.getKey(),
+                            apexService.getEngineKeys(), apexService.getApexModelKey());
+                    LOGGER.debug(
+                            "returned engine service information for engine service " + apexService.getKey().getID());
+                    break;
+
+                case UPDATE_MODEL:
+                    final UpdateModel updateModelMessage = (UpdateModel) message;
+                    LOGGER.debug("updating model in engine {} . . .", updateModelMessage.getTarget().getID());
+                    // Update the model
+                    apexService.updateModel(updateModelMessage.getTarget(), updateModelMessage.getMessageData(),
+                            updateModelMessage.isForceInstall());
+                    // Send a reply indicating the message action worked
+                    sendReply(webSocket, updateModelMessage, true,
+                            "updated model in engine " + updateModelMessage.getTarget().getID());
+                    LOGGER.debug("updated model in engine service {}", updateModelMessage.getTarget().getID());
+                    break;
+
+                case START_ENGINE:
+                    final StartEngine startEngineMessage = (StartEngine) message;
+                    LOGGER.debug("starting engine {} . . .", startEngineMessage.getTarget().getID());
+                    // Start the engine
+                    apexService.start(startEngineMessage.getTarget());
+                    // Send a reply indicating the message action worked
+                    sendReply(webSocket, startEngineMessage, true,
+                            "started engine " + startEngineMessage.getTarget().getID());
+                    LOGGER.debug("started engine {}", startEngineMessage.getTarget().getID());
+                    break;
+
+                case STOP_ENGINE:
+                    final StopEngine stopEngineMessage = (StopEngine) message;
+                    LOGGER.debug("stopping engine {} . . .", stopEngineMessage.getTarget().getID());
+                    // Stop the engine
+                    apexService.stop(stopEngineMessage.getTarget());
+                    // Send a reply indicating the message action worked
+                    sendReply(webSocket, stopEngineMessage, true,
+                            "stopped engine " + stopEngineMessage.getTarget().getID());
+                    LOGGER.debug("stopping engine {}", stopEngineMessage.getTarget().getID());
+                    break;
+
+                case START_PERIODIC_EVENTS:
+                    final StartPeriodicEvents startPeriodicEventsMessage = (StartPeriodicEvents) message;
+                    LOGGER.debug("starting periodic events on engine {} . . .",
+                            startPeriodicEventsMessage.getTarget().getID());
+                    // Start periodic events with the period specified in the message
+                    final Long period = Long.parseLong(startPeriodicEventsMessage.getMessageData());
+                    apexService.startPeriodicEvents(period);
+                    // Send a reply indicating the message action worked
+                    sendReply(webSocket, startPeriodicEventsMessage, true, "started periodic events on engine "
+                            + startPeriodicEventsMessage.getTarget().getID() + " with period " + period);
+                    LOGGER.debug("started periodic events on engine " + startPeriodicEventsMessage.getTarget().getID()
+                            + " with period " + period);
+                    break;
+
+                case STOP_PERIODIC_EVENTS:
+                    final StopPeriodicEvents stopPeriodicEventsMessage = (StopPeriodicEvents) message;
+                    LOGGER.debug("stopping periodic events on engine {} . . .",
+                            stopPeriodicEventsMessage.getTarget().getID());
+                    // Stop periodic events
+                    apexService.stopPeriodicEvents();
+                    // Send a reply indicating the message action worked
+                    sendReply(webSocket, stopPeriodicEventsMessage, true,
+                            "stopped periodic events on engine " + stopPeriodicEventsMessage.getTarget().getID());
+                    LOGGER.debug("stopped periodic events on engine " + stopPeriodicEventsMessage.getTarget().getID());
+                    break;
+
+                case GET_ENGINE_STATUS:
+                    final GetEngineStatus getEngineStatusMessage = (GetEngineStatus) message;
+                    LOGGER.debug("getting status for engine{} . . .", getEngineStatusMessage.getTarget().getID());
+                    // Send a reply with the engine status
+                    sendReply(webSocket, getEngineStatusMessage, true,
+                            apexService.getStatus(getEngineStatusMessage.getTarget()));
+                    LOGGER.debug("returned status for engine {}", getEngineStatusMessage.getTarget().getID());
+                    break;
+
+                case GET_ENGINE_INFO:
+                    final GetEngineInfo getEngineInfo = (GetEngineInfo) message;
+                    LOGGER.debug("getting runtime information for engine {} . . .", getEngineInfo.getTarget().getID());
+                    // Send a reply with the engine runtime information
+                    sendReply(webSocket, getEngineInfo, true, apexService.getRuntimeInfo(getEngineInfo.getTarget()));
+                    LOGGER.debug("returned runtime information for engine {}", getEngineInfo.getTarget().getID());
+                    break;
+                case RESPONSE:
+                    throw new ApexException("RESPONSE action on received message not handled by engine");
+
+                default:
+                    break;
+            }
+        } catch (final ApexException e) {
+            LOGGER.warn("apex failed to execute message", e);
+            sendReply(webSocket, message, false, e.getCascadedMessage());
+        } catch (final Exception e) {
+            LOGGER.warn("system failure executing message", e);
+            sendReply(webSocket, message, false, e.getMessage());
+        }
+        LOGGER.exit();
+    }
+
+    /**
+     * Send the Response message to the client.
+     *
+     * @param client the client to which to send the response message
+     * @param requestMessage the message to which we are responding
+     * @param result the result indicating success or failure
+     * @param messageData the message data
+     */
+    private void sendReply(final WebSocket client, final Message requestMessage, final boolean result,
+            final String messageData) {
+        LOGGER.entry(result, messageData);
+
+        if (client == null || !client.isOpen()) {
+            LOGGER.debug("error sending reply {}, client has disconnected", requestMessage.getAction());
+            return;
+        }
+
+        LOGGER.debug("sending {} to web socket {}", requestMessage.getAction(),
+                client.getRemoteSocketAddress().toString());
+
+        final Response responseMessage = new Response(requestMessage.getTarget(), result, requestMessage);
+        responseMessage.setMessageData(messageData);
+
+        final MessageHolder<Message> messageHolder = new MessageHolder<>(MessagingUtils.getHost());
+        messageHolder.addMessage(responseMessage);
+        client.send(MessagingUtils.serializeObject(messageHolder));
+
+        LOGGER.exit();
+    }
+
+    /**
+     * Send the EngineServiceInfoResponse message to the client.
+     *
+     * @param client the client to which to send the response message
+     * @param requestMessage the message to which we are responding
+     * @param engineServiceKey The key of this engine service
+     * @param engineKeyCollection The keys of the engines in this engine service
+     * @param apexModelKey the apex model key
+     */
+    private void sendServiceInfoReply(final WebSocket client, final Message requestMessage,
+            final AxArtifactKey engineServiceKey, final Collection<AxArtifactKey> engineKeyCollection,
+            final AxArtifactKey apexModelKey) {
+        LOGGER.entry();
+        LOGGER.debug("sending {} to web socket {}", requestMessage.getAction(),
+                client.getRemoteSocketAddress().toString());
+
+        final EngineServiceInfoResponse responseMessage =
+                new EngineServiceInfoResponse(requestMessage.getTarget(), true, requestMessage);
+        responseMessage.setMessageData("engine service information");
+        responseMessage.setEngineServiceKey(engineServiceKey);
+        responseMessage.setEngineKeyArray(engineKeyCollection);
+        responseMessage.setApexModelKey(apexModelKey);
+
+        final MessageHolder<Message> messageHolder = new MessageHolder<>(MessagingUtils.getHost());
+        messageHolder.addMessage(responseMessage);
+        client.send(MessagingUtils.serializeObject(messageHolder));
+
+        LOGGER.exit();
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/engdep/EngDepMessagingService.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/engdep/EngDepMessagingService.java
new file mode 100644 (file)
index 0000000..86589ac
--- /dev/null
@@ -0,0 +1,107 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.engdep;
+
+import java.net.InetSocketAddress;
+
+import org.onap.policy.apex.service.engine.runtime.EngineService;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import org.onap.policy.apex.core.infrastructure.messaging.MessagingService;
+import org.onap.policy.apex.core.infrastructure.messaging.MessagingServiceFactory;
+import org.onap.policy.apex.core.infrastructure.messaging.util.MessagingUtils;
+import org.onap.policy.apex.core.protocols.Message;
+
+/**
+ * The Class EngDepMessagingService is used to encapsulate the server side of EngDep communication.
+ * This class allows users to create and start an EngDep server.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class EngDepMessagingService {
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(EngDepMessagingService.class);
+
+    // Messaging service is used to transmit and receive messages over a communication protocol
+    private static MessagingServiceFactory<Message> messageServiceFactory = new MessagingServiceFactory<>();
+    private final MessagingService<Message> messageService;
+
+    // The listener that is listening for messages coming in on the EngDep protocol from clients
+    private final EngDepMessageListener messageListener;
+
+    /**
+     * Instantiates a new EngDep messaging service. It creates the message service instance, a
+     * listener for incoming messages, and starts the message listener thread for handling incoming
+     * messages.
+     *
+     * @param service the Apex engine service that this EngDep service is running for
+     * @param port the port The port to use for EngDep communication
+     */
+    public EngDepMessagingService(final EngineService service, final int port) {
+        LOGGER.entry(service);
+
+        // Create the service and listener and add the listener.
+        messageService = messageServiceFactory.createServer(new InetSocketAddress(MessagingUtils.checkPort(port)));
+        messageListener = new EngDepMessageListener(service);
+        messageService.addMessageListener(messageListener);
+
+        // Start incoming message processing on the listener
+        messageListener.startProcessorThread();
+        LOGGER.exit();
+    }
+
+    /**
+     * Start the server, open the communication mechanism for connections.
+     */
+    public void start() {
+        LOGGER.info("engine<-->deployment messaging starting . . .");
+        messageService.startConnection();
+        LOGGER.info("engine<-->deployment messaging started");
+    }
+
+    /**
+     * Start the server, close the communication mechanism.
+     */
+    public void stop() {
+        LOGGER.info("engine<-->deployment messaging stopping . . .");
+        messageService.stopConnection();
+        messageListener.stopProcessorThreads();
+        LOGGER.info("engine<-->deployment messaging stopped");
+    }
+
+    /**
+     * Is the server started?.
+     *
+     * @return true, if checks if is started
+     */
+    public boolean isStarted() {
+        return messageService.isStarted();
+    }
+
+    /**
+     * Is the server stopped?.
+     *
+     * @return true, if checks if is stopped
+     */
+    public boolean isStopped() {
+        return !messageService.isStarted();
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/engdep/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/engdep/package-info.java
new file mode 100644 (file)
index 0000000..41f6444
--- /dev/null
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Gives access to the APEX EngDep protocol for APEX engine management at runtime over a Java API.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.engdep;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEvent.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEvent.java
new file mode 100644 (file)
index 0000000..552f949
--- /dev/null
@@ -0,0 +1,342 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The Class ApexEvent is an event class that external systems use to send events to and receive events from Apex engines. The event itself is a hash map of
+ * string keys and object values, used to pass data.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ApexEvent extends HashMap<String, Object> implements Serializable {
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexEvent.class);
+
+    private static final long serialVersionUID = -4451918242101961685L;
+
+    // Holds the next identifier for event execution.
+    private static AtomicLong nextExecutionID = new AtomicLong(0L);
+
+    /** The name of the Apex event, a mandatory field. All Apex events must have a name so that the event can be looked up in the Apex policy model. */
+    public static final String NAME_HEADER_FIELD = "name";
+
+    /**
+     * The version of the Apex event, an optional field. If a version is specified on an Apex event, the definition of that version of the event is taken from
+     * the Apex policy model. If no version is specified, the latest version of the event is used.
+     */
+    public static final String VERSION_HEADER_FIELD = "version";
+
+    /**
+     * The name space of the Apex event, an optional field. If a name space is specified on an Apex event it must match the name space on the event definition
+     * taken from the Apex policy model. If no name space is specified, the name space from the event definition in the Apex policy model is used.
+     */
+    public static final String NAMESPACE_HEADER_FIELD = "nameSpace";
+
+    /**
+     * The source of the Apex event, an optional field. It specifies where the Apex event has come from and its use is reserved for now. If no source is
+     * specified, the source from the event definition in the Apex policy model is used.
+     */
+    public static final String SOURCE_HEADER_FIELD = "source";
+
+    /**
+     * The target of the Apex event, an optional field. It specifies where the Apex event is going to and its use is reserved for now. If no target is
+     * specified, the target from the event definition in the Apex policy model is used.
+     */
+    public static final String TARGET_HEADER_FIELD = "target";
+
+    /**
+     * The exception message field of an Apex event is an exception message indicating that an event failed.
+     */
+    public static final String EXCEPTION_MESSAGE_HEADER_FIELD = "exceptionMessage";
+
+    /** The name of an Apex event must match this regular expression. */
+    public static final String NAME_REGEXP = "[A-Za-z0-9\\-_.]+";
+
+    /** The version of an Apex event must match this regular expression. */
+    public static final String VERSION_REGEXP = "[A-Za-z0-9.]+";
+
+    /** The name space of an Apex event must match this regular expression. */
+    public static final String NAMESPACE_REGEXP = "([a-zA_Z_][\\.\\w]*)";
+
+    /** The source of an Apex event must match this regular expression. */
+    public static final String SOURCE_REGEXP = "^$|[A-Za-z0-9\\.\\-_:]+";
+
+    /** The target of an Apex event must match this regular expression. */
+    public static final String TARGET_REGEXP = "^$|[A-Za-z0-9\\.\\-_:]+";
+
+    // The fields of the event
+    // @formatter:off
+    private final String name;
+    private final String version;
+    private final String nameSpace;
+    private final String source;
+    private final String target;
+    // @formatter:on
+
+    // An identifier for the current event execution. The default value here will always be unique in a single JVM
+    private long executionID = ApexEvent.getNextExecutionID();
+
+    // A string holding a message that indicates why processing of this event threw an exception
+    private String exceptionMessage;
+
+    /**
+     * Private utility to get the next candidate value for a Execution ID. This value will always be unique in a single JVM
+     * 
+     * @return the next candidate value for a Execution ID
+     */
+    private static synchronized long getNextExecutionID() {
+        return nextExecutionID.getAndIncrement();
+    }
+
+    /**
+     * Instantiates a new apex event.
+     *
+     * @param name the name of the event
+     * @param version the version of the event
+     * @param nameSpace the name space (java package) of the event
+     * @param source the source of the event
+     * @param target the target of the event
+     * @throws ApexEventException thrown on validation errors on event names and versions
+     */
+    public ApexEvent(final String name, final String version, final String nameSpace, final String source, final String target) throws ApexEventException {
+        // @formatter:off
+        this.name      = validateField("name",      name,      NAME_REGEXP);
+        this.version   = validateField("version",   version,   VERSION_REGEXP);
+        this.nameSpace = validateField("nameSpace", nameSpace, NAMESPACE_REGEXP);
+        this.source    = validateField("source",    source,    SOURCE_REGEXP);
+        this.target    = validateField("target",    target,    TARGET_REGEXP);
+        // @formatter:on
+    }
+
+    /**
+     * Check that a field of the event is valid.
+     *
+     * @param fieldName the name of the field to check
+     * @param fieldValue the value of the field to check
+     * @param fieldRegexp the regular expression to check the field against
+     * @return the validated field value
+     * @throws ApexEventException thrown if the field is invalid
+     */
+    private String validateField(final String fieldName, final String fieldValue, final String fieldRegexp) throws ApexEventException {
+        if (fieldValue.matches(fieldRegexp)) {
+            return fieldValue;
+        }
+        else {
+            LOGGER.warn("event \"" + name + ": field \"" + fieldName + "=" + fieldValue + "\"  is illegal. It doesn't match regex '" + fieldRegexp + "'");
+            throw new ApexEventException("event \"" + name + ": field \"" + fieldName + "=" + fieldValue + "\"  is illegal");
+        }
+    }
+
+    /**
+     * Check that the key of an event is valid.
+     *
+     * @param key the key
+     * @return the string
+     * @throws ApexEventException the apex event exception
+     */
+    private String validKey(final String key) throws ApexEventException {
+        if (key.matches(NAME_REGEXP)) {
+            return key;
+        }
+        else {
+            LOGGER.warn("event \"" + name + ": key \"" + key + "\" is illegal");
+            throw new ApexEventException("event \"" + name + ": key \"" + key + "\" is illegal");
+        }
+    }
+
+    /**
+     * Gets the name.
+     *
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Gets the version.
+     *
+     * @return the version
+     */
+    public String getVersion() {
+        return version;
+    }
+
+    /**
+     * Gets the name space.
+     *
+     * @return the name space
+     */
+    public String getNameSpace() {
+        return nameSpace;
+    }
+
+    /**
+     * Gets the source.
+     *
+     * @return the source
+     */
+    public String getSource() {
+        return source;
+    }
+
+    /**
+     * Gets the target.
+     *
+     * @return the target
+     */
+    public String getTarget() {
+        return target;
+    }
+
+    /**
+     * Gets the pass-thru executionID for this event.
+     *
+     * @return the executionID
+     */
+    public long getExecutionID() {
+        return executionID;
+    }
+
+    /**
+     * Sets the pass-thru executionID for this event. The default value for executionID will be be unique in the current JVM. For some applications/deployments
+     * this executionID may need to globally unique
+     *
+     * @param executionID the executionID
+     */
+    public void setExecutionID(final long executionID) {
+        this.executionID = executionID;
+    }
+
+    /**
+     * Gets the exception message explaining why processing of this event to fail.
+     *
+     * @return the exception message
+     */
+    public String getExceptionMessage() {
+        return exceptionMessage;
+    }
+
+    /**
+     * Sets the exception message explaining why processing of this event to fail.
+     *
+     * @param exceptionMessage the exception message
+     */
+    public void setExceptionMessage(final String exceptionMessage) {
+        this.exceptionMessage = exceptionMessage;
+    }
+
+    /*
+     * Map overrides from here
+     */
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.Map#put(java.lang.Object, java.lang.Object)
+     */
+    @Override
+    public Object put(final String key, final Object value) {
+        // Check if the key is valid
+        try {
+            return super.put(validKey(key), value);
+        }
+        catch (final ApexEventException e) {
+            return null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.Map#putAll(java.util.Map)
+     */
+    @Override
+    public void putAll(final Map<? extends String, ? extends Object> incomingMap) {
+        // Check the keys are valid
+        try {
+            for (final String key : incomingMap.keySet()) {
+                validKey(key);
+            }
+        }
+        catch (final ApexEventException e) {
+            // One of the keys is invalid
+            return;
+        }
+
+        // Go ahead and put everything
+        super.putAll(incomingMap);
+    }
+
+    /*
+     * Object overrides from here
+     */
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        final StringBuilder builder = new StringBuilder();
+        builder.append("name=");
+        builder.append(name);
+        builder.append(",version=");
+        builder.append(version);
+        builder.append(",nameSpace=");
+        builder.append(nameSpace);
+        builder.append(",source=");
+        builder.append(source);
+        builder.append(",target=");
+        builder.append(target);
+        builder.append(",executionID=");
+        builder.append(executionID);
+        builder.append(",exceptionMessage=");
+        builder.append(exceptionMessage);
+        builder.append(",");
+        builder.append("[");
+
+        boolean firstData = true;
+        for (final Map.Entry<String, Object> dataEntry : this.entrySet()) {
+            if (firstData) {
+                firstData = false;
+            }
+            else {
+                builder.append(',');
+            }
+
+            builder.append(dataEntry.getKey());
+            builder.append('=');
+            builder.append(dataEntry.getValue());
+        }
+
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventConsumer.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventConsumer.java
new file mode 100644 (file)
index 0000000..53f11dd
--- /dev/null
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+
+/**
+ * This interface is used by technology specific consumers and listeners that are are listening for
+ * or collecting events for input into Apex. Users specify the consumer technology to use in the
+ * Apex configuration and Apex uses a factory to start the appropriate consumer plugin that
+ * implements this interface for its input. The technology specific implementation details are
+ * hidden behind this interface.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public interface ApexEventConsumer {
+    /**
+     * Initialize the consumer.
+     *
+     * @param name a name for this consumer
+     * @param consumerParameters the parameters to initialize this consumer
+     * @param apexEventReceiver the apex event receiver that should be used to pass events received
+     *        by the consumer into Apex
+     * @throws ApexEventException container exception on errors initializing event handling
+     */
+    void init(String name, EventHandlerParameters consumerParameters, ApexEventReceiver apexEventReceiver)
+            throws ApexEventException;
+
+    /**
+     * Start the consumer, start input of events into Apex.
+     */
+    void start();
+
+    /**
+     * Get the peered reference object for this consumer.
+     * 
+     * @param peeredMode the peered mode for which to return the reference
+     * @return the peered reference object for this consumer
+     */
+    PeeredReference getPeeredReference(EventHandlerPeeredMode peeredMode);
+
+    /**
+     * Set the peered reference object for this consumer.
+     * 
+     * @param peeredMode the peered mode for which to return the reference
+     * @param peeredReference the peered reference object for this consumer
+     */
+    void setPeeredReference(EventHandlerPeeredMode peeredMode, PeeredReference peeredReference);
+
+    /**
+     * Get the name of this event consumer.
+     * 
+     * @return the event consumer name
+     */
+    String getName();
+
+    /**
+     * Stop the event consumer.
+     */
+    void stop();
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventConverter.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventConverter.java
new file mode 100644 (file)
index 0000000..11f005d
--- /dev/null
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import java.util.List;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+
+/**
+ * The Interface ApexEventConverter is used for applications that want to convert arbitrary event
+ * types to and from Apex events. Application implement this interface to convert their events to
+ * and from Apex events.The Apex service can then use this interface to transparently transfer
+ * events into and out of an Apex system.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public interface ApexEventConverter {
+
+    /**
+     * Convert an event of arbitrary type into an Apex event.
+     *
+     * @param name the name of the incoming event
+     * @param eventOfOtherType the event of some other type to convert
+     * @return the apex event
+     * @throws ApexException thrown on conversion errors
+     */
+    List<ApexEvent> toApexEvent(String name, Object eventOfOtherType) throws ApexException;
+
+    /**
+     * Convert an Apex event into an event of arbitrary type {@code OTHER_EVENT_TYPE}.
+     *
+     * @param apexEvent the apex event to convert
+     * @return the event converted into the other type
+     * @throws ApexException thrown on conversion errors
+     */
+    Object fromApexEvent(ApexEvent apexEvent) throws ApexException;
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventException.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventException.java
new file mode 100644 (file)
index 0000000..24f57d7
--- /dev/null
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+
+/**
+ * This class will be called if an error occurs in handling Apex events.
+ *
+ * @author eeilfn
+ */
+public class ApexEventException extends ApexException {
+    private static final long serialVersionUID = -4245694568321686450L;
+
+    /**
+     * Instantiates a new apex event exception.
+     *
+     * @param message the message
+     */
+    public ApexEventException(final String message) {
+        super(message);
+    }
+
+    /**
+     * Instantiates a new apex event exception.
+     *
+     * @param message the message
+     * @param e the e
+     */
+    public ApexEventException(final String message, final Exception e) {
+        super(message, e);
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventList.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventList.java
new file mode 100644 (file)
index 0000000..9fe03ef
--- /dev/null
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import java.util.ArrayList;
+
+/**
+ * The Class ApexEventList holds a list of APEX events.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ApexEventList extends ArrayList<ApexEvent> {
+    private static final long serialVersionUID = -8496211897512202896L;
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventProducer.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventProducer.java
new file mode 100644 (file)
index 0000000..414fbc9
--- /dev/null
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+
+/**
+ * This interface is used by technology specific producers and publishers that are handling events
+ * output by Apex. Users specify the producer technology to use in the Apex configuration and Apex
+ * uses a factory to start the appropriate producer plugin that implements this interface for its
+ * output. The technology specific implementation details are hidden behind this interface.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public interface ApexEventProducer {
+
+    /**
+     * Initialize the producer.
+     *
+     * @param name a name for this producer
+     * @param producerParameters the parameters to initialise this producer
+     * @throws ApexEventException exception on errors initializing an event producer
+     */
+    void init(String name, EventHandlerParameters producerParameters) throws ApexEventException;
+
+    /**
+     * Get the peered reference object for this producer.
+     * 
+     * @param peeredMode the peered mode for which to return the reference
+     * @return the peered reference object for this producer
+     */
+    PeeredReference getPeeredReference(EventHandlerPeeredMode peeredMode);
+
+    /**
+     * Set the peered reference object for this producer.
+     * 
+     * @param peeredMode the peered mode for which to return the reference
+     * @param peeredReference the peered reference object for this producer
+     */
+    void setPeeredReference(EventHandlerPeeredMode peeredMode, PeeredReference peeredReference);
+
+    /**
+     * Send an event to the producer.
+     *
+     * @param executionId the unique ID that produced this event
+     * @param eventName The name of the event
+     * @param event The converted event as an object
+     */
+    void sendEvent(long executionId, String eventName, Object event);
+
+    /**
+     * Get the name of this event producer.
+     * 
+     * @return the event producer name
+     */
+    String getName();
+
+    /**
+     * Stop the event producer.
+     */
+    void stop();
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventProtocolConverter.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventProtocolConverter.java
new file mode 100644 (file)
index 0000000..ec19e65
--- /dev/null
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters;
+
+/**
+ * The Interface ApexEventProtocolConverter extends ApexEventConverter to allow
+ * EventProtocolParameters conversion parameters to be passed to the converter.
+ *
+ * @author John Keeney (john.keeney@ericsson.com)
+ */
+public interface ApexEventProtocolConverter extends ApexEventConverter {
+
+    /**
+     * Initialise the converter instance with the parameters for the EventProtocol.
+     *
+     * @param parameters the parameters for the EventProtocol
+     */
+    void init(EventProtocolParameters parameters);
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventReceiver.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventReceiver.java
new file mode 100644 (file)
index 0000000..8d7e7ba
--- /dev/null
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+/**
+ * This interface is used by an Apex event consumer {@link ApexEventConsumer} consumer to pass a
+ * received event to Apex.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public interface ApexEventReceiver {
+    /**
+     * Receive an event from a consumer for processing.
+     *
+     * @param executionId the unique ID for execution of this event
+     * @param event the event to receive
+     * @throws ApexEventException on exceptions receiving an event into Apex
+     */
+    void receiveEvent(long executionId, Object event) throws ApexEventException;
+
+    /**
+     * Receive an event from a consumer for processing.
+     *
+     * @param event the event to receive
+     * @throws ApexEventException on exceptions receiving an event into Apex
+     */
+    void receiveEvent(Object event) throws ApexEventException;
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventRuntimeException.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexEventRuntimeException.java
new file mode 100644 (file)
index 0000000..1a624fa
--- /dev/null
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException;
+
+/**
+ * This exception will be called if a runtime error occurs in Apex event handling.
+ *
+ * @author Liam Fallon
+ */
+public class ApexEventRuntimeException extends ApexRuntimeException {
+    private static final long serialVersionUID = -8507246953751956974L;
+
+    /**
+     * Instantiates a new apex runtime event exception with a message.
+     *
+     * @param message the message
+     */
+    public ApexEventRuntimeException(final String message) {
+        super(message);
+    }
+
+    /**
+     * Instantiates a new apex runtime event exception with a message and a caused by exception.
+     *
+     * @param message the message
+     * @param e the exception that caused this exception to be thrown
+     */
+    public ApexEventRuntimeException(final String message, final Exception e) {
+        super(message, e);
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexPeriodicEventGenerator.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/ApexPeriodicEventGenerator.java
new file mode 100644 (file)
index 0000000..62663b9
--- /dev/null
@@ -0,0 +1,176 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.onap.policy.apex.service.engine.runtime.EngineServiceEventInterface;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This class is used to generate periodic events into an Apex engine service. It is used to trigger
+ * policies that perform housekeeping operations.
+ *
+ * @author eeilfn
+ */
+public class ApexPeriodicEventGenerator extends TimerTask {
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexPeriodicEventGenerator.class);
+
+    /** The name of the periodic event. */
+    public static final String PERIODIC_EVENT_NAME = "PERIODIC_EVENT";
+
+    /** The version of the periodic event. */
+    public static final String PERIODIC_EVENT_VERSION = "0.0.1";
+
+    /** The name space of the periodic event. */
+    public static final String PERIODIC_EVENT_NAMESPACE = "com.ericsson.apex.service.engine.event";
+
+    /** The source of the periodic event. */
+    public static final String PERIODIC_EVENT_SOURCE = "internal";
+
+    /** The target of the periodic event. */
+    public static final String PERIODIC_EVENT_TARGET = "internal";
+
+    /**
+     * The field name in the periodic event for the delay between occurrences of the periodic event.
+     */
+    public static final String PERIODIC_DELAY = "PERIODIC_DELAY";
+
+    /**
+     * The field name in the periodic event for the time at which the first periodic event will
+     * occur.
+     */
+    public static final String PERIODIC_FIRST_TIME = "PERIODIC_FIRST_TIME";
+
+    /**
+     * The field name in the periodic event for the time at which the last periodic event will
+     * occur.
+     */
+    public static final String PERIODIC_LAST_TIME = "PERIODIC_LAST_TIME";
+
+    /** The field name in the periodic event for the time at which the event was sent. */
+    public static final String PERIODIC_CURRENT_TIME = "PERIODIC_CURRENT_TIME";
+
+    /**
+     * The field name in the periodic event for the number of occurrences of this event that have
+     * been sent to date, this is a sequence number for the periodic event.
+     */
+    public static final String PERIODIC_EVENT_COUNT = "PERIODIC_EVENT_COUNT";
+
+    // The Java timer used to send periodic events
+    private Timer timer = null;
+
+    // The engine service interface we'll send periodic events to
+    private final EngineServiceEventInterface engineServiceEventInterface;
+
+    // Timing information
+    private long period = 0;
+    private long firstEventTime = 0;
+    private long lastEventTime = 0;
+    private long eventCount = 0;
+
+    /**
+     * Constructor, save a reference to the event stream handler.
+     *
+     * @param engineServiceEventInterface the engine service event interface on which to send
+     *        periodic events
+     * @param period The period in milliseconds between events
+     */
+    public ApexPeriodicEventGenerator(final EngineServiceEventInterface engineServiceEventInterface,
+            final long period) {
+        // Save the engine service reference and delay
+        this.engineServiceEventInterface = engineServiceEventInterface;
+        this.period = period;
+
+        timer = new Timer(ApexPeriodicEventGenerator.class.getSimpleName(), true);
+        timer.schedule(this, period, period);
+    }
+
+    /**
+     * Output the metrics for stream loading.
+     */
+    @Override
+    public void run() {
+        final Map<String, Object> periodicEventMap = new HashMap<>();
+
+        // Record the current event time
+        final long currentEventTime = System.currentTimeMillis();
+
+        // Check if this is the first periodic event
+        if (firstEventTime == 0) {
+            firstEventTime = currentEventTime;
+            lastEventTime = currentEventTime;
+        }
+
+        // Increment the event counter
+        eventCount++;
+
+        // Set the fields in the periodic event
+        periodicEventMap.put(PERIODIC_DELAY, period);
+        periodicEventMap.put(PERIODIC_FIRST_TIME, firstEventTime);
+        periodicEventMap.put(PERIODIC_LAST_TIME, lastEventTime);
+        periodicEventMap.put(PERIODIC_CURRENT_TIME, currentEventTime);
+        periodicEventMap.put(PERIODIC_EVENT_COUNT, eventCount);
+
+        // Send the periodic event
+        try {
+            final ApexEvent periodicEvent = new ApexEvent(PERIODIC_EVENT_NAME, PERIODIC_EVENT_VERSION,
+                    PERIODIC_EVENT_NAMESPACE, PERIODIC_EVENT_SOURCE, PERIODIC_EVENT_TARGET);
+            periodicEvent.putAll(periodicEventMap);
+            engineServiceEventInterface.sendEvent(periodicEvent);
+        } catch (final ApexEventException e) {
+            LOGGER.warn("could not send Apex periodic event " + PERIODIC_EVENT_NAME + ":" + PERIODIC_EVENT_VERSION, e);
+            return;
+        }
+
+        // Save the current time as the last time
+        lastEventTime = currentEventTime;
+    }
+
+    /**
+     * Cancel the timer.
+     *
+     * @return true, if cancel
+     */
+    @Override
+    public boolean cancel() {
+        // Cancel the timer
+        if (timer != null) {
+            timer.cancel();
+        }
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "ApexPeriodicEventGenerator [period=" + period + ", firstEventTime=" + firstEventTime
+                + ", lastEventTime=" + lastEventTime + ", eventCount=" + eventCount + "]";
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/PeeredReference.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/PeeredReference.java
new file mode 100644 (file)
index 0000000..9560a83
--- /dev/null
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+
+/**
+ * This class holds a reference to an event consumer and producer that have been peered.
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class PeeredReference {
+    // The consumer putting events into APEX
+    private final ApexEventConsumer peeredConsumer;
+
+    // The synchronous producer taking events out of APEX
+    private final ApexEventProducer peeredProducer;
+
+    /**
+     * Create a peered consumer/producer reference
+     * 
+     * @param peeredMode the peered mode for which to return the reference
+     * @param consumer the consumer that is receiving event
+     * @param producer the producer that is sending events
+     */
+    public PeeredReference(final EventHandlerPeeredMode peeredMode, final ApexEventConsumer consumer, final ApexEventProducer producer) {
+        this.peeredConsumer = consumer;
+        this.peeredProducer = producer;
+
+        // Set the peered reference on the producer and consumer
+        peeredConsumer.setPeeredReference(peeredMode, this);
+        peeredProducer.setPeeredReference(peeredMode, this);
+    }
+
+    /**
+     * Gets the synchronous consumer putting events into the cache.
+     *
+     * @return the source synchronous consumer
+     */
+    public ApexEventConsumer getPeeredConsumer() {
+        return peeredConsumer;
+    }
+
+    /**
+     * Gets the synchronous producer taking events from the cache.
+     *
+     * @return the synchronous producer that is taking events from the cache
+     */
+    public ApexEventProducer getPeeredProducer() {
+        return peeredProducer;
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/SynchronousEventCache.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/SynchronousEventCache.java
new file mode 100644 (file)
index 0000000..25f92d8
--- /dev/null
@@ -0,0 +1,294 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import java.util.AbstractMap.SimpleEntry;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This class holds a cache of the synchronous events sent into Apex and that have not yet been replied to. It runs a thread to time out events that have not
+ * been replied to in the specified timeout.
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class SynchronousEventCache extends PeeredReference implements Runnable {
+    // Get a reference to the logger
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(SynchronousEventCache.class);
+
+    // The default amount of time to wait for a synchronous event to be replied to is 1 second
+    private static final long DEFAULT_SYNCHRONOUS_EVENT_TIMEOUT = 1000;
+
+    // The timeout to wait between event polls in milliseconds and the time to wait for the thread to stop
+    private static final long OUTSTANDING_EVENT_POLL_TIMEOUT = 50;
+    private static final long CACHE_STOP_WAIT_INTERVAL = 10;
+
+    // The time in milliseconds to wait for the reply to a sent synchronous event
+    private long synchronousEventTimeout = DEFAULT_SYNCHRONOUS_EVENT_TIMEOUT;
+
+    // Map holding outstanding synchronous events
+    private final Map<Long, SimpleEntry<Long, Object>> toApexEventMap = new HashMap<Long, SimpleEntry<Long, Object>>();
+
+    // Map holding reply events
+    private final Map<Long, SimpleEntry<Long, Object>> fromApexEventMap = new HashMap<Long, SimpleEntry<Long, Object>>();
+
+    // The message listener thread and stopping flag
+    private final Thread synchronousEventCacheThread;
+    private boolean stopOrderedFlag = false;
+
+    /**
+     * Create a synchronous event cache that caches outstanding synchronous Apex events.
+     * 
+     * @param peeredMode the peered mode for which to return the reference
+     * @param consumer the consumer that is populating the cache
+     * @param producer the producer that is emptying the cache
+     * @param synchronousEventTimeout the time in milliseconds to wait for the reply to a sent synchronous event
+     */
+    public SynchronousEventCache(final EventHandlerPeeredMode peeredMode, final ApexEventConsumer consumer, final ApexEventProducer producer, final long synchronousEventTimeout) {
+               super(peeredMode, consumer, producer);
+
+        if (synchronousEventTimeout != 0) {
+            this.synchronousEventTimeout = synchronousEventTimeout;
+        }
+        else {
+            this.synchronousEventTimeout = DEFAULT_SYNCHRONOUS_EVENT_TIMEOUT;
+        }
+
+        // Start scanning the outstanding events
+        synchronousEventCacheThread = new Thread(this);
+        synchronousEventCacheThread.setDaemon(true);
+        synchronousEventCacheThread.start();
+    }
+
+    /**
+     * Gets the timeout value for synchronous events.
+     *
+     * @return the synchronous event timeout
+     */
+    public long getSynchronousEventTimeout() {
+        return synchronousEventTimeout;
+    }
+
+    /**
+     * Cache a synchronized event sent into Apex in the event cache.
+     *
+     * @param executionId the execution ID that was assigned to the event
+     * @param event the apex event
+     */
+    public void cacheSynchronizedEventToApex(final long executionId, final Object event) {
+        // Add the event to the map
+        synchronized (toApexEventMap) {
+            cacheSynchronizedEvent(toApexEventMap, executionId, event);
+        }
+    }
+
+    /**
+     * Remove the record of an event sent to Apex if it exists in the cache.
+     * 
+     * @param executionId the execution ID of the event
+     * @return The removed event
+     */
+    public Object removeCachedEventToApexIfExists(final long executionId) {
+        synchronized (toApexEventMap) {
+            return removeCachedEventIfExists(toApexEventMap, executionId);
+        }
+    }
+
+    /**
+     * Check if an event exists in the to apex cache.
+     * 
+     * @param executionId the execution ID of the event
+     * @return true if the event exists, false otherwise
+     */
+    public boolean existsEventToApex(final long executionId) {
+        synchronized (toApexEventMap) {
+            return toApexEventMap.containsKey(executionId);
+        }
+    }
+
+    /**
+     * Cache synchronized event received from Apex in the event cache.
+     *
+     * @param executionId the execution ID of the event
+     * @param event the apex event
+     */
+    public void cacheSynchronizedEventFromApex(final long executionId, final Object event) {
+        // Add the event to the map
+        synchronized (fromApexEventMap) {
+            cacheSynchronizedEvent(fromApexEventMap, executionId, event);
+        }
+    }
+
+    /**
+     * Remove the record of an event received from Apex if it exists in the cache.
+     * 
+     * @param executionId the execution ID of the event
+     * @return The removed event
+     */
+    public Object removeCachedEventFromApexIfExists(final long executionId) {
+        synchronized (fromApexEventMap) {
+            return removeCachedEventIfExists(fromApexEventMap, executionId);
+        }
+    }
+
+    /**
+     * Check if an event exists in the from apex cache.
+     * 
+     * @param executionId the execution ID of the event
+     * @return true if the event exists, false otherwise
+     */
+    public boolean existsEventFromApex(final long executionId) {
+        synchronized (fromApexEventMap) {
+            return fromApexEventMap.containsKey(executionId);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Runnable#run()
+     */
+    @Override
+    public void run() {
+        LOGGER.entry();
+
+        // Periodic scan of outstanding events
+        while (synchronousEventCacheThread.isAlive() && !stopOrderedFlag) {
+            ThreadUtilities.sleep(OUTSTANDING_EVENT_POLL_TIMEOUT);
+
+            // Check for timeouts on events
+            synchronized (toApexEventMap) {
+                timeoutEventsOnCache(toApexEventMap);
+            }
+            synchronized (fromApexEventMap) {
+                timeoutEventsOnCache(fromApexEventMap);
+            }
+        }
+
+        LOGGER.exit();
+    }
+
+    /**
+     * Stops the scanning thread and clears the cache.
+     */
+    public synchronized void stop() {
+        LOGGER.entry();
+        stopOrderedFlag = true;
+
+        while (synchronousEventCacheThread.isAlive()) {
+            ThreadUtilities.sleep(CACHE_STOP_WAIT_INTERVAL);
+        }
+
+        // Check if there are any unprocessed events
+        if (!toApexEventMap.isEmpty()) {
+            LOGGER.warn(toApexEventMap.size() + " synchronous events dropped due to system shutdown");
+        }
+
+        toApexEventMap.clear();
+        LOGGER.exit();
+    }
+
+    /**
+     * Cache a synchronized event sent in an event cache.
+     * @param eventCacheMap the map to cache the event on
+     * @param executionId the execution ID of the event
+     * @param event the event to cache
+     */
+    private void cacheSynchronizedEvent(final Map<Long, SimpleEntry<Long, Object>> eventCacheMap, final long executionId, final Object event) {
+        LOGGER.entry("Adding event with execution ID: " + executionId);
+
+        // Check if the event is already in the cache
+        if (eventCacheMap.containsKey(executionId)) {
+            // If there was no sent event then the event timed out or some unexpected event was received
+            final String errorMessage = "an event with ID " + executionId
+            + " already exists in the synchronous event cache, execution IDs must be unique in the system";
+            LOGGER.warn(errorMessage);
+            throw new ApexEventRuntimeException(errorMessage);
+        }
+
+        // Add the event to the map
+        eventCacheMap.put(executionId, new SimpleEntry<Long, Object>(System.currentTimeMillis(), event));
+
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("event has been cached:" + event);
+        }
+
+        LOGGER.exit("Added: " + executionId);
+    }
+
+    /**
+     * Remove the record of an event if it exists in the cache.
+     * 
+     * @param eventCacheMap the map to remove the event from
+     * @param executionId the execution ID of the event
+     * @return The removed event
+     */
+    private Object removeCachedEventIfExists(final Map<Long, SimpleEntry<Long, Object>> eventCacheMap, final long executionId) {
+        LOGGER.entry("Removing: " + executionId);
+
+        final SimpleEntry<Long, Object> removedEventEntry = eventCacheMap.remove(executionId);
+
+        if (removedEventEntry != null) {
+            LOGGER.exit("Removed: " + executionId);
+            return removedEventEntry.getValue();
+        }
+        else {
+            // The event may not be one of the events in our cache, so we just ignore removal failures
+            return null;
+        }
+    }
+
+    /**
+     * Time out events on an event cache map. Events that have a timeout longer than the configured timeout are timed out.
+     * @param eventCacheMap the event cache to operate on
+     */
+    private void timeoutEventsOnCache(final Map<Long, SimpleEntry<Long, Object>> eventCacheMap) {
+        // Use a set to keep track of the events that have timed out
+        final Set<Long> timedOutEventSet = new HashSet<>();
+
+        for (final Entry<Long, SimpleEntry<Long, Object>> cachedEventEntry : eventCacheMap.entrySet()) {
+            // The amount of time we are waiting for the event reply
+            final long eventWaitTime = System.currentTimeMillis() - cachedEventEntry.getValue().getKey();
+
+            // Have we a timeout?
+            if (eventWaitTime > synchronousEventTimeout) {
+                timedOutEventSet.add(cachedEventEntry.getKey());
+            }
+        }
+
+        // Remove timed out events from the map
+        for (final long timedoutEventExecutionID : timedOutEventSet) {
+            // Remove the map entry and issue a warning
+            final SimpleEntry<Long, Object> timedOutEventEntry = eventCacheMap.remove(timedoutEventExecutionID);
+
+            LOGGER.warn("synchronous event timed out, reply not received in " + synchronousEventTimeout + " milliseconds on event "
+                    + timedOutEventEntry.getValue());
+        }
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/EventConsumerFactory.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/EventConsumerFactory.java
new file mode 100644 (file)
index 0000000..8f54c04
--- /dev/null
@@ -0,0 +1,83 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl;
+
+import org.onap.policy.apex.service.engine.event.ApexEventConsumer;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This factory class creates event consumers of various technology types for Apex engines.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class EventConsumerFactory {
+    // The logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(EventConsumerFactory.class);
+
+    /**
+     * Empty constructor with no generic overloading.
+     */
+    public EventConsumerFactory() {}
+
+    /**
+     * Create an event consumer of the required type for the specified consumer technology.
+     *
+     * @param name the name of the consumer
+     * @param consumerParameters The parameters for the Apex engine, we use the technology type of
+     *        the required consumer
+     * @return the event consumer
+     * @throws ApexEventException on errors creating the Apex event consumer
+     */
+    public ApexEventConsumer createConsumer(final String name, final EventHandlerParameters consumerParameters)
+            throws ApexEventException {
+        // Get the carrier technology parameters
+        final CarrierTechnologyParameters technologyParameters = consumerParameters.getCarrierTechnologyParameters();
+
+        // Get the class for the event consumer using reflection
+        final String consumerPluginClass = technologyParameters.getEventConsumerPluginClass();
+        Object consumerPluginObject = null;
+        try {
+            consumerPluginObject = Class.forName(consumerPluginClass).newInstance();
+        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
+            final String errorMessage = "could not create an Apex event consumer for \"" + name
+                    + "\" for the carrier technology \"" + technologyParameters.getLabel()
+                    + "\", specified event consumer plugin class \"" + consumerPluginClass + "\" not found";
+            LOGGER.error(errorMessage, e);
+            throw new ApexEventException(errorMessage, e);
+        }
+
+        // Check the class is an event consumer
+        if (!(consumerPluginObject instanceof ApexEventConsumer)) {
+            final String errorMessage = "could not create an Apex event consumer \"" + name
+                    + "\" for the carrier technology \"" + technologyParameters.getLabel()
+                    + "\", specified event consumer plugin class \"" + consumerPluginClass
+                    + "\" is not an instance of \"" + ApexEventConsumer.class.getCanonicalName() + "\"";
+            LOGGER.error(errorMessage);
+            throw new ApexEventException(errorMessage);
+        }
+
+        return (ApexEventConsumer) consumerPluginObject;
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/EventProducerFactory.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/EventProducerFactory.java
new file mode 100644 (file)
index 0000000..9bbbad3
--- /dev/null
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl;
+
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.engine.event.ApexEventProducer;
+import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This factory class creates event producers for the defined technology type for Apex engines.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class EventProducerFactory {
+    // The logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(EventProducerFactory.class);
+
+    /**
+     * Empty constructor with no generic overloading.
+     */
+    public EventProducerFactory() {}
+
+    /**
+     * Create an event producer of the required type for the specified producer technology.
+     *
+     * @param name the name of the producer
+     * @param producerParameters The Apex parameters containing the configuration for the producer
+     * @return the event producer
+     * @throws ApexEventException on errors creating the Apex event producer
+     */
+    public ApexEventProducer createProducer(final String name, final EventHandlerParameters producerParameters)
+            throws ApexEventException {
+        // Get the carrier technology parameters
+        final CarrierTechnologyParameters technologyParameters = producerParameters.getCarrierTechnologyParameters();
+
+        // Get the class for the event producer using reflection
+        final String producerPluginClass = technologyParameters.getEventProducerPluginClass();
+        Object producerPluginObject = null;
+        try {
+            producerPluginObject = Class.forName(producerPluginClass).newInstance();
+        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
+            final String errorMessage = "could not create an Apex event producer for Producer \"" + name
+                    + "\" for the carrier technology \"" + technologyParameters.getLabel()
+                    + "\", specified event producer plugin class \"" + producerPluginClass + "\" not found";
+            LOGGER.error(errorMessage, e);
+            throw new ApexEventException(errorMessage, e);
+        }
+
+        // Check the class is an event producer
+        if (!(producerPluginObject instanceof ApexEventProducer)) {
+            final String errorMessage = "could not create an Apex event producer for Producer \"" + name
+                    + "\" for the carrier technology \"" + technologyParameters.getLabel()
+                    + "\", specified event producer plugin class \"" + producerPluginClass
+                    + "\" is not an instance of \"" + ApexEventProducer.class.getCanonicalName() + "\"";
+            LOGGER.error(errorMessage);
+            throw new ApexEventException(errorMessage);
+        }
+
+        return (ApexEventProducer) producerPluginObject;
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/EventProtocolFactory.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/EventProtocolFactory.java
new file mode 100644 (file)
index 0000000..85c5bf0
--- /dev/null
@@ -0,0 +1,76 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl;
+
+import org.onap.policy.apex.service.engine.event.ApexEventProtocolConverter;
+import org.onap.policy.apex.service.engine.event.ApexEventRuntimeException;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This factory class uses the Apex event protocol parameters to create and return an instance of
+ * the correct Apex event protocol converter plugin for the specified event protocol.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class EventProtocolFactory {
+    // The logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(EventProtocolFactory.class);
+
+    /**
+     * Create an event converter that converts between an
+     * {@link org.onap.policy.apex.service.engine.event.ApexEvent} and the specified event protocol.
+     *
+     * @param name the name of the event protocol
+     * @param eventProtocolParameters the event protocol parameters defining what to convert from
+     *        and to
+     * @return The event converter for converting events to and from Apex format
+     */
+    public ApexEventProtocolConverter createConverter(final String name,
+            final EventProtocolParameters eventProtocolParameters) {
+        // Get the class for the event protocol plugin using reflection
+        final String eventProtocolPluginClass = eventProtocolParameters.getEventProtocolPluginClass();
+        Object eventProtocolPluginObject = null;
+        try {
+            eventProtocolPluginObject = Class.forName(eventProtocolPluginClass).newInstance();
+        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
+            final String errorMessage = "could not create an Apex event protocol converter for \"" + name
+                    + "\" for the protocol \"" + eventProtocolParameters.getLabel()
+                    + "\", specified event protocol converter plugin class \"" + eventProtocolPluginClass
+                    + "\" not found";
+            LOGGER.error(errorMessage, e);
+            throw new ApexEventRuntimeException(errorMessage, e);
+        }
+
+        // Check the class is an event consumer
+        if (!(eventProtocolPluginObject instanceof ApexEventProtocolConverter)) {
+            final String errorMessage = "could not create an Apex event protocol converter for \"" + name
+                    + "\" for the protocol \"" + eventProtocolParameters.getLabel()
+                    + "\", specified event protocol converter plugin class \"" + eventProtocolPluginClass
+                    + "\" is not an instance of \"" + ApexEventProtocolConverter.class.getCanonicalName() + "\"";
+            LOGGER.error(errorMessage);
+            throw new ApexEventRuntimeException(errorMessage);
+        }
+        ((ApexEventProtocolConverter) eventProtocolPluginObject).init(eventProtocolParameters);
+        return (ApexEventProtocolConverter) eventProtocolPluginObject;
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/apexprotocolplugin/Apex2ApexEventConverter.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/apexprotocolplugin/Apex2ApexEventConverter.java
new file mode 100644 (file)
index 0000000..b73aeb5
--- /dev/null
@@ -0,0 +1,140 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.apexprotocolplugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onap.policy.apex.service.engine.event.ApexEvent;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.engine.event.ApexEventList;
+import org.onap.policy.apex.service.engine.event.ApexEventProtocolConverter;
+import org.onap.policy.apex.service.engine.event.ApexEventRuntimeException;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The Class Apex2ApexEventConverter passes through {@link ApexEvent} instances. It is used for
+ * transferring Apex events directly as POJOs between APEX producers and consumers.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class Apex2ApexEventConverter implements ApexEventProtocolConverter {
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(Apex2ApexEventConverter.class);
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.onap.policy.apex.service.engine.event.ApexEventProtocolConverter#init(org.onap.policy.
+     * apex. service.parameters.eventprotocol.EventProtocolParameters)
+     */
+    @Override
+    public void init(final EventProtocolParameters parameters) {
+        // Check and get the APEX parameters
+        if (!(parameters instanceof ApexEventProtocolParameters)) {
+            final String errorMessage = "specified consumer properties are not applicable to the APEX event protocol";
+            LOGGER.warn(errorMessage);
+            throw new ApexEventRuntimeException(errorMessage);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.event.ApexEventConverter#toApexEvent(java.lang.String,
+     * java.lang.Object)
+     */
+    @Override
+    public List<ApexEvent> toApexEvent(final String eventName, final Object eventObject) throws ApexEventException {
+        // Check the event eventObject
+        if (eventObject == null) {
+            LOGGER.warn("event processing failed, event is null");
+            throw new ApexEventException("event processing failed, event is null");
+        }
+
+        // The list of events we will return
+        final List<ApexEvent> eventList = new ArrayList<>();
+
+        try {
+            // Check if its a single APEX event
+            if (!(eventObject instanceof ApexEvent)) {
+                throw new ApexEventException("incoming event (" + eventObject + ") is not an ApexEvent");
+            }
+
+            final ApexEvent event = (ApexEvent) eventObject;
+
+            // Check whether we have any ApexEventList fields, if so this is an event of events and
+            // all fields should be of type ApexEventList
+            boolean foundEventListFields = false;
+            boolean foundOtherFields = false;
+            for (final Object fieldObject : event.values()) {
+                if (fieldObject instanceof ApexEventList) {
+                    foundEventListFields = true;
+
+                    // Add the events to the event list
+                    eventList.addAll((ApexEventList) fieldObject);
+                } else {
+                    foundOtherFields = true;
+                }
+            }
+
+            // If we found both event list fields and other fields we're in trouble
+            if (foundEventListFields && foundOtherFields) {
+                throw new ApexEventException("incoming event (" + eventObject
+                        + ") has both event list fields and other fields, it cannot be processed");
+            }
+
+            // Check if the incoming event just has other fields, if so it's just a regular event
+            // and we add it to the event list as the only event there
+            if (foundOtherFields) {
+                eventList.add(event);
+            }
+        } catch (final Exception e) {
+            final String errorString = "Failed to unmarshal APEX event: " + e.getMessage() + ", event=" + eventObject;
+            LOGGER.warn(errorString, e);
+            throw new ApexEventException(errorString, e);
+        }
+
+        // Return the list of events we have unmarshalled
+        return eventList;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.event.ApexEventConverter#fromApexEvent(org.onap.policy.
+     * apex.service.engine.event.ApexEvent)
+     */
+    @Override
+    public Object fromApexEvent(final ApexEvent apexEvent) throws ApexEventException {
+        // Check the Apex event
+        if (apexEvent == null) {
+            LOGGER.warn("event processing failed, Apex event is null");
+            throw new ApexEventException("event processing failed, Apex event is null");
+        }
+
+        return apexEvent;
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/apexprotocolplugin/ApexEventProtocolParameters.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/apexprotocolplugin/ApexEventProtocolParameters.java
new file mode 100644 (file)
index 0000000..10cd58e
--- /dev/null
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.apexprotocolplugin;
+
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters;
+
+/**
+ * Event protocol parameters for JSON as an event protocol, there are no user defined parameters.
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ApexEventProtocolParameters extends EventProtocolParameters {
+    /** The label of this event protocol. */
+    public static final String APEX_EVENT_PROTOCOL_LABEL = "APEX";
+
+    /**
+     * Constructor to create a JSON event protocol parameter instance and register the instance with
+     * the parameter service.
+     */
+    public ApexEventProtocolParameters() {
+        this(ApexEventProtocolParameters.class.getCanonicalName(), APEX_EVENT_PROTOCOL_LABEL);
+    }
+
+    /**
+     * Constructor to create an event protocol parameters instance with the name of a sub class of
+     * this class.
+     *
+     * @param parameterClassName the class name of a sub class of this class
+     * @param eventProtocolLabel the name of the event protocol for this plugin
+     */
+    public ApexEventProtocolParameters(final String parameterClassName, final String eventProtocolLabel) {
+        super(parameterClassName);
+
+        // Set the event protocol properties for the JSON event protocol
+        this.setLabel(eventProtocolLabel);
+
+        // Set the event protocol plugin class
+        this.setEventProtocolPluginClass(Apex2ApexEventConverter.class.getCanonicalName());
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/apexprotocolplugin/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/apexprotocolplugin/package-info.java
new file mode 100644 (file)
index 0000000..a3c7d0d
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Contains the implementation of the APEX event protocol converter plugin for events in Json
+ * format.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.event.impl.apexprotocolplugin;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/enevent/ApexEvent2EnEventConverter.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/enevent/ApexEvent2EnEventConverter.java
new file mode 100644 (file)
index 0000000..90a19ff
--- /dev/null
@@ -0,0 +1,143 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.enevent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onap.policy.apex.service.engine.event.ApexEvent;
+import org.onap.policy.apex.service.engine.event.ApexEventConverter;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.engine.event.ApexEventRuntimeException;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import org.onap.policy.apex.core.engine.engine.ApexEngine;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvents;
+
+/**
+ * The Class ApexEvent2EnEventConverter converts externally facing {@link ApexEvent} instances to
+ * and from instances of {@link EnEvent} that are used internally in the Apex engine core.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public final class ApexEvent2EnEventConverter implements ApexEventConverter {
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexEvent2EnEventConverter.class);
+
+    // The Apex engine with its event definitions
+    private final ApexEngine apexEngine;
+
+    /**
+     * Set up the event converter.
+     *
+     * @param apexEngine The engine to use to create events to be converted
+     */
+    public ApexEvent2EnEventConverter(final ApexEngine apexEngine) {
+        this.apexEngine = apexEngine;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.event.ApexEventConverter#toApexEvent(java.lang.String,
+     * java.lang.Object)
+     */
+    @Override
+    public List<ApexEvent> toApexEvent(final String eventName, final Object event) throws ApexException {
+        // Check the Engine event
+        if (event == null) {
+            LOGGER.warn("event processing failed, engine event is null");
+            throw new ApexEventException("event processing failed, engine event is null");
+        }
+
+        // Cast the event to an Engine event event, if our conversion is correctly configured, this
+        // cast should always work
+        EnEvent enEvent = null;
+        try {
+            enEvent = (EnEvent) event;
+        } catch (final Exception e) {
+            final String errorMessage = "error transferring event \"" + event + "\" to the Apex engine";
+            LOGGER.debug(errorMessage, e);
+            throw new ApexEventRuntimeException(errorMessage, e);
+        }
+
+        // Create the Apex event
+        final AxEvent axEvent = enEvent.getAxEvent();
+        final ApexEvent apexEvent = new ApexEvent(axEvent.getKey().getName(), axEvent.getKey().getVersion(),
+                axEvent.getNameSpace(), axEvent.getSource(), axEvent.getTarget());
+
+        // Copy the ExecutionID from the EnEvent into the ApexEvent
+        apexEvent.setExecutionID(enEvent.getExecutionID());
+
+        // Copy he exception message to the Apex event if it is set
+        if (enEvent.getExceptionMessage() != null) {
+            apexEvent.setExceptionMessage(enEvent.getExceptionMessage());
+        }
+
+        // Set the data on the apex event
+        apexEvent.putAll(enEvent);
+
+        // Return the event in a single element
+        final ArrayList<ApexEvent> eventList = new ArrayList<ApexEvent>();
+        eventList.add(apexEvent);
+        return eventList;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.event.ApexEventConverter#fromApexEvent(org.onap.policy.
+     * apex.service.engine.event.ApexEvent)
+     */
+    @Override
+    public EnEvent fromApexEvent(final ApexEvent apexEvent) throws ApexException {
+        // Check the Apex model
+        if (apexEngine == null) {
+            LOGGER.warn("event processing failed, apex engine is null");
+            throw new ApexEventException("event processing failed, apex engine is null");
+        }
+
+        // Get the event definition
+        final AxEvent eventDefinition = ModelService.getModel(AxEvents.class).get(apexEvent.getName());
+        if (eventDefinition == null) {
+            LOGGER.warn("event processing failed, event \"" + apexEvent.getName() + "\" not found in apex model");
+            throw new ApexEventException(
+                    "event processing failed, event \"" + apexEvent.getName() + "\" not found in apex model");
+        }
+
+        // Create the internal engine event
+        final EnEvent enEvent = apexEngine.createEvent(eventDefinition.getKey());
+
+        // Set the data on the engine event
+        enEvent.putAll(apexEvent);
+
+        // copy the ExecutionID from the ApexEvent into the EnEvent
+        enEvent.setExecutionID(apexEvent.getExecutionID());
+
+        return enEvent;
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/enevent/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/enevent/package-info.java
new file mode 100644 (file)
index 0000000..6bc6bc2
--- /dev/null
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Provides conversion between externally facing
+ * {@link org.onap.policy.apex.service.engine.event.ApexEvent} instances and internal
+ * {@link org.onap.policy.apex.core.engine.event.EnEvent} instances.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.event.impl.enevent;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/eventrequestor/EventRequestorCarrierTechnologyParameters.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/eventrequestor/EventRequestorCarrierTechnologyParameters.java
new file mode 100644 (file)
index 0000000..fb722ea
--- /dev/null
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.eventrequestor;
+
+import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters;
+
+/**
+ * This class holds the parameters that allows an output event to to be sent back into APEX as one
+ * or multiple input events, there are no user defined parameters.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class EventRequestorCarrierTechnologyParameters extends CarrierTechnologyParameters {
+    // @formatter:off
+    /** The label of this carrier technology. */
+    public static final String EVENT_REQUESTOR_CARRIER_TECHNOLOGY_LABEL = "EVENT_REQUESTOR";
+
+    /** The producer plugin class for the EVENT_REQUESTOR carrier technology. */
+    public static final String EVENT_REQUESTOR_EVENT_PRODUCER_PLUGIN_CLASS =
+            EventRequestorProducer.class.getCanonicalName();
+
+    /** The consumer plugin class for the EVENT_REQUESTOR carrier technology. */
+    public static final String EVENT_REQUESTOR_EVENT_CONSUMER_PLUGIN_CLASS =
+            EventRequestorConsumer.class.getCanonicalName();
+    // @formatter:on
+
+    /**
+     * Constructor to create an event requestor carrier technology parameters instance and register
+     * the instance with the parameter service.
+     */
+    public EventRequestorCarrierTechnologyParameters() {
+        super(EventRequestorCarrierTechnologyParameters.class.getCanonicalName());
+
+        // Set the carrier technology properties for the EVENT_REQUESTOR carrier technology
+        this.setLabel(EVENT_REQUESTOR_CARRIER_TECHNOLOGY_LABEL);
+        this.setEventProducerPluginClass(EVENT_REQUESTOR_EVENT_PRODUCER_PLUGIN_CLASS);
+        this.setEventConsumerPluginClass(EVENT_REQUESTOR_EVENT_CONSUMER_PLUGIN_CLASS);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.apps.uservice.parameters.ApexParameterValidator#validate()
+     */
+    @Override
+    public String validate() {
+        return "";
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/eventrequestor/EventRequestorConsumer.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/eventrequestor/EventRequestorConsumer.java
new file mode 100644 (file)
index 0000000..b472cc9
--- /dev/null
@@ -0,0 +1,218 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.eventrequestor;
+
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import org.onap.policy.apex.core.infrastructure.threading.ApplicationThreadFactory;
+import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities;
+import org.onap.policy.apex.service.engine.event.ApexEventConsumer;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.engine.event.ApexEventReceiver;
+import org.onap.policy.apex.service.engine.event.ApexEventRuntimeException;
+import org.onap.policy.apex.service.engine.event.PeeredReference;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class implements an Apex event consumer that receives events from its peered event requestor
+ * producer.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class EventRequestorConsumer implements ApexEventConsumer, Runnable {
+    // Get a reference to the logger
+    private static final Logger LOGGER = LoggerFactory.getLogger(EventRequestorConsumer.class);
+
+    // The amount of time to wait in milliseconds between checks that the consumer thread has
+    // stopped
+    private static final long EVENT_REQUESTOR_WAIT_SLEEP_TIME = 50;
+
+    // The event receiver that will receive events from this consumer
+    private ApexEventReceiver eventReceiver;
+
+    // The name for this consumer
+    private String name = null;
+
+    // The peer references for this event handler
+    private final Map<EventHandlerPeeredMode, PeeredReference> peerReferenceMap =
+            new EnumMap<>(EventHandlerPeeredMode.class);
+
+    // Temporary request holder for incoming event send requests
+    private final BlockingQueue<Object> incomingEventRequestQueue = new LinkedBlockingQueue<>();
+
+    // The consumer thread and stopping flag
+    private Thread consumerThread;
+    private boolean stopOrderedFlag = false;
+
+    // The number of events received to date
+    private int eventsReceived = 0;
+
+    @Override
+    public void init(final String consumerName, final EventHandlerParameters consumerParameters,
+            final ApexEventReceiver incomingEventReceiver) throws ApexEventException {
+        this.eventReceiver = incomingEventReceiver;
+        this.name = consumerName;
+
+        // Check and get the event requestor consumer properties
+        if (!(consumerParameters
+                .getCarrierTechnologyParameters() instanceof EventRequestorCarrierTechnologyParameters)) {
+            final String errorMessage =
+                    "specified consumer properties are not applicable to event Requestor consumer (" + this.name + ")";
+            LOGGER.warn(errorMessage);
+            throw new ApexEventException(errorMessage);
+        }
+
+        // Check if we are in peered mode
+        if (!consumerParameters.isPeeredMode(EventHandlerPeeredMode.REQUESTOR)) {
+            final String errorMessage = "event Requestor consumer (" + this.name
+                    + ") must run in peered requestor mode with a event Requestor producer";
+            LOGGER.warn(errorMessage);
+            throw new ApexEventException(errorMessage);
+        }
+
+    }
+
+    /**
+     * Receive an incoming event send request from the peered event Requestor producer and queue it
+     * 
+     * @param eventObject the incoming event to process
+     * @throws ApexEventRuntimeException on queueing errors
+     */
+    public void processEvent(final Object eventObject) {
+        // Push the event onto the queue for handling
+        try {
+            incomingEventRequestQueue.add(eventObject);
+        } catch (final Exception e) {
+            final String errorMessage =
+                    "could not queue request \"" + eventObject + "\" on event Requestor consumer (" + this.name + ")";
+            LOGGER.warn(errorMessage);
+            throw new ApexEventRuntimeException(errorMessage);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#start()
+     */
+    @Override
+    public void start() {
+        // Configure and start the event reception thread
+        final String threadName = this.getClass().getName() + ":" + this.name;
+        consumerThread = new ApplicationThreadFactory(threadName).newThread(this);
+        consumerThread.setDaemon(true);
+        consumerThread.start();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#getName()
+     */
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Get the number of events received to date
+     * 
+     * @return the number of events received
+     */
+    public int getEventsReceived() {
+        return eventsReceived;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#getPeeredReference(org.onap.
+     * policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode)
+     */
+    @Override
+    public PeeredReference getPeeredReference(final EventHandlerPeeredMode peeredMode) {
+        return peerReferenceMap.get(peeredMode);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#setPeeredReference(org.onap.
+     * policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode,
+     * org.onap.policy.apex.service.engine.event.PeeredReference)
+     */
+    @Override
+    public void setPeeredReference(final EventHandlerPeeredMode peeredMode, final PeeredReference peeredReference) {
+        peerReferenceMap.put(peeredMode, peeredReference);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Runnable#run()
+     */
+    @Override
+    public void run() {
+        // The endless loop that receives events using REST calls
+        while (consumerThread.isAlive() && !stopOrderedFlag) {
+            try {
+                // Take the next event from the queue
+                final Object eventObject =
+                        incomingEventRequestQueue.poll(EVENT_REQUESTOR_WAIT_SLEEP_TIME, TimeUnit.MILLISECONDS);
+                if (eventObject == null) {
+                    // Poll timed out, wait again
+                    continue;
+                }
+
+                // Send the event into Apex
+                eventReceiver.receiveEvent(eventObject);
+
+                eventsReceived++;
+            } catch (final InterruptedException e) {
+                LOGGER.debug("Thread interrupted, Reason {}", e.getMessage());
+                Thread.currentThread().interrupt();
+            } catch (final Exception e) {
+                LOGGER.warn("error receiving events on thread {}", consumerThread.getName(), e);
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.apps.uservice.producer.ApexEventConsumer#stop()
+     */
+    @Override
+    public void stop() {
+        stopOrderedFlag = true;
+
+        while (consumerThread.isAlive()) {
+            ThreadUtilities.sleep(EVENT_REQUESTOR_WAIT_SLEEP_TIME);
+        }
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/eventrequestor/EventRequestorProducer.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/eventrequestor/EventRequestorProducer.java
new file mode 100644 (file)
index 0000000..4a972f2
--- /dev/null
@@ -0,0 +1,178 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.eventrequestor;
+
+import java.util.EnumMap;
+import java.util.Map;
+
+import org.onap.policy.apex.service.engine.event.ApexEventConsumer;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.engine.event.ApexEventProducer;
+import org.onap.policy.apex.service.engine.event.ApexEventRuntimeException;
+import org.onap.policy.apex.service.engine.event.PeeredReference;
+import org.onap.policy.apex.service.engine.event.SynchronousEventCache;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Concrete implementation of an Apex event producer that sends one or more events to its peered
+ * event requestor consumer.
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * 
+ */
+public class EventRequestorProducer implements ApexEventProducer {
+    private static final Logger LOGGER = LoggerFactory.getLogger(EventRequestorProducer.class);
+
+    // The name for this producer
+    private String name = null;
+
+    // The peer references for this event handler
+    private final Map<EventHandlerPeeredMode, PeeredReference> peerReferenceMap =
+            new EnumMap<>(EventHandlerPeeredMode.class);
+
+    // The number of events sent
+    private int eventsSent = 0;
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#init(java.lang.String,
+     * org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters)
+     */
+    @Override
+    public void init(final String producerName, final EventHandlerParameters producerParameters)
+            throws ApexEventException {
+        this.name = producerName;
+
+        // Check and get the producer Properties
+        if (!(producerParameters
+                .getCarrierTechnologyParameters() instanceof EventRequestorCarrierTechnologyParameters)) {
+            final String errorMessage =
+                    "specified consumer properties are not applicable to event requestor producer (" + this.name + ")";
+            LOGGER.warn(errorMessage);
+            throw new ApexEventException(errorMessage);
+        }
+
+        // Check if we are in peered mode
+        if (!producerParameters.isPeeredMode(EventHandlerPeeredMode.REQUESTOR)) {
+            final String errorMessage = "Event Requestor producer (" + this.name
+                    + ") must run in peered requestor mode with a Event Requestor consumer";
+            LOGGER.warn(errorMessage);
+            throw new ApexEventException(errorMessage);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#getName()
+     */
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Get the number of events sent to date
+     * 
+     * @return the number of events received
+     */
+    public int getEventsSent() {
+        return eventsSent;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#getPeeredReference(org.onap.
+     * policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode)
+     */
+    @Override
+    public PeeredReference getPeeredReference(final EventHandlerPeeredMode peeredMode) {
+        return peerReferenceMap.get(peeredMode);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#setPeeredReference(org.onap.
+     * policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode,
+     * org.onap.policy.apex.service.engine.event.PeeredReference)
+     */
+    @Override
+    public void setPeeredReference(final EventHandlerPeeredMode peeredMode, final PeeredReference peeredReference) {
+        peerReferenceMap.put(peeredMode, peeredReference);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#sendEvent(long, java.lang.
+     * String, java.lang.Object)
+     */
+    @Override
+    public void sendEvent(final long executionId, final String eventName, final Object eventObject) {
+        // Check if this is a synchronized event, if so we have received a reply
+        final SynchronousEventCache synchronousEventCache =
+                (SynchronousEventCache) peerReferenceMap.get(EventHandlerPeeredMode.SYNCHRONOUS);
+        if (synchronousEventCache != null) {
+            synchronousEventCache.removeCachedEventToApexIfExists(executionId);
+        }
+
+        // Find the peered consumer for this producer
+        final PeeredReference peeredRequestorReference = peerReferenceMap.get(EventHandlerPeeredMode.REQUESTOR);
+        if (peeredRequestorReference != null) {
+            // Find the event Response Consumer that will handle this request
+            final ApexEventConsumer consumer = peeredRequestorReference.getPeeredConsumer();
+            if (!(consumer instanceof EventRequestorConsumer)) {
+                final String errorMessage = "send of event to event consumer \""
+                        + peeredRequestorReference.getPeeredConsumer() + "\" failed,"
+                        + " event response consumer is not an instance of EventRequestorConsumer\n" + eventObject;
+                LOGGER.warn(errorMessage);
+                throw new ApexEventRuntimeException(errorMessage);
+            }
+
+            // Use the consumer to handle this event
+            final EventRequestorConsumer eventRequstConsumer = (EventRequestorConsumer) consumer;
+            eventRequstConsumer.processEvent(eventObject);
+
+            eventsSent++;
+        } else {
+            // No peered consumer defined
+            final String errorMessage = "send of event failed, event response consumer is not defined\n" + eventObject;
+            LOGGER.warn(errorMessage);
+            throw new ApexEventRuntimeException(errorMessage);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#stop()
+     */
+    @Override
+    public void stop() {
+        // For event requestor, all the implementation is in the consumer
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/eventrequestor/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/eventrequestor/package-info.java
new file mode 100644 (file)
index 0000000..3b6da08
--- /dev/null
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Implements the Event Requestor carrier technology for multiple event input from an output event.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.event.impl.eventrequestor;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/FILECarrierTechnologyParameters.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/FILECarrierTechnologyParameters.java
new file mode 100644 (file)
index 0000000..f7f25cb
--- /dev/null
@@ -0,0 +1,208 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.filecarrierplugin;
+
+import org.onap.policy.apex.model.utilities.ResourceUtils;
+import org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer.ApexFileEventConsumer;
+import org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.producer.ApexFileEventProducer;
+import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters;
+
+/**
+ * This class holds the parameters that allows transport of events into and out of Apex using files
+ * and standard input and output.
+ *
+ * <p>
+ * The following parameters are defined:
+ * <ol>
+ * <li>fileName: The full path to the file from which to read events or to which to write events.
+ * <li>standardIO: If this flag is set to true, then standard input is used to read events in or
+ * standard output is used to write events and the fileName parameter is ignored if present
+ * <li>standardError: If this flag is set to true, then standard error is used to write events
+ * <li>streamingMode: If this flag is set to true, then streaming mode is set for reading events and
+ * event handling will wait on the input stream for events until the stream is closed. If streaming
+ * model is off, then event reading completes when the end of input is detected.
+ * <li>startDelay: The amount of milliseconds to wait at startup startup before processing the first
+ * event.
+ * </ol>
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class FILECarrierTechnologyParameters extends CarrierTechnologyParameters {
+    // @formatter:off
+    /** The label of this carrier technology. */
+    public static final String FILE_CARRIER_TECHNOLOGY_LABEL = "FILE";
+
+    /** The producer plugin class for the FILE carrier technology. */
+    public static final String FILE_EVENT_PRODUCER_PLUGIN_CLASS = ApexFileEventProducer.class.getCanonicalName();
+
+    /** The consumer plugin class for the FILE carrier technology. */
+    public static final String FILE_EVENT_CONSUMER_PLUGIN_CLASS = ApexFileEventConsumer.class.getCanonicalName();
+
+    private String fileName;
+    private boolean standardIO = false;
+    private boolean standardError = false;
+    private boolean streamingMode = false;
+    private long startDelay = 0;
+    // @formatter:on
+
+    /**
+     * Constructor to create a file carrier technology parameters instance and register the instance
+     * with the parameter service.
+     */
+    public FILECarrierTechnologyParameters() {
+        super(FILECarrierTechnologyParameters.class.getCanonicalName());
+
+        // Set the carrier technology properties for the FILE carrier technology
+        this.setLabel(FILE_CARRIER_TECHNOLOGY_LABEL);
+        this.setEventProducerPluginClass(FILE_EVENT_PRODUCER_PLUGIN_CLASS);
+        this.setEventConsumerPluginClass(FILE_EVENT_CONSUMER_PLUGIN_CLASS);
+    }
+
+    /**
+     * Gets the file name from which to read or to which to write events.
+     *
+     * @return the file name from which to read or to which to write events
+     */
+    public String getFileName() {
+        return ResourceUtils.getFilePath4Resource(fileName);
+    }
+
+    /**
+     * Checks if is standard IO should be used for input or output.
+     *
+     * @return true, if standard IO should be used for input or output
+     */
+    public boolean isStandardIO() {
+        return standardIO;
+    }
+
+    /**
+     * Checks if is standard error should be used for output.
+     *
+     * @return true, if standard error should be used for output
+     */
+    public boolean isStandardError() {
+        return standardError;
+    }
+
+    /**
+     * Checks if is streaming mode is on.
+     *
+     * @return true, if streaming mode is on
+     */
+    public boolean isStreamingMode() {
+        return streamingMode;
+    }
+
+    /**
+     * Sets the file name from which to read or to which to write events.
+     *
+     * @param fileName the file name from which to read or to which to write events
+     */
+    public void setFileName(final String fileName) {
+        this.fileName = fileName;
+    }
+
+    /**
+     * Sets if standard IO should be used for event input or output.
+     *
+     * @param standardIO if standard IO should be used for event input or output
+     */
+    public void setStandardIO(final boolean standardIO) {
+        this.standardIO = standardIO;
+    }
+
+    /**
+     * Sets if standard error should be used for event output.
+     *
+     * @param standardError if standard error should be used for event output
+     */
+    public void setStandardError(final boolean standardError) {
+        this.standardError = standardError;
+    }
+
+    /**
+     * Sets streaming mode.
+     *
+     * @param streamingMode the streaming mode value
+     */
+    public void setStreamingMode(final boolean streamingMode) {
+        this.streamingMode = streamingMode;
+    }
+
+    /**
+     * Gets the delay in milliseconds before the plugin starts processing
+     * 
+     * @return the delay
+     */
+    public long getStartDelay() {
+        return startDelay;
+    }
+
+    /**
+     * Sets the delay in milliseconds before the plugin starts processing
+     * 
+     * @param startDelay the delay
+     */
+    public void setStartDelay(final long startDelay) {
+        this.startDelay = startDelay;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters#
+     * toString()
+     */
+    @Override
+    public String toString() {
+        return "FILECarrierTechnologyParameters [fileName=" + fileName + ", standardIO=" + standardIO
+                + ", standardError=" + standardError + ", streamingMode=" + streamingMode + ", startDelay=" + startDelay
+                + "]";
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.apps.uservice.parameters.ApexParameterValidator#validate()
+     */
+    @Override
+    public String validate() {
+        final StringBuilder errorMessageBuilder = new StringBuilder();
+
+        errorMessageBuilder.append(super.validate());
+
+        if (!standardIO && !standardError && (fileName == null || fileName.trim().length() == 0)) {
+            errorMessageBuilder.append(
+                    "  fileName not specified or is blank or null, it must be specified as a valid file location\n");
+        }
+
+        if (standardIO || standardError) {
+            streamingMode = true;
+        }
+
+        if (startDelay < 0) {
+            errorMessageBuilder.append("  startDelay must be zero or a positive number of milliseconds\n");
+        }
+
+        return errorMessageBuilder.toString();
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/ApexFileEventConsumer.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/ApexFileEventConsumer.java
new file mode 100644 (file)
index 0000000..7521c3a
--- /dev/null
@@ -0,0 +1,247 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.onap.policy.apex.core.infrastructure.threading.ApplicationThreadFactory;
+import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities;
+import org.onap.policy.apex.service.engine.event.ApexEventConsumer;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.engine.event.ApexEventReceiver;
+import org.onap.policy.apex.service.engine.event.PeeredReference;
+import org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.FILECarrierTechnologyParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Concrete implementation an Apex event consumer that reads events from a file. This consumer also
+ * implements ApexEventProducer and therefore can be used as a synchronous consumer.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ApexFileEventConsumer implements ApexEventConsumer, Runnable {
+
+    // Get a reference to the logger
+    private static final Logger LOGGER = LoggerFactory.getLogger(ApexFileEventConsumer.class);
+
+    // The input stream to read events from
+    private InputStream eventInputStream;
+
+    // The text block reader that will read text blocks from the contents of the file
+    private TextBlockReader textBlockReader;
+
+    // The event receiver that will receive asynchronous events from this consumer
+    private ApexEventReceiver eventReceiver = null;
+
+    // The consumer thread and stopping flag
+    private Thread consumerThread;
+
+    // The name for this consumer
+    private String consumerName = null;
+
+    // The specific carrier technology parameters for this consumer
+    private FILECarrierTechnologyParameters fileCarrierTechnologyParameters;
+
+    // The peer references for this event handler
+    private final Map<EventHandlerPeeredMode, PeeredReference> peerReferenceMap =
+            new EnumMap<>(EventHandlerPeeredMode.class);
+
+    // Holds the next identifier for event execution.
+    private static AtomicLong nextExecutionID = new AtomicLong(0L);
+
+    /**
+     * Private utility to get the next candidate value for a Execution ID. This value will always be
+     * unique in a single JVM
+     * 
+     * @return the next candidate value for a Execution ID
+     */
+    private static synchronized long getNextExecutionID() {
+        return nextExecutionID.getAndIncrement();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.apps.uservice.consumer.ApexEventConsumer#init(org.onap.policy.apex.apps.
+     * uservice.consumer.ApexEventReceiver)
+     */
+    @Override
+    public void init(final String name, final EventHandlerParameters consumerParameters,
+            final ApexEventReceiver incomingEventReceiver) throws ApexEventException {
+        this.eventReceiver = incomingEventReceiver;
+        this.consumerName = name;
+
+        // Get and check the Apex parameters from the parameter service
+        if (consumerParameters == null) {
+            final String errorMessage = "Consumer parameters for ApexFileConsumer \"" + consumerName + "\" is null";
+            LOGGER.warn(errorMessage);
+            throw new ApexEventException(errorMessage);
+        }
+
+        // Check and get the file Properties
+        if (!(consumerParameters.getCarrierTechnologyParameters() instanceof FILECarrierTechnologyParameters)) {
+            final String errorMessage = "specified consumer properties for ApexFileConsumer \"" + consumerName
+                    + "\" are not applicable to a File consumer";
+            LOGGER.warn(errorMessage);
+            throw new ApexEventException(errorMessage);
+        }
+        fileCarrierTechnologyParameters =
+                (FILECarrierTechnologyParameters) consumerParameters.getCarrierTechnologyParameters();
+
+        // Open the file producing events
+        try {
+            if (fileCarrierTechnologyParameters.isStandardIO()) {
+                eventInputStream = System.in;
+            } else {
+                eventInputStream = new FileInputStream(fileCarrierTechnologyParameters.getFileName());
+            }
+
+            // Get an event composer for our event source
+            textBlockReader = new TextBlockReaderFactory().getTaggedReader(eventInputStream,
+                    consumerParameters.getEventProtocolParameters());
+        } catch (final IOException e) {
+            final String errorMessage = "ApexFileConsumer \"" + consumerName + "\" failed to open file for reading: \""
+                    + fileCarrierTechnologyParameters.getFileName() + "\"";
+            LOGGER.warn(errorMessage, e);
+            throw new ApexEventException(errorMessage, e);
+        }
+
+        if (fileCarrierTechnologyParameters.getStartDelay() > 0) {
+            ThreadUtilities.sleep(fileCarrierTechnologyParameters.getStartDelay());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#getName()
+     */
+    @Override
+    public String getName() {
+        return consumerName;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#getPeeredReference(org.onap.
+     * policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode)
+     */
+    @Override
+    public PeeredReference getPeeredReference(final EventHandlerPeeredMode peeredMode) {
+        return peerReferenceMap.get(peeredMode);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#setPeeredReference(org.onap.
+     * policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode,
+     * org.onap.policy.apex.service.engine.event.PeeredReference)
+     */
+    @Override
+    public void setPeeredReference(final EventHandlerPeeredMode peeredMode, final PeeredReference peeredReference) {
+        peerReferenceMap.put(peeredMode, peeredReference);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#start()
+     */
+    @Override
+    public void start() {
+        // Configure and start the event reception thread
+        final String threadName = this.getClass().getName() + " : " + consumerName;
+        consumerThread = new ApplicationThreadFactory(threadName).newThread(this);
+        consumerThread.setDaemon(true);
+        consumerThread.start();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Runnable#run()
+     */
+    @Override
+    public void run() {
+        // Check that we have been initialized in async or sync mode
+        if (eventReceiver == null) {
+            LOGGER.warn("\"{}\" has not been initilaized for either asynchronous or synchronous event handling",
+                    consumerName);
+            return;
+        }
+
+        // Read the events from the file while there are still events in the file
+        try {
+            // Read all the text blocks
+            TextBlock textBlock;
+            do {
+                // Read the text block
+                textBlock = textBlockReader.readTextBlock();
+
+                // Process the event from the text block if there is one there
+                if (textBlock.getText() != null) {
+                    eventReceiver.receiveEvent(getNextExecutionID(), textBlock.getText());
+                }
+            } while (!textBlock.isEndOfText());
+        } catch (final Exception e) {
+            LOGGER.warn("\"" + consumerName + "\" failed to read event from file: \""
+                    + fileCarrierTechnologyParameters.getFileName() + "\"", e);
+        } finally {
+            try {
+                eventInputStream.close();
+            } catch (final IOException e) {
+                LOGGER.warn("ApexFileConsumer \"" + consumerName + "\" failed to close file: \""
+                        + fileCarrierTechnologyParameters.getFileName() + "\"", e);
+            }
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.apps.uservice.producer.ApexEventProducer#stop()
+     */
+    @Override
+    public void stop() {
+        try {
+            eventInputStream.close();
+        } catch (final IOException e) {
+            LOGGER.warn("ApexFileConsumer \"" + consumerName + "\" failed to close file for reading: \""
+                    + fileCarrierTechnologyParameters.getFileName() + "\"", e);
+        }
+
+        if (consumerThread.isAlive() && !consumerThread.isInterrupted()) {
+            consumerThread.interrupt();
+        }
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/CharacterDelimitedTextBlockReader.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/CharacterDelimitedTextBlockReader.java
new file mode 100644 (file)
index 0000000..b286f8a
--- /dev/null
@@ -0,0 +1,141 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolTextCharDelimitedParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The class CharacterDelimitedTextBlockReader reads the next block of text between two character
+ * tags from an input stream.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class CharacterDelimitedTextBlockReader implements TextBlockReader {
+    // The logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(CharacterDelimitedTextBlockReader.class);
+
+    // The character tags
+    private final char startTagChar;
+    private final char endTagChar;
+
+    // The input stream for text
+    private InputStream inputStream;
+
+    // Flag indicating we have seen EOF on the stream
+    private boolean eofOnInputStream = false;
+
+    /**
+     * Constructor, set the delimiters.
+     *
+     * @param startTagChar The start tag for text blocks
+     * @param endTagChar The end tag for text blocks
+     */
+    public CharacterDelimitedTextBlockReader(final char startTagChar, final char endTagChar) {
+        this.startTagChar = startTagChar;
+        this.endTagChar = endTagChar;
+    }
+
+    /**
+     * Constructor, set the delimiters from a character delimited event protocol parameter class.
+     *
+     * @param charDelimitedParameters the character delimited event protocol parameter class
+     */
+    public CharacterDelimitedTextBlockReader(final EventProtocolTextCharDelimitedParameters charDelimitedParameters) {
+        this.startTagChar = charDelimitedParameters.getStartChar();
+        this.endTagChar = charDelimitedParameters.getEndChar();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer.TextBlockReader#init(
+     * java.io.InputStream)
+     */
+    @Override
+    public void init(final InputStream incomingInputStream) {
+        this.inputStream = incomingInputStream;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer.TextBlockReader#
+     * readTextBlock()
+     */
+    @Override
+    public TextBlock readTextBlock() throws IOException {
+        // Check if there was a previous end of a text block with a non-empty text block returned
+        if (eofOnInputStream) {
+            return new TextBlock(eofOnInputStream, null);
+        }
+
+        // The initial nesting level of incoming text blocks is always zero
+        int nestingLevel = 0;
+
+        // Holder for the text block
+        final StringBuilder textBlockBuilder = new StringBuilder();
+
+        // Read the next text block
+        while (true) {
+            final char nextChar = (char) inputStream.read();
+
+            // Check for EOF
+            if (nextChar == (char) -1) {
+                eofOnInputStream = true;
+                break;
+            }
+
+            if (nextChar == startTagChar) {
+                nestingLevel++;
+            } else if (nestingLevel == 0 && !Character.isWhitespace(nextChar)) {
+                LOGGER.warn("invalid input on consumer: " + nextChar);
+                continue;
+            }
+
+            textBlockBuilder.append(nextChar);
+
+            // Check for end of the text block, we have come back to level 0
+            if (nextChar == endTagChar) {
+                if (nestingLevel > 0) {
+                    nestingLevel--;
+                }
+
+                if (nestingLevel == 0) {
+                    break;
+                }
+            }
+        }
+
+        // Condition the text block and return it
+        final String textBlock = textBlockBuilder.toString().trim();
+        if (textBlock.length() > 0) {
+            return new TextBlock(eofOnInputStream, textBlock);
+        } else {
+            return new TextBlock(eofOnInputStream, null);
+        }
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/HeaderDelimitedTextBlockReader.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/HeaderDelimitedTextBlockReader.java
new file mode 100644 (file)
index 0000000..e40bc75
--- /dev/null
@@ -0,0 +1,167 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Queue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.onap.policy.apex.core.infrastructure.threading.ApplicationThreadFactory;
+import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolTextTokenDelimitedParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The Class TextBlockReader reads the next block of text from an input stream.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class HeaderDelimitedTextBlockReader implements TextBlockReader, Runnable {
+    // The logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(HeaderDelimitedTextBlockReader.class);
+
+    // The amount of time to wait for input on the text block reader
+    private static final long TEXT_BLOCK_DELAY = 250;
+
+    // Tag for the start of a text block
+    private final String blockStartToken;
+
+    // The input stream for text
+    private InputStream inputStream;
+
+    // The lines of input read from the input stream
+    private final Queue<String> textLineQueue = new LinkedBlockingQueue<>();
+
+    // The thread used to read text from the input stream
+    private Thread textConsumputionThread;
+
+    // True while EOF has not been seen on input
+    private boolean eofOnInputStream = false;
+
+    /**
+     * Constructor, initialize the text block reader.
+     *
+     * @param blockStartToken the block start token for the start of a text block
+     */
+    public HeaderDelimitedTextBlockReader(final String blockStartToken) {
+        this.blockStartToken = blockStartToken;
+    }
+
+    /**
+     * Constructor, initialize the text block reader using token delimited event protocol
+     * parameters.
+     *
+     * @param tokenDelimitedParameters the token delimited event protocol parameters
+     */
+    public HeaderDelimitedTextBlockReader(final EventProtocolTextTokenDelimitedParameters tokenDelimitedParameters) {
+        this.blockStartToken = tokenDelimitedParameters.getDelimiterToken();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer.TextBlockReader#
+     * init( java.io.InputStream)
+     */
+    @Override
+    public void init(final InputStream incomingInputStream) {
+        this.inputStream = incomingInputStream;
+
+        // Configure and start the text reading thread
+        textConsumputionThread = new ApplicationThreadFactory(this.getClass().getName()).newThread(this);
+        textConsumputionThread.setDaemon(true);
+        textConsumputionThread.start();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer.TextBlockReader#
+     * readTextBlock()
+     */
+    @Override
+    public TextBlock readTextBlock() throws IOException {
+        // Holder for the current text block
+        final StringBuilder textBlockBuilder = new StringBuilder();
+
+        // Wait for the timeout period if there is no input
+        if (!eofOnInputStream && textLineQueue.size() == 0) {
+            ThreadUtilities.sleep(TEXT_BLOCK_DELAY);
+        }
+
+        // Scan the lines in the queue
+        while (textLineQueue.size() > 0) {
+            // Scroll down in the available lines looking for the start of the text block
+            if (textLineQueue.peek().startsWith(blockStartToken)) {
+                // Process the input line header
+                textBlockBuilder.append(textLineQueue.remove());
+                textBlockBuilder.append('\n');
+                break;
+            } else {
+                LOGGER.warn("invalid input on consumer: " + textLineQueue.remove());
+            }
+        }
+
+        // Get the rest of the text document
+        while (textLineQueue.size() > 0 && !textLineQueue.peek().startsWith(blockStartToken)) {
+            textBlockBuilder.append(textLineQueue.remove());
+            textBlockBuilder.append('\n');
+        }
+
+        // Condition the text block and return it
+        final String textBlock = textBlockBuilder.toString().trim();
+        final boolean endOfText = (eofOnInputStream && textLineQueue.size() == 0 ? true : false);
+
+        if (textBlock.length() > 0) {
+            return new TextBlock(endOfText, textBlock);
+        } else {
+            return new TextBlock(endOfText, null);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Runnable#run()
+     */
+    @Override
+    public void run() {
+        final BufferedReader textReader = new BufferedReader(new InputStreamReader(inputStream));
+
+        try {
+            // Read the input line by line until we see end of file on the stream
+            String line;
+            while ((line = textReader.readLine()) != null) {
+                textLineQueue.add(line);
+            }
+        } catch (final IOException e) {
+            LOGGER.warn("I/O exception on text input on consumer: ", e);
+        } finally {
+            eofOnInputStream = true;
+        }
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/TextBlock.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/TextBlock.java
new file mode 100644 (file)
index 0000000..526d9c3
--- /dev/null
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer;
+
+/**
+ * This class is a bean that holds a block of text read from an incoming text file.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class TextBlock {
+    private boolean endOfText = false;
+    private String text;
+
+    /**
+     * Constructor to initiate the text block.
+     *
+     * @param endOfText the end of text
+     * @param text the text
+     */
+    public TextBlock(final boolean endOfText, final String text) {
+        this.endOfText = endOfText;
+        this.text = text;
+    }
+
+    /**
+     * Checks if is end of text.
+     *
+     * @return true, if checks if is end of text
+     */
+    public boolean isEndOfText() {
+        return endOfText;
+    }
+
+    /**
+     * Sets whether end of text has been reached.
+     *
+     * @param endOfText the end of text flag value
+     */
+    public void setEndOfText(final boolean endOfText) {
+        this.endOfText = endOfText;
+    }
+
+    /**
+     * Gets the text of the text block.
+     *
+     * @return the text of the text block
+     */
+    public String getText() {
+        return text;
+    }
+
+    /**
+     * Sets the text of the text block.
+     *
+     * @param text the text of the text block
+     */
+    public void setText(final String text) {
+        this.text = text;
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/TextBlockReader.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/TextBlockReader.java
new file mode 100644 (file)
index 0000000..6277184
--- /dev/null
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Implementers of the interface TextBlockReader read the next block of text from an input stream.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public interface TextBlockReader {
+    /**
+     * Initialize the text block reader reader.
+     *
+     * @param inputStream The stream to read from
+     */
+    void init(InputStream inputStream);
+
+    /**
+     * Read a block of text between two delimiters.
+     *
+     * @return The text block
+     * @throws IOException On reading errors
+     */
+    TextBlock readTextBlock() throws IOException;
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/TextBlockReaderFactory.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/TextBlockReaderFactory.java
new file mode 100644 (file)
index 0000000..e482666
--- /dev/null
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer;
+
+import java.io.InputStream;
+
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolTextCharDelimitedParameters;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolTextTokenDelimitedParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This factory creates text block readers for breaking character streams into blocks of text.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class TextBlockReaderFactory {
+    // The logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(TextBlockReaderFactory.class);
+
+    /**
+     * Get a text block reader for the given event protocol.
+     *
+     * @param inputStream the input stream that will be used for reading
+     * @param eventProtocolParameters the parameters that have been specified for event protocols
+     * @return the tagged reader
+     * @throws ApexEventException On an unsupported event protocol
+     */
+    public TextBlockReader getTaggedReader(final InputStream inputStream,
+            final EventProtocolParameters eventProtocolParameters) throws ApexEventException {
+        // Check the type of event protocol we have
+        if (eventProtocolParameters instanceof EventProtocolTextCharDelimitedParameters) {
+            // We have character delimited textual input
+            final EventProtocolTextCharDelimitedParameters charDelimitedParameters =
+                    (EventProtocolTextCharDelimitedParameters) eventProtocolParameters;
+
+            // Create the text block reader
+            final TextBlockReader characterDelimitedTextBlockReader =
+                    new CharacterDelimitedTextBlockReader(charDelimitedParameters);
+            characterDelimitedTextBlockReader.init(inputStream);
+            return characterDelimitedTextBlockReader;
+        } else if (eventProtocolParameters instanceof EventProtocolTextTokenDelimitedParameters) {
+            // We have token delimited textual input
+            final EventProtocolTextTokenDelimitedParameters tokenDelimitedParameters =
+                    (EventProtocolTextTokenDelimitedParameters) eventProtocolParameters;
+
+            // Create the text block reader
+            final HeaderDelimitedTextBlockReader headerDelimitedTextBlockReader =
+                    new HeaderDelimitedTextBlockReader(tokenDelimitedParameters);
+            headerDelimitedTextBlockReader.init(inputStream);
+            return headerDelimitedTextBlockReader;
+        } else {
+            final String errorMessage =
+                    "could not create text block reader for a textual event protocol, the required type "
+                            + eventProtocolParameters.getLabel() + " is not supported";
+            LOGGER.error(errorMessage);
+            throw new ApexEventException(errorMessage);
+        }
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/consumer/package-info.java
new file mode 100644 (file)
index 0000000..05833ac
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Implements the FILE carrier technology consumer that sends events to APEX from files, standard IO
+ * or named pipes.
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/package-info.java
new file mode 100644 (file)
index 0000000..de0b1b5
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Implements the FILE carrier technology for event input and output to and from Apex using files,
+ * named pipes, and standard IO.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.event.impl.filecarrierplugin;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/producer/ApexFileEventProducer.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/producer/ApexFileEventProducer.java
new file mode 100644 (file)
index 0000000..d5f9ff1
--- /dev/null
@@ -0,0 +1,181 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.producer;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.EnumMap;
+import java.util.Map;
+
+import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.engine.event.ApexEventProducer;
+import org.onap.policy.apex.service.engine.event.ApexEventRuntimeException;
+import org.onap.policy.apex.service.engine.event.PeeredReference;
+import org.onap.policy.apex.service.engine.event.SynchronousEventCache;
+import org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.FILECarrierTechnologyParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Concrete implementation of an Apex event producer that sends events to a file.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ApexFileEventProducer implements ApexEventProducer {
+    // Get a reference to the logger
+    private static final Logger LOGGER = LoggerFactory.getLogger(ApexFileEventProducer.class);
+
+    // The name for this producer
+    private String producerName = null;
+
+    // The output stream to write events to
+    private PrintStream eventOutputStream;
+
+    // The peer references for this event handler
+    private final Map<EventHandlerPeeredMode, PeeredReference> peerReferenceMap =
+            new EnumMap<>(EventHandlerPeeredMode.class);
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.apps.uservice.producer.ApexEventProducer#init()
+     */
+    @Override
+    public void init(final String name, final EventHandlerParameters producerParameters) throws ApexEventException {
+        producerName = name;
+
+        // Get and check the Apex parameters from the parameter service
+        if (producerParameters == null) {
+            final String errorMessage = "Producer parameters for ApexFileProducer \"" + producerName + "\" is null";
+            LOGGER.warn(errorMessage);
+            throw new ApexEventException(errorMessage);
+        }
+
+        // Check and get the file Properties
+        if (!(producerParameters.getCarrierTechnologyParameters() instanceof FILECarrierTechnologyParameters)) {
+            final String errorMessage = "specified producer properties for ApexFileProducer \"" + producerName
+                    + "\" are not applicable to a FILE producer";
+            LOGGER.warn(errorMessage);
+            throw new ApexEventException(errorMessage);
+        }
+        final FILECarrierTechnologyParameters fileCarrierTechnologyParameters =
+                (FILECarrierTechnologyParameters) producerParameters.getCarrierTechnologyParameters();
+
+        // Now we create a writer for events
+        try {
+            if (fileCarrierTechnologyParameters.isStandardError()) {
+                eventOutputStream = System.err;
+            } else if (fileCarrierTechnologyParameters.isStandardIO()) {
+                eventOutputStream = System.out;
+            } else {
+                eventOutputStream =
+                        new PrintStream(new FileOutputStream(fileCarrierTechnologyParameters.getFileName()), true);
+            }
+        } catch (final IOException e) {
+            final String errorMessage = "ApexFileProducer \"" + producerName + "\" failed to open file for writing: \""
+                    + fileCarrierTechnologyParameters.getFileName() + "\"";
+            LOGGER.warn(errorMessage, e);
+            throw new ApexEventException(errorMessage, e);
+        }
+
+        if (fileCarrierTechnologyParameters.getStartDelay() > 0) {
+            ThreadUtilities.sleep(fileCarrierTechnologyParameters.getStartDelay());
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#getName()
+     */
+    @Override
+    public String getName() {
+        return producerName;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#getPeeredReference(org.onap.
+     * policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode)
+     */
+    @Override
+    public PeeredReference getPeeredReference(final EventHandlerPeeredMode peeredMode) {
+        return peerReferenceMap.get(peeredMode);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#setPeeredReference(org.onap.
+     * policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode,
+     * org.onap.policy.apex.service.engine.event.PeeredReference)
+     */
+    @Override
+    public void setPeeredReference(final EventHandlerPeeredMode peeredMode, final PeeredReference peeredReference) {
+        peerReferenceMap.put(peeredMode, peeredReference);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventProducer#sendEvent(long,
+     * java.lang.String, java.lang.Object)
+     */
+    @Override
+    public void sendEvent(final long executionId, final String eventName, final Object event) {
+        // Check if this is a synchronized event, if so we have received a reply
+        final SynchronousEventCache synchronousEventCache =
+                (SynchronousEventCache) peerReferenceMap.get(EventHandlerPeeredMode.SYNCHRONOUS);
+        if (synchronousEventCache != null) {
+            synchronousEventCache.removeCachedEventToApexIfExists(executionId);
+        }
+
+        // Cast the event to a string, if our conversion is correctly configured, this cast should
+        // always work
+        String stringEvent = null;
+        try {
+            stringEvent = (String) event;
+        } catch (final Exception e) {
+            final String errorMessage = "error in ApexFileProducer \"" + producerName + "\" while transferring event \""
+                    + event + "\" to the output stream";
+            LOGGER.debug(errorMessage, e);
+            throw new ApexEventRuntimeException(errorMessage, e);
+        }
+
+        eventOutputStream.println(stringEvent);
+        eventOutputStream.flush();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.apps.uservice.producer.ApexEventProducer#stop()
+     */
+    @Override
+    public void stop() {
+        eventOutputStream.close();
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/producer/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/filecarrierplugin/producer/package-info.java
new file mode 100644 (file)
index 0000000..f7d7cbf
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Implements the FILE carrier technology producer that outputs events from APEX to files, standard
+ * IO or named pipes.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.producer;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/jsonprotocolplugin/Apex2JSONEventConverter.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/jsonprotocolplugin/Apex2JSONEventConverter.java
new file mode 100644 (file)
index 0000000..3b21a29
--- /dev/null
@@ -0,0 +1,433 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.jsonprotocolplugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvents;
+import org.onap.policy.apex.model.eventmodel.concepts.AxField;
+import org.onap.policy.apex.service.engine.event.ApexEvent;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.engine.event.ApexEventProtocolConverter;
+import org.onap.policy.apex.service.engine.event.ApexEventRuntimeException;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+/**
+ * The Class Apex2JSONEventConverter converts {@link ApexEvent} instances to and from JSON string
+ * representations of Apex events.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class Apex2JSONEventConverter implements ApexEventProtocolConverter {
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(Apex2JSONEventConverter.class);
+
+    // The parameters for the JSON event protocol
+    private JSONEventProtocolParameters jsonPars;
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.onap.policy.apex.service.engine.event.ApexEventProtocolConverter#init(org.onap.policy.
+     * apex.service.parameters.eventprotocol.EventProtocolParameters)
+     */
+    @Override
+    public void init(final EventProtocolParameters parameters) {
+        // Check and get the JSON parameters
+        if (!(parameters instanceof JSONEventProtocolParameters)) {
+            final String errorMessage = "specified consumer properties are not applicable to the JSON event protocol";
+            LOGGER.warn(errorMessage);
+            throw new ApexEventRuntimeException(errorMessage);
+        }
+
+        jsonPars = (JSONEventProtocolParameters) parameters;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.event.ApexEventConverter#toApexEvent(java.lang.String,
+     * java.lang.Object)
+     */
+    @Override
+    public List<ApexEvent> toApexEvent(final String eventName, final Object eventObject) throws ApexEventException {
+        // Check the event eventObject
+        if (eventObject == null) {
+            LOGGER.warn("event processing failed, event is null");
+            throw new ApexEventException("event processing failed, event is null");
+        }
+
+        // Cast the event to a string, if our conversion is correctly configured, this cast should
+        // always work
+        String jsonEventString = null;
+        try {
+            jsonEventString = (String) eventObject;
+        } catch (final Exception e) {
+            final String errorMessage = "error converting event \"" + eventObject + "\" to a string";
+            LOGGER.debug(errorMessage, e);
+            throw new ApexEventRuntimeException(errorMessage, e);
+        }
+
+        // The list of events we will return
+        final List<ApexEvent> eventList = new ArrayList<ApexEvent>();
+
+        try {
+            // We may have a single JSON object with a single event or an array of JSON objects
+            final Object decodedJsonObject =
+                    new GsonBuilder().serializeNulls().create().fromJson(jsonEventString, Object.class);
+
+            // Check if we have a list of objects
+            if (decodedJsonObject instanceof List) {
+                // Check if it's a list of JSON objects or a list of strings
+                @SuppressWarnings("unchecked")
+                final List<Object> decodedJsonList = (List<Object>) decodedJsonObject;
+
+                // Decode each of the list elements in sequence
+                for (final Object jsonListObject : decodedJsonList) {
+                    if (jsonListObject instanceof String) {
+                        eventList.add(jsonStringApexEvent(eventName, (String) jsonListObject));
+                    } else if (jsonListObject instanceof JsonObject) {
+                        eventList.add(jsonObject2ApexEvent(eventName, (JsonObject) jsonListObject));
+                    } else {
+                        throw new ApexEventException("incoming event (" + jsonEventString
+                                + ") is a JSON object array containing an invalid object " + jsonListObject);
+                    }
+                }
+            } else {
+                eventList.add(jsonStringApexEvent(eventName, jsonEventString));
+            }
+        } catch (final Exception e) {
+            final String errorString =
+                    "Failed to unmarshal JSON event: " + e.getMessage() + ", event=" + jsonEventString;
+            LOGGER.warn(errorString, e);
+            throw new ApexEventException(errorString, e);
+        }
+
+        // Return the list of events we have unmarshalled
+        return eventList;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.event.ApexEventConverter#fromApexEvent(org.onap.policy.
+     * apex.service.engine.event.ApexEvent)
+     */
+    @Override
+    public Object fromApexEvent(final ApexEvent apexEvent) throws ApexEventException {
+        // Check the Apex event
+        if (apexEvent == null) {
+            LOGGER.warn("event processing failed, Apex event is null");
+            throw new ApexEventException("event processing failed, Apex event is null");
+        }
+
+        // Get the event definition for the event from the model service
+        final AxEvent eventDefinition =
+                ModelService.getModel(AxEvents.class).get(apexEvent.getName(), apexEvent.getVersion());
+
+        // Use a GSON Json object to marshal the Apex event to JSON
+        final Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();
+        final JsonObject jsonObject = new JsonObject();
+
+        jsonObject.addProperty(ApexEvent.NAME_HEADER_FIELD, apexEvent.getName());
+        jsonObject.addProperty(ApexEvent.VERSION_HEADER_FIELD, apexEvent.getVersion());
+        jsonObject.addProperty(ApexEvent.NAMESPACE_HEADER_FIELD, apexEvent.getNameSpace());
+        jsonObject.addProperty(ApexEvent.SOURCE_HEADER_FIELD, apexEvent.getSource());
+        jsonObject.addProperty(ApexEvent.TARGET_HEADER_FIELD, apexEvent.getTarget());
+
+        if (apexEvent.getExceptionMessage() != null) {
+            jsonObject.addProperty(ApexEvent.EXCEPTION_MESSAGE_HEADER_FIELD, apexEvent.getExceptionMessage());
+        }
+
+        for (final AxField eventField : eventDefinition.getFields()) {
+            final String fieldName = eventField.getKey().getLocalName();
+
+            if (!apexEvent.containsKey(fieldName)) {
+                if (!eventField.getOptional()) {
+                    final String errorMessage = "error parsing " + eventDefinition.getID() + " event to Json. "
+                            + "Field \"" + fieldName + "\" is missing, but is mandatory. Fields: " + apexEvent;
+                    LOGGER.debug(errorMessage);
+                    throw new ApexEventRuntimeException(errorMessage);
+                }
+                continue;
+            }
+
+            final Object fieldValue = apexEvent.get(fieldName);
+
+            // Get the schema helper
+            final SchemaHelper fieldSchemaHelper =
+                    new SchemaHelperFactory().createSchemaHelper(eventField.getKey(), eventField.getSchema());
+            jsonObject.add(fieldName, fieldSchemaHelper.marshal2JsonElement(fieldValue));
+        }
+
+        // Output JSON string in a pretty format
+        return gson.toJson(jsonObject);
+    }
+
+    /**
+     * This method converts a JSON object into an Apex event.
+     *
+     * @param eventName the name of the event
+     * @param jsonEventString the JSON string that holds the event
+     * @return the apex event that we have converted the JSON object into
+     * @throws ApexEventException thrown on unmarshaling exceptions
+     */
+    private ApexEvent jsonStringApexEvent(final String eventName, final String jsonEventString)
+            throws ApexEventException {
+        // Use GSON to read the event string
+        final JsonObject jsonObject =
+                new GsonBuilder().serializeNulls().create().fromJson(jsonEventString, JsonObject.class);
+
+        if (jsonObject == null || !jsonObject.isJsonObject()) {
+            throw new ApexEventException(
+                    "incoming event (" + jsonEventString + ") is not a JSON object or an JSON object array");
+        }
+
+        return jsonObject2ApexEvent(eventName, jsonObject);
+    }
+
+    /**
+     * This method converts a JSON object into an Apex event.
+     *
+     * @param eventName the name of the event
+     * @param jsonObject the JSON object that holds the event
+     * @return the apex event that we have converted the JSON object into
+     * @throws ApexEventException thrown on unmarshaling exceptions
+     */
+    private ApexEvent jsonObject2ApexEvent(final String eventName, final JsonObject jsonObject)
+            throws ApexEventException {
+        // Process the mandatory Apex header
+        final ApexEvent apexEvent = processApexEventHeader(eventName, jsonObject);
+
+        // Get the event definition for the event from the model service
+        final AxEvent eventDefinition =
+                ModelService.getModel(AxEvents.class).get(apexEvent.getName(), apexEvent.getVersion());
+
+        // Iterate over the input fields in the event
+        for (final AxField eventField : eventDefinition.getFields()) {
+            final String fieldName = eventField.getKey().getLocalName();
+            if (!hasJSONField(jsonObject, fieldName)) {
+                if (!eventField.getOptional()) {
+                    final String errorMessage = "error parsing " + eventDefinition.getID() + " event from Json. "
+                            + "Field \"" + fieldName + "\" is missing, but is mandatory.";
+                    LOGGER.debug(errorMessage);
+                    throw new ApexEventException(errorMessage);
+                }
+                continue;
+            }
+
+            final JsonElement fieldValue = getJSONField(jsonObject, fieldName, null, !eventField.getOptional());
+
+            if (fieldValue != null && !fieldValue.isJsonNull()) {
+                // Get the schema helper
+                final SchemaHelper fieldSchemaHelper =
+                        new SchemaHelperFactory().createSchemaHelper(eventField.getKey(), eventField.getSchema());
+                apexEvent.put(fieldName, fieldSchemaHelper.createNewInstance(fieldValue));
+            } else {
+                apexEvent.put(fieldName, null);
+            }
+        }
+        return apexEvent;
+
+    }
+
+    /**
+     * This method processes the event header of an Apex event.
+     *
+     * @param eventName the name of the event
+     * @param jsonObject the JSON object containing the JSON representation of the incoming event
+     * @return an apex event constructed using the header fields of the event
+     * @throws ApexEventRuntimeException the apex event runtime exception
+     * @throws ApexEventException on invalid events with missing header fields
+     */
+    private ApexEvent processApexEventHeader(final String eventName, final JsonObject jsonObject)
+            throws ApexEventRuntimeException, ApexEventException {
+        // Get the event header fields
+  // @formatter:off
+               String name      = getJSONStringField(jsonObject, ApexEvent.NAME_HEADER_FIELD,      jsonPars.getNameAlias(),      ApexEvent.NAME_REGEXP,      false);
+               String version   = getJSONStringField(jsonObject, ApexEvent.VERSION_HEADER_FIELD,   jsonPars.getVersionAlias(),   ApexEvent.VERSION_REGEXP,   false);
+               String namespace = getJSONStringField(jsonObject, ApexEvent.NAMESPACE_HEADER_FIELD, jsonPars.getNameSpaceAlias(), ApexEvent.NAMESPACE_REGEXP, false);
+               String source    = getJSONStringField(jsonObject, ApexEvent.SOURCE_HEADER_FIELD,    jsonPars.getSourceAlias(),    ApexEvent.SOURCE_REGEXP,    false);
+               String target    = getJSONStringField(jsonObject, ApexEvent.TARGET_HEADER_FIELD,    jsonPars.getTargetAlias(),    ApexEvent.TARGET_REGEXP,    false);
+               // @formatter:on
+
+        // Check if an event name was specified on the event parameters
+        if (eventName != null) {
+            if (name != null && !eventName.equals(name)) {
+                LOGGER.warn("The incoming event name \"" + name + "\" does not match the configured event name \""
+                        + eventName + "\", using configured event name");
+            }
+            name = eventName;
+        } else {
+            if (name == null) {
+                throw new ApexEventRuntimeException(
+                        "event received without mandatory parameter \"name\" on configuration or on event");
+            }
+        }
+
+        // Now, find the event definition in the model service. If version is null, the newest event
+        // definition in the model service is used
+        final AxEvent eventDefinition = ModelService.getModel(AxEvents.class).get(name, version);
+        if (eventDefinition == null) {
+            if (version == null) {
+                throw new ApexEventRuntimeException(
+                        "an event definition for an event named \"" + name + "\" not found in Apex model");
+            } else {
+                throw new ApexEventRuntimeException("an event definition for an event named \"" + name
+                        + "\" with version \"" + version + "\" not found in Apex model");
+            }
+        }
+
+        // Use the defined event version if no version is specified on the incoming fields
+        if (version == null) {
+            version = eventDefinition.getKey().getVersion();
+        }
+
+        // Check the name space is OK if it is defined, if not, use the name space from the model
+        if (namespace != null) {
+            if (!namespace.equals(eventDefinition.getNameSpace())) {
+                throw new ApexEventRuntimeException(
+                        "namespace \"" + namespace + "\" on event \"" + name + "\" does not match namespace \""
+                                + eventDefinition.getNameSpace() + "\" for that event in the Apex model");
+            }
+        } else {
+            namespace = eventDefinition.getNameSpace();
+        }
+
+        // For source, use the defined source only if the source is not found on the incoming event
+        if (source == null) {
+            source = eventDefinition.getSource();
+        }
+
+        // For target, use the defined source only if the source is not found on the incoming event
+        if (target == null) {
+            target = eventDefinition.getTarget();
+        }
+
+        return new ApexEvent(name, version, namespace, source, target);
+    }
+
+    /**
+     * This method gets an event string field from a JSON object.
+     *
+     * @param jsonObject the JSON object containing the JSON representation of the incoming event
+     * @param fieldName the field name to find in the event
+     * @param fieldAlias the alias for the field to find in the event, overrides the field name if
+     *        it is not null
+     * @param fieldRE the regular expression to check the field against for validity
+     * @param mandatory true if the field is mandatory
+     * @return the value of the field in the JSON object or null if the field is optional
+     * @throws ApexEventRuntimeException the apex event runtime exception
+     */
+    private String getJSONStringField(final JsonObject jsonObject, final String fieldName, final String fieldAlias,
+            final String fieldRE, final boolean mandatory) throws ApexEventRuntimeException {
+        // Get the JSON field for the string field
+        final JsonElement jsonField = getJSONField(jsonObject, fieldName, fieldAlias, mandatory);
+
+        // Null strings are allowed
+        if (jsonField == null || jsonField.isJsonNull()) {
+            return null;
+        }
+
+        // Check if this is a string field
+        String fieldValueString = null;
+        try {
+            fieldValueString = jsonField.getAsString();
+        } catch (final Exception e) {
+            // The element is not a string so throw an error
+            throw new ApexEventRuntimeException("field \"" + fieldName + "\" with type \""
+                    + jsonField.getClass().getCanonicalName() + "\" is not a string value");
+        }
+
+        // Is regular expression checking required
+        if (fieldRE == null) {
+            return fieldValueString;
+        }
+
+        // Check the event field against its regular expression
+        if (!fieldValueString.matches(fieldRE)) {
+            throw new ApexEventRuntimeException(
+                    "field \"" + fieldName + "\" with value \"" + fieldValueString + "\" is invalid");
+        }
+
+        return fieldValueString;
+    }
+
+    /**
+     * This method gets an event field from a JSON object.
+     *
+     * @param jsonObject the JSON object containing the JSON representation of the incoming event
+     * @param fieldName the field name to find in the event
+     * @param fieldAlias the alias for the field to find in the event, overrides the field name if
+     *        it is not null
+     * @param mandatory true if the field is mandatory
+     * @return the value of the field in the JSON object or null if the field is optional
+     * @throws ApexEventRuntimeException the apex event runtime exception
+     */
+    private JsonElement getJSONField(final JsonObject jsonObject, final String fieldName, final String fieldAlias,
+            final boolean mandatory) throws ApexEventRuntimeException {
+
+        // Check if we should use the alias for this field
+        String fieldToFind = fieldName;
+        if (fieldAlias != null) {
+            fieldToFind = fieldAlias;
+        }
+
+        // Get the event field
+        final JsonElement eventElement = jsonObject.get(fieldToFind);
+        if (eventElement == null) {
+            if (!mandatory) {
+                return null;
+            } else {
+                throw new ApexEventRuntimeException("mandatory field \"" + fieldToFind + "\" is missing");
+            }
+        }
+
+        return eventElement;
+    }
+
+    /**
+     * This method if a JSON object has a named field.
+     *
+     * @param jsonObject the JSON object containing the JSON representation of the incoming event
+     * @param fieldName the field name to find in the event
+     * @return true if the field is present
+     * @throws ApexEventRuntimeException the apex event runtime exception
+     */
+    private boolean hasJSONField(final JsonObject jsonObject, final String fieldName) throws ApexEventRuntimeException {
+        // check for the field
+        return jsonObject.has(fieldName);
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/jsonprotocolplugin/JSONEventProtocolParameters.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/jsonprotocolplugin/JSONEventProtocolParameters.java
new file mode 100644 (file)
index 0000000..b4a4055
--- /dev/null
@@ -0,0 +1,135 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event.impl.jsonprotocolplugin;
+
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolTextCharDelimitedParameters;
+
+/**
+ * Event protocol parameters for JSON as an event protocol.
+ *
+ * The parameters for this plugin are:
+ * <ol>
+ * <li>nameAlias: The field in a JSON event to use as an alias for the event name. This parameter is
+ * optional.
+ * <li>versionAlias: The field in a JSON event to use as an alias for the event version. This
+ * parameter is optional.
+ * <li>nameSpaceAlias: The field in a JSON event to use as an alias for the event name space. This
+ * parameter is optional.
+ * <li>sourceAlias: The field in a JSON event to use as an alias for the event source. This
+ * parameter is optional.
+ * <li>targetAlias: The field in a JSON event to use as an alias for the event target. This
+ * parameter is optional.
+ * </ol>
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class JSONEventProtocolParameters extends EventProtocolTextCharDelimitedParameters {
+    /** The label of this event protocol. */
+    public static final String JSON_EVENT_PROTOCOL_LABEL = "JSON";
+
+    // Constants for text block delimiters
+    private static final char JSON_TEXT_BLOCK_START_DELIMITER = '{';
+    private static final char JSON_TEXT_BLOCK_END_DELIMITER = '}';
+
+    // Aliases for Apex event header fields
+    // @formatter:off
+    private final String nameAlias      = null;
+    private final String versionAlias   = null;
+    private final String nameSpaceAlias = null;
+    private final String sourceAlias    = null;
+    private final String targetAlias    = null;
+    // @formatter:on
+
+    /**
+     * Constructor to create a JSON event protocol parameter instance and register the instance with
+     * the parameter service.
+     */
+    public JSONEventProtocolParameters() {
+        this(JSONEventProtocolParameters.class.getCanonicalName(), JSON_EVENT_PROTOCOL_LABEL);
+    }
+
+    /**
+     * Constructor to create an event protocol parameters instance with the name of a sub class of
+     * this class.
+     *
+     * @param parameterClassName the class name of a sub class of this class
+     * @param eventProtocolLabel the name of the event protocol for this plugin
+     */
+    public JSONEventProtocolParameters(final String parameterClassName, final String eventProtocolLabel) {
+        super(parameterClassName);
+
+        // Set the event protocol properties for the JSON event protocol
+        this.setLabel(eventProtocolLabel);
+
+        // Set the starting and ending delimiters for text blocks of JSON events
+        this.setStartChar(JSON_TEXT_BLOCK_START_DELIMITER);
+        this.setEndChar(JSON_TEXT_BLOCK_END_DELIMITER);
+
+        // Set the event protocol plugin class
+        this.setEventProtocolPluginClass(Apex2JSONEventConverter.class.getCanonicalName());
+    }
+
+    /**
+     * Gets the name alias.
+     *
+     * @return the name alias
+     */
+    public String getNameAlias() {
+        return nameAlias;
+    }
+
+    /**
+     * Gets the version alias.
+     *
+     * @return the version alias
+     */
+    public String getVersionAlias() {
+        return versionAlias;
+    }
+
+    /**
+     * Gets the name space alias.
+     *
+     * @return the name space alias
+     */
+    public String getNameSpaceAlias() {
+        return nameSpaceAlias;
+    }
+
+    /**
+     * Gets the source alias.
+     *
+     * @return the source alias
+     */
+    public String getSourceAlias() {
+        return sourceAlias;
+    }
+
+    /**
+     * Gets the target alias.
+     *
+     * @return the target alias
+     */
+    public String getTargetAlias() {
+        return targetAlias;
+    }
+
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/jsonprotocolplugin/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/jsonprotocolplugin/package-info.java
new file mode 100644 (file)
index 0000000..65f4831
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Contains the implementation of the APEX event protocol cinverter plugin for events in Json
+ * format.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.event.impl.jsonprotocolplugin;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/impl/package-info.java
new file mode 100644 (file)
index 0000000..ae2d587
--- /dev/null
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Contains implementations for conversion between externally facing
+ * {@link org.onap.policy.apex.service.engine.event.ApexEvent} instances and internal APEX engine
+ * {@link org.onap.policy.apex.core.engine.event.EnEvent} instances. It also contains the
+ * implementation of the default APEX File carrier technology plugin as well as the protocol plugins
+ * for XML and JSON event protocols.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.event.impl;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/event/package-info.java
new file mode 100644 (file)
index 0000000..7540413
--- /dev/null
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Provides a generic externally-facing {@link ApexEvent} class that can be sent into an APEX engine
+ * and processed by an APEX engine. It provides the producer {@link ApexEventProducer} producer and
+ * {@link ApexEventConsumer} consumer interfaces that APEX uses to send events to and receive events
+ * from other systems. It also provides the {@link ApexEventConverter} interface that can be
+ * implemented by plugins that wish to convert some external event format into the APEX event
+ * format. It also provides a periodic event generator that can be used to send periodic events into
+ * an APEX engine for triggering of policies to carry out housekeeping tasks.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.event;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivator.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivator.java
new file mode 100644 (file)
index 0000000..20af314
--- /dev/null
@@ -0,0 +1,193 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.main;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.utilities.TextFileUtils;
+import org.onap.policy.apex.service.engine.engdep.EngDepMessagingService;
+import org.onap.policy.apex.service.engine.runtime.EngineService;
+import org.onap.policy.apex.service.engine.runtime.impl.EngineServiceImpl;
+import org.onap.policy.apex.service.parameters.ApexParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This class wraps an Apex engine so that it can be activated as a complete service together with
+ * all its context, executor, and event plugins.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ApexActivator {
+    // The logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexActivator.class);
+
+    // The parameters of this Apex activator
+    private final ApexParameters apexParameters;
+
+    // Event unmarshalers are used to receive events asynchronously into Apex
+    private final Map<String, ApexEventUnmarshaller> unmarshallerMap = new LinkedHashMap<>();
+
+    // Event marshalers are used to send events asynchronously from Apex
+    private final Map<String, ApexEventMarshaller> marshallerMap = new LinkedHashMap<>();
+
+    // The engine service handler holds the references to the engine and its EngDep deployment
+    // interface. It also acts as a receiver for asynchronous
+    // and synchronous events from the engine.
+    private ApexEngineServiceHandler engineServiceHandler = null;
+
+    /**
+     * Instantiate the activator for the Apex engine as a complete service.
+     *
+     * @param parameters the apex parameters for the Apex service
+     */
+    public ApexActivator(final ApexParameters parameters) {
+        apexParameters = parameters;
+    }
+
+    /**
+     * Initialize the Apex engine as a complete service.
+     *
+     * @throws ApexActivatorException on errors in initializing the engine
+     */
+    public void initialize() throws ApexActivatorException {
+        LOGGER.debug("Apex engine starting as a service . . .");
+
+        try {
+            // Create engine with specified thread count
+            LOGGER.debug("starting apex engine service . . .");
+            final EngineService apexEngineService =
+                    EngineServiceImpl.create(apexParameters.getEngineServiceParameters());
+
+            // Instantiate and start the messaging service for Deployment
+            LOGGER.debug("starting apex deployment service . . .");
+            final EngDepMessagingService engDepService = new EngDepMessagingService(apexEngineService,
+                    apexParameters.getEngineServiceParameters().getDeploymentPort());
+            engDepService.start();
+
+            // Create the engine holder to hold the engine's references and act as an event receiver
+            engineServiceHandler = new ApexEngineServiceHandler(apexEngineService, engDepService);
+
+            // Check if a policy model file has been specified
+            if (apexParameters.getEngineServiceParameters().getPolicyModelFileName() != null) {
+                LOGGER.debug("deploying policy model in \""
+                        + apexParameters.getEngineServiceParameters().getPolicyModelFileName()
+                        + "\" to the apex engines . . .");
+
+                // Set the policy model in the engine
+                final String policyModelString = TextFileUtils
+                        .getTextFileAsString(apexParameters.getEngineServiceParameters().getPolicyModelFileName());
+                apexEngineService.updateModel(apexParameters.getEngineServiceParameters().getEngineKey(),
+                        policyModelString, true);
+                apexEngineService.startAll();
+            }
+
+            // Producer parameters specify what event marshalers to handle events leaving Apex are
+            // set up and how they are set up
+            for (final Entry<String, EventHandlerParameters> outputParameters : apexParameters
+                    .getEventOutputParameters().entrySet()) {
+                final ApexEventMarshaller marshaller = new ApexEventMarshaller(outputParameters.getKey(),
+                        apexParameters.getEngineServiceParameters(), outputParameters.getValue());
+                marshaller.init();
+                apexEngineService.registerActionListener(outputParameters.getKey(), marshaller);
+                marshallerMap.put(outputParameters.getKey(), marshaller);
+            }
+
+            // Consumer parameters specify what event unmarshalers to handle events coming into Apex
+            // are set up and how they are set up
+            for (final Entry<String, EventHandlerParameters> inputParameters : apexParameters.getEventInputParameters()
+                    .entrySet()) {
+                final ApexEventUnmarshaller unmarshaller = new ApexEventUnmarshaller(inputParameters.getKey(),
+                        apexParameters.getEngineServiceParameters(), inputParameters.getValue());
+                unmarshallerMap.put(inputParameters.getKey(), unmarshaller);
+                unmarshaller.init(engineServiceHandler);
+            }
+
+            // Set up unmarshaler/marshaler pairing for synchronized event handling. We only need to
+            // traverse the unmarshalers because the
+            // unmarshalers and marshalers are paired one to one uniquely so if we find a
+            // synchronized unmarshaler we'll also find its
+            // paired marshaler
+            for (final Entry<String, EventHandlerParameters> inputParameters : apexParameters.getEventInputParameters()
+                    .entrySet()) {
+                final ApexEventUnmarshaller unmarshaller = unmarshallerMap.get(inputParameters.getKey());
+
+                // Pair up peered unmarshalers and marshalers
+                for (final EventHandlerPeeredMode peeredMode : EventHandlerPeeredMode.values()) {
+                    // Check if the unmarshaler is synchronized with a marshaler
+                    if (inputParameters.getValue().isPeeredMode(peeredMode)) {
+                        // Find the unmarshaler and marshaler
+                        final ApexEventMarshaller peeredMarshaler =
+                                marshallerMap.get(inputParameters.getValue().getPeer(peeredMode));
+
+                        // Connect the unmarshaler and marshaler
+                        unmarshaller.connectMarshaler(peeredMode, peeredMarshaler);
+                    }
+                }
+                // Now let's get events flowing
+                unmarshaller.start();
+            }
+        } catch (final Exception e) {
+            LOGGER.debug("Apex engine failed to start as a service", e);
+            throw new ApexActivatorException("Apex engine failed to start as a service", e);
+        }
+
+        LOGGER.debug("Apex engine started as a service");
+    }
+
+    /**
+     * Terminate the Apex engine.
+     *
+     * @throws ApexException on termination errors
+     */
+    public void terminate() throws ApexException {
+        // Shut down all marshalers and unmarshalers
+        for (final ApexEventMarshaller marshaller : marshallerMap.values()) {
+            marshaller.stop();
+        }
+        marshallerMap.clear();
+
+        for (final ApexEventUnmarshaller unmarshaller : unmarshallerMap.values()) {
+            unmarshaller.stop();
+        }
+        unmarshallerMap.clear();
+
+        // Check if the engine service handler has been shut down already
+        if (engineServiceHandler != null) {
+            engineServiceHandler.terminate();
+            engineServiceHandler = null;
+        }
+    }
+
+    /**
+     * Get the parameters used by the adapter.
+     *
+     * @return the parameters of the adapter
+     */
+    public ApexParameters getApexParameters() {
+        return apexParameters;
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivatorException.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivatorException.java
new file mode 100644 (file)
index 0000000..371a3a8
--- /dev/null
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.main;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+
+/**
+ * This exception will be called if an error occurs when running Apex as a complete service.
+ *
+ * @author Liam Fallon
+ */
+public class ApexActivatorException extends ApexException {
+    private static final long serialVersionUID = -8507246953751956974L;
+
+    /**
+     * Instantiates a new apex activator exception with a message.
+     *
+     * @param message the message
+     */
+    public ApexActivatorException(final String message) {
+        super(message);
+    }
+
+    /**
+     * Instantiates a new apex activator exception with a message and a caused by exception.
+     *
+     * @param message the message
+     * @param e the exception that caused this exception to be thrown
+     */
+    public ApexActivatorException(final String message, final Exception e) {
+        super(message, e);
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivatorRuntimeException.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexActivatorRuntimeException.java
new file mode 100644 (file)
index 0000000..cf1842d
--- /dev/null
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.main;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException;
+
+/**
+ * This runtime exception will be called if a runtime error occurs when running Apex as a complete
+ * service.
+ *
+ * @author Liam Fallon
+ */
+public class ApexActivatorRuntimeException extends ApexRuntimeException {
+    private static final long serialVersionUID = -8507246953751956974L;
+
+    /**
+     * Instantiates a new apex activator exception with a message.
+     *
+     * @param message the message
+     */
+    public ApexActivatorRuntimeException(final String message) {
+        super(message);
+    }
+
+    /**
+     * Instantiates a new apex activator exception with a message and a caused by exception.
+     *
+     * @param message the message
+     * @param e the exception that caused this exception to be thrown
+     */
+    public ApexActivatorRuntimeException(final String message, final Exception e) {
+        super(message, e);
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexCommandLineArguments.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexCommandLineArguments.java
new file mode 100644 (file)
index 0000000..02dc248
--- /dev/null
@@ -0,0 +1,285 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.main;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.Arrays;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException;
+import org.onap.policy.apex.model.utilities.ResourceUtils;
+
+/**
+ * This class reads and handles command line parameters for the Apex main program.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ApexCommandLineArguments {
+    private static final int HELP_LINE_LENGTH = 120;
+
+    // Apache Commons CLI options
+    private final Options options;
+
+    // The command line options
+    private String modelFilePath = null;
+    private String configurationFilePath = null;
+
+    /**
+     * Construct the options for the CLI editor.
+     */
+    public ApexCommandLineArguments() {
+        //@formatter:off
+        options = new Options();
+        options.addOption(Option.builder("h")
+                .longOpt("help")
+                .desc("outputs the usage of this command")
+                .required(false)
+                .type(Boolean.class)
+                .build());
+        options.addOption(Option.builder("v")
+                .longOpt("version")
+                .desc("outputs the version of Apex")
+                .required(false)
+                .type(Boolean.class)
+                .build());
+        options.addOption(Option.builder("c")
+                .longOpt("config-file")
+                .desc("the full path to the configuration file to use, the configuration file must be a Json file containing the Apex configuration parameters")
+                .hasArg()
+                .argName("CONFIG_FILE")
+                .required(false)
+                .type(String.class)
+                .build());
+        options.addOption(Option.builder("m").longOpt("model-file")
+                .desc("the full path to the model file to use, if set it overrides the model file set in the configuration file").hasArg().argName("MODEL_FILE")
+                .required(false)
+                .type(String.class).build());
+        //@formatter:on
+    }
+
+    /**
+     * Construct the options for the CLI editor and parse in the given arguments.
+     *
+     * @param args The command line arguments
+     */
+    public ApexCommandLineArguments(final String[] args) {
+        // Set up the options with the default constructor
+        this();
+
+        // Parse the arguments
+        try {
+            parse(args);
+        } catch (final ApexException e) {
+            throw new ApexRuntimeException("parse error on Apex parameters");
+        }
+    }
+
+    /**
+     * Parse the command line options.
+     *
+     * @param args The command line arguments
+     * @return a string with a message for help and version, or null if there is no message
+     * @throws ApexException on command argument errors
+     */
+    public String parse(final String[] args) throws ApexException {
+        // Clear all our arguments
+        setConfigurationFilePath(null);
+        setModelFilePath(null);
+
+        CommandLine commandLine = null;
+        try {
+            commandLine = new DefaultParser().parse(options, args);
+        } catch (final ParseException e) {
+            throw new ApexException("invalid command line arguments specified : " + e.getMessage());
+        }
+
+        // Arguments left over after Commons CLI does its stuff
+        final String[] remainingArgs = commandLine.getArgs();
+
+        if (remainingArgs.length > 0 && commandLine.hasOption('c') || remainingArgs.length > 1) {
+            throw new ApexException("too many command line arguments specified : " + Arrays.toString(args));
+        }
+
+        if (remainingArgs.length == 1) {
+            configurationFilePath = remainingArgs[0];
+        }
+
+        if (commandLine.hasOption('h')) {
+            return help(ApexMain.class.getCanonicalName());
+        }
+
+        if (commandLine.hasOption('v')) {
+            return version();
+        }
+
+        if (commandLine.hasOption('c')) {
+            setConfigurationFilePath(commandLine.getOptionValue('c'));
+        }
+
+        if (commandLine.hasOption('m')) {
+            setModelFilePath(commandLine.getOptionValue('m'));
+        }
+
+        return null;
+    }
+
+    /**
+     * Validate the command line options.
+     *
+     * @throws ApexException on command argument validation errors
+     */
+    public void validate() throws ApexException {
+        validateReadableFile("Apex configuration", configurationFilePath);
+
+        if (checkSetModelFilePath()) {
+            validateReadableFile("Apex model", modelFilePath);
+        }
+    }
+
+    /**
+     * Print version information for Apex.
+     * 
+     * @return the version string
+     */
+    public String version() {
+        return ResourceUtils.getResourceAsString("version.txt");
+    }
+
+    /**
+     * Print help information for Apex.
+     *
+     * @param mainClassName the main class name
+     * @return the help string
+     */
+    public String help(final String mainClassName) {
+        final HelpFormatter helpFormatter = new HelpFormatter();
+        final StringWriter stringWriter = new StringWriter();
+        final PrintWriter stringPW = new PrintWriter(stringWriter);
+
+        helpFormatter.printHelp(stringPW, HELP_LINE_LENGTH, mainClassName + " [options...]", "options", options, 0, 0,
+                "");
+
+        return stringWriter.toString();
+    }
+
+    /**
+     * Gets the model file path.
+     *
+     * @return the model file path
+     */
+    public String getModelFilePath() {
+        return ResourceUtils.getFilePath4Resource(modelFilePath);
+    }
+
+    /**
+     * Sets the model file path.
+     *
+     * @param modelFilePath the model file path
+     */
+    public void setModelFilePath(final String modelFilePath) {
+        this.modelFilePath = modelFilePath;
+    }
+
+    /**
+     * Check set model file path.
+     *
+     * @return true, if check set model file path
+     */
+    public boolean checkSetModelFilePath() {
+        return modelFilePath != null && modelFilePath.length() > 0;
+    }
+
+    /**
+     * Gets the configuration file path.
+     *
+     * @return the configuration file path
+     */
+    public String getConfigurationFilePath() {
+        return configurationFilePath;
+    }
+
+    /**
+     * Gets the full expanded configuration file path.
+     *
+     * @return the configuration file path
+     */
+    public String getFullConfigurationFilePath() {
+        return ResourceUtils.getFilePath4Resource(getConfigurationFilePath());
+    }
+
+    /**
+     * Sets the configuration file path.
+     *
+     * @param configurationFilePath the configuration file path
+     */
+    public void setConfigurationFilePath(final String configurationFilePath) {
+        this.configurationFilePath = configurationFilePath;
+
+    }
+
+    /**
+     * Check set configuration file path.
+     *
+     * @return true, if check set configuration file path
+     */
+    public boolean checkSetConfigurationFilePath() {
+        return configurationFilePath != null && configurationFilePath.length() > 0;
+    }
+
+    /**
+     * Validate readable file.
+     *
+     * @param fileTag the file tag
+     * @param fileName the file name
+     * @throws ApexException the apex exception
+     */
+    private void validateReadableFile(final String fileTag, final String fileName) throws ApexException {
+        if (fileName == null || fileName.length() == 0) {
+            throw new ApexException(fileTag + " file was not specified as an argument");
+        }
+
+        // The file name can refer to a resource on the local file system or on the class path
+        final URL fileURL = ResourceUtils.getURL4Resource(fileName);
+        if (fileURL == null) {
+            throw new ApexException(fileTag + " file \"" + fileName + "\" does not exist");
+        }
+
+        final File theFile = new File(fileURL.getPath());
+        if (!theFile.exists()) {
+            throw new ApexException(fileTag + " file \"" + fileName + "\" does not exist");
+        }
+        if (!theFile.isFile()) {
+            throw new ApexException(fileTag + " file \"" + fileName + "\" is not a normal file");
+        }
+        if (!theFile.canRead()) {
+            throw new ApexException(fileTag + " file \"" + fileName + "\" is ureadable");
+        }
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexEngineServiceHandler.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexEngineServiceHandler.java
new file mode 100644 (file)
index 0000000..ad7af94
--- /dev/null
@@ -0,0 +1,88 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.main;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.service.engine.engdep.EngDepMessagingService;
+import org.onap.policy.apex.service.engine.event.ApexEvent;
+import org.onap.policy.apex.service.engine.runtime.EngineService;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The Class ApexEngineServiceHandler holds the reference to the Apex engine service and the EngDep
+ * service for that engine. It also acts as an event receiver for asynchronous and synchronous
+ * events.
+ */
+public class ApexEngineServiceHandler {
+    // The logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexEngineServiceHandler.class);
+
+    // The Apex engine service, the Apex engine itself
+    private final EngineService apexEngineService;
+
+    // The interface between the Apex engine and Apex policy deployment for the Apex engine
+    private final EngDepMessagingService engDepService;
+
+    /**
+     * Instantiates a new engine holder with its engine service and EngDep service.
+     *
+     * @param apexEngineService the apex engine service
+     * @param engDepService the EngDep service
+     */
+    ApexEngineServiceHandler(final EngineService apexEngineService, final EngDepMessagingService engDepService) {
+        this.apexEngineService = apexEngineService;
+        this.engDepService = engDepService;
+    }
+
+    /**
+     * This method forwards an event to the Apex service.
+     * 
+     * @param apexEvent The event to forward to Apex
+     */
+    public void forwardEvent(final ApexEvent apexEvent) {
+        try {
+            // Send the event to the engine runtime
+            apexEngineService.getEngineServiceEventInterface().sendEvent(apexEvent);
+        } catch (final Exception e) {
+            final String errorMessage = "error transferring event \"" + apexEvent.getName() + "\" to the Apex engine";
+            LOGGER.debug(errorMessage, e);
+            throw new ApexActivatorRuntimeException(errorMessage, e);
+        }
+    }
+
+    /**
+     * Terminate the Apex engine.
+     *
+     * @throws ApexException on termination errors
+     */
+    public void terminate() throws ApexException {
+        // Shut down engine management
+        if (engDepService != null) {
+            engDepService.stop();
+        }
+
+        // Shut down each engine instance
+        if (apexEngineService != null) {
+            apexEngineService.stop();
+        }
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexEventMarshaller.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexEventMarshaller.java
new file mode 100644 (file)
index 0000000..b4ba2ac
--- /dev/null
@@ -0,0 +1,232 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.main;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import org.onap.policy.apex.core.infrastructure.threading.ApplicationThreadFactory;
+import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities;
+import org.onap.policy.apex.service.engine.event.ApexEvent;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.engine.event.ApexEventProducer;
+import org.onap.policy.apex.service.engine.event.ApexEventProtocolConverter;
+import org.onap.policy.apex.service.engine.event.impl.EventProducerFactory;
+import org.onap.policy.apex.service.engine.event.impl.EventProtocolFactory;
+import org.onap.policy.apex.service.engine.runtime.ApexEventListener;
+import org.onap.policy.apex.service.parameters.engineservice.EngineServiceParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This event marshaler handles events coming out of Apex and sends them on, handles threading,
+ * event queuing, transformations and sending using the configured sending technology.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ApexEventMarshaller implements ApexEventListener, Runnable {
+    // Get a reference to the logger
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexEventMarshaller.class);
+
+    // Interval to wait between thread shutdown checks
+    private static final int MARSHALLER_SHUTDOWN_WAIT_INTERVAL = 10;
+
+    // The amount of time to wait between polls of the event queue in milliseconds
+    private static final long EVENT_QUEUE_POLL_INTERVAL = 20;
+
+    // The name of the marshaler
+    private final String name;
+
+    // The engine service and producer parameters
+    private final EngineServiceParameters engineServiceParameters;
+    private final EventHandlerParameters producerParameters;
+
+    // Apex event producer and event converter, all conversions are to and from string
+    // representation of events
+    private ApexEventProducer producer;
+    private ApexEventProtocolConverter converter;
+
+    // Temporary event holder for events coming out of Apex
+    private final BlockingQueue<ApexEvent> queue = new LinkedBlockingQueue<>();
+
+    // The marshaler thread and stopping flag
+    private Thread marshallerThread;
+    private boolean stopOrderedFlag = false;
+
+    /**
+     * Create the marshaler.
+     *
+     * @param name the name of the marshaler
+     * @param engineServiceParameters the engine service parameters for this Apex engine
+     * @param producerParameters the producer parameters for this specific marshaler
+     */
+    public ApexEventMarshaller(final String name, final EngineServiceParameters engineServiceParameters,
+            final EventHandlerParameters producerParameters) {
+        this.name = name;
+        this.engineServiceParameters = engineServiceParameters;
+        this.producerParameters = producerParameters;
+    }
+
+    /**
+     * Configure the marshaler by setting up the producer and event converter and initialize the
+     * thread for event sending.
+     *
+     * @throws ApexActivatorException on errors initializing the producer
+     * @throws ApexEventException on errors initializing event handling
+     */
+    public void init() throws ApexActivatorException, ApexEventException {
+        // Create the producer for sending events and the converter for transforming events
+        producer = new EventProducerFactory().createProducer(name, producerParameters);
+
+        // Initialize the producer
+        producer.init(this.name, this.producerParameters);
+
+        // Create the converter for transforming events
+        converter = new EventProtocolFactory().createConverter(name, producerParameters.getEventProtocolParameters());
+
+        // Configure and start the event sending thread
+        final String threadName =
+                engineServiceParameters.getEngineKey().getName() + ':' + this.getClass().getName() + ':' + this.name;
+        marshallerThread = new ApplicationThreadFactory(threadName).newThread(this);
+        marshallerThread.setDaemon(true);
+        marshallerThread.start();
+    }
+
+    /**
+     * Gets the name of the marshaler.
+     *
+     * @return the marshaler name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Gets the technology specific producer for this marshaler.
+     *
+     * @return the producer
+     */
+    public ApexEventProducer getProducer() {
+        return producer;
+    }
+
+    /**
+     * Gets the event protocol converter for this marshaler.
+     *
+     * @return the event protocol converter
+     */
+    public ApexEventProtocolConverter getConverter() {
+        return converter;
+    }
+
+    /**
+     * Callback method called on implementations of this interface when Apex emits an event.
+     *
+     * @param apexEvent the apex event emitted by Apex
+     */
+    @Override
+    public void onApexEvent(final ApexEvent apexEvent) {
+        // Check if we are filtering events on this marshaler, if so check the event name against
+        // the filter
+        if (producerParameters.isSetEventNameFilter()
+                && !apexEvent.getName().matches(producerParameters.getEventNameFilter())) {
+            if (LOGGER.isTraceEnabled()) {
+                LOGGER.trace("onMessage(): event {} not processed, filtered  out by filter", apexEvent,
+                        producerParameters.getEventNameFilter());
+            }
+
+            // Ignore this event
+            return;
+        }
+
+        // Push the event onto the queue for handling
+        try {
+            queue.put(apexEvent);
+        } catch (final InterruptedException e) {
+            LOGGER.warn("Failed to queue the event: " + apexEvent, e);
+        }
+    }
+
+    /**
+     * Run a thread that runs forever (well until system termination anyway) and listens for
+     * outgoing events on the queue.
+     */
+    @Override
+    public void run() {
+        // Run until interrupted
+        while (marshallerThread.isAlive() && !stopOrderedFlag) {
+            try {
+                // Take the next event from the queue
+                final ApexEvent apexEvent = queue.poll(EVENT_QUEUE_POLL_INTERVAL, TimeUnit.MILLISECONDS);
+                if (apexEvent == null) {
+                    continue;
+                }
+
+                // Process the next Apex event from the queue
+                final Object event = converter.fromApexEvent(apexEvent);
+
+                producer.sendEvent(apexEvent.getExecutionID(), apexEvent.getName(), event);
+
+                if (LOGGER.isTraceEnabled()) {
+                    LOGGER.trace("event sent : " + apexEvent.toString());
+                }
+            } catch (final InterruptedException e) {
+                LOGGER.debug("Thread interrupted, Reason {}", e.getMessage());
+                break;
+            } catch (final Exception e) {
+                LOGGER.warn("Error while forwarding events for " + marshallerThread.getName(), e);
+                continue;
+            }
+        }
+
+        // Stop event production if we are not synchronized,;in the synchronized case, the producer
+        // takes care of its own cleanup.
+        producer.stop();
+    }
+
+    /**
+     * Get the marshaler thread.
+     *
+     * @return the marshaler thread
+     */
+    public Thread getThread() {
+        return marshallerThread;
+    }
+
+    /**
+     * Stop the Apex event marshaller's event producer using its termination mechanism.
+     */
+    public void stop() {
+        LOGGER.entry("shutting down Apex event marshaller . . .");
+
+        // Order the stop
+        stopOrderedFlag = true;
+
+        // Wait for thread shutdown
+        while (marshallerThread.isAlive()) {
+            ThreadUtilities.sleep(MARSHALLER_SHUTDOWN_WAIT_INTERVAL);
+        }
+
+        LOGGER.exit("shut down Apex event marshaller");
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexEventUnmarshaller.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexEventUnmarshaller.java
new file mode 100644 (file)
index 0000000..a938575
--- /dev/null
@@ -0,0 +1,323 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.main;
+
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import org.onap.policy.apex.core.infrastructure.threading.ApplicationThreadFactory;
+import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.service.engine.event.ApexEvent;
+import org.onap.policy.apex.service.engine.event.ApexEventConsumer;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.engine.event.ApexEventProtocolConverter;
+import org.onap.policy.apex.service.engine.event.ApexEventReceiver;
+import org.onap.policy.apex.service.engine.event.PeeredReference;
+import org.onap.policy.apex.service.engine.event.SynchronousEventCache;
+import org.onap.policy.apex.service.engine.event.impl.EventConsumerFactory;
+import org.onap.policy.apex.service.engine.event.impl.EventProtocolFactory;
+import org.onap.policy.apex.service.parameters.engineservice.EngineServiceParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This event unmarshaler handles events coming into Apex, handles threading, event queuing,
+ * transformation and receiving using the configured receiving technology.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ApexEventUnmarshaller implements ApexEventReceiver, Runnable {
+    // Get a reference to the logger
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexEventUnmarshaller.class);
+
+    // Interval to wait between thread shutdown checks
+    private static final int UNMARSHALLER_SHUTDOWN_WAIT_INTERVAL = 10;
+
+    // The amount of time to wait between polls of the event queue in milliseconds
+    private static final long EVENT_QUEUE_POLL_INTERVAL = 20;
+
+    // The name of the unmarshaler
+    private final String name;
+
+    // The engine service and consumer parameters
+    private final EngineServiceParameters engineServiceParameters;
+    private final EventHandlerParameters consumerParameters;
+
+    // The engine service handler to use for forwarding on of unmarshalled events
+    private ApexEngineServiceHandler engineServiceHandler;
+
+    // Apex event producer and event converter, all events are sent as string representations
+    private ApexEventConsumer consumer;
+    private ApexEventProtocolConverter converter;
+
+    // Temporary event holder for events going into Apex
+    private final BlockingQueue<ApexEvent> queue = new LinkedBlockingQueue<>();
+
+    // The unmarshaler thread and stopping flag
+    private Thread unmarshallerThread = null;
+    private boolean stopOrderedFlag = false;
+
+    /**
+     * Create the unmarshaler.
+     *
+     * @param name the name of the unmarshaler
+     * @param engineServiceParameters the engine service parameters for this Apex engine
+     * @param consumerParameters the consumer parameters for this specific unmarshaler
+     */
+    public ApexEventUnmarshaller(final String name, final EngineServiceParameters engineServiceParameters,
+            final EventHandlerParameters consumerParameters) {
+        this.name = name;
+        this.engineServiceParameters = engineServiceParameters;
+        this.consumerParameters = consumerParameters;
+    }
+
+    /**
+     * Configure the consumer and initialize the thread for event sending.
+     *
+     * @param incomingEngineServiceHandler the Apex engine service handler for passing events to
+     *        Apex
+     * @throws ApexEventException on errors initializing event handling
+     */
+    public void init(final ApexEngineServiceHandler incomingEngineServiceHandler) throws ApexEventException {
+        this.engineServiceHandler = incomingEngineServiceHandler;
+
+        // Create the consumer for sending events and the converter for transforming events
+        consumer = new EventConsumerFactory().createConsumer(name, consumerParameters);
+        consumer.init(this.name, this.consumerParameters, this);
+
+        converter = new EventProtocolFactory().createConverter(name, consumerParameters.getEventProtocolParameters());
+    }
+
+    /**
+     * Start the unmarshaler and consumer threads.
+     */
+    public void start() {
+        // Start the consumer
+        consumer.start();
+
+        // Configure and start the event reception thread
+        final String threadName =
+                engineServiceParameters.getEngineKey().getName() + ":" + this.getClass().getName() + ":" + name;
+        unmarshallerThread = new ApplicationThreadFactory(threadName).newThread(this);
+        unmarshallerThread.setDaemon(true);
+        unmarshallerThread.start();
+    }
+
+    /**
+     * Gets the name of the unmarshaler.
+     *
+     * @return the unmarshaler name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Gets the technology specific consumer for this unmarshaler.
+     *
+     * @return the consumer
+     */
+    public ApexEventConsumer getConsumer() {
+        return consumer;
+    }
+
+    /**
+     * Gets the event protocol converter for this unmarshaler.
+     *
+     * @return the event protocol converter
+     */
+    public ApexEventProtocolConverter getConverter() {
+        return converter;
+    }
+
+    /**
+     * Connect a synchronous unmarshaler with a synchronous marshaler.
+     * 
+     * @param peeredMode the peered mode under which the unmarshaler and marshaler are connected
+     * @param peeredMarshaller the synchronous marshaler to connect with
+     */
+    public void connectMarshaler(final EventHandlerPeeredMode peeredMode, final ApexEventMarshaller peeredMarshaller) {
+        switch (peeredMode) {
+            case SYNCHRONOUS:
+                // To connect a synchronous unmarshaler and marshaler, we create a synchronous event
+                // cache on the consumer/producer pair
+                new SynchronousEventCache(peeredMode, consumer, peeredMarshaller.getProducer(),
+                        consumerParameters.getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+                return;
+
+            case REQUESTOR:
+                new PeeredReference(peeredMode, consumer, peeredMarshaller.getProducer());
+                return;
+
+            default:
+                return;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.onap.policy.apex.service.engine.event.ApexEventReceiver#receiveEvent(java.lang.Object)
+     */
+    @Override
+    public void receiveEvent(final Object event) throws ApexEventException {
+        receiveEvent(0, event, true);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventReceiver#receiveEvent(long,
+     * java.lang.Object)
+     */
+    @Override
+    public void receiveEvent(final long executionId, final Object event) throws ApexEventException {
+        receiveEvent(executionId, event, false);
+    }
+
+    /**
+     * Receive an event from a consumer, convert its protocol and forward it to Apex.
+     *
+     * @param executionId the execution id the incoming execution ID
+     * @param event the event in its native format
+     * @param generateExecutionId if true, let Apex generate the execution ID, if false, use the
+     *        incoming execution ID
+     * @throws ApexEventException on unmarshaling errors on events
+     */
+    private void receiveEvent(final long executionId, final Object event, final boolean generateExecutionId)
+            throws ApexEventException {
+        // Push the event onto the queue
+        if (LOGGER.isTraceEnabled()) {
+            LOGGER.trace("onMessage(): event received: {}", event.toString());
+        }
+
+        // Convert the incoming events to Apex events
+        try {
+            final List<ApexEvent> apexEventList = converter.toApexEvent(consumerParameters.getEventName(), event);
+            for (final ApexEvent apexEvent : apexEventList) {
+                // Check if we are filtering events on this unmarshaler, if so check the event name
+                // against the filter
+                if (consumerParameters.isSetEventNameFilter()
+                        && !apexEvent.getName().matches(consumerParameters.getEventNameFilter())) {
+                    if (LOGGER.isTraceEnabled()) {
+                        LOGGER.trace("onMessage(): event {} not processed, filtered  out by filter", apexEvent,
+                                consumerParameters.getEventNameFilter());
+                    }
+
+                    // Ignore this event
+                    continue;
+                }
+
+                if (!generateExecutionId) {
+                    apexEvent.setExecutionID(executionId);
+                }
+
+                // Enqueue the event
+                queue.add(apexEvent);
+
+                // Cache synchronized events that are sent
+                if (consumerParameters.isPeeredMode(EventHandlerPeeredMode.SYNCHRONOUS)) {
+                    final SynchronousEventCache synchronousEventCache =
+                            (SynchronousEventCache) consumer.getPeeredReference(EventHandlerPeeredMode.SYNCHRONOUS);
+                    synchronousEventCache.cacheSynchronizedEventToApex(apexEvent.getExecutionID(), apexEvent);
+                }
+            }
+        } catch (final ApexException e) {
+            final String errorMessage = "Error while converting event into an ApexEvent for " + name + ": "
+                    + e.getMessage() + ", Event=" + event;
+            LOGGER.warn(errorMessage, e);
+            throw new ApexEventException(errorMessage, e);
+        }
+    }
+
+    /**
+     * Run a thread that runs forever (well until system termination anyway) and listens for
+     * incoming events on the queue.
+     */
+    @Override
+    public void run() {
+        // Run until interruption
+        while (unmarshallerThread.isAlive() && !stopOrderedFlag) {
+            try {
+                // Take the next event from the queue
+                final ApexEvent apexEvent = queue.poll(EVENT_QUEUE_POLL_INTERVAL, TimeUnit.MILLISECONDS);
+                if (apexEvent == null) {
+                    continue;
+                }
+
+                if (LOGGER.isTraceEnabled()) {
+                    LOGGER.trace("event received {}", apexEvent.toString());
+                }
+
+                // Pass the event to the activator for forwarding to Apex
+                engineServiceHandler.forwardEvent(apexEvent);
+            } catch (final InterruptedException e) {
+                LOGGER.warn("BatchProcessor thread interrupted, Reason {}", e.getMessage());
+                break;
+            } catch (final Exception e) {
+                LOGGER.warn("Error while forwarding events for " + unmarshallerThread.getName(), e);
+                continue;
+            }
+        }
+
+        // Stop event production
+        consumer.stop();
+    }
+
+    /**
+     * Get the unmarshaler thread.
+     *
+     * @return the unmarshaler thread
+     */
+    public Thread getThread() {
+        return unmarshallerThread;
+    }
+
+    /**
+     * Stop the Apex event unmarshaller's event producer using its termination mechanism.
+     */
+    public void stop() {
+        LOGGER.entry("shutting down Apex event unmarshaller . . .");
+
+        // Order the stop
+        stopOrderedFlag = true;
+
+        // Order a stop on the synchronous cache if one exists
+        if (consumerParameters != null && consumerParameters.isPeeredMode(EventHandlerPeeredMode.SYNCHRONOUS)) {
+            if (consumer.getPeeredReference(EventHandlerPeeredMode.SYNCHRONOUS) != null) {
+                ((SynchronousEventCache) consumer.getPeeredReference(EventHandlerPeeredMode.SYNCHRONOUS)).stop();
+            }
+        }
+
+        // Wait for thread shutdown
+        while (unmarshallerThread != null && unmarshallerThread.isAlive()) {
+            ThreadUtilities.sleep(UNMARSHALLER_SHUTDOWN_WAIT_INTERVAL);
+        }
+
+        LOGGER.exit("shut down Apex event unmarshaller");
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexMain.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/ApexMain.java
new file mode 100644 (file)
index 0000000..1b56034
--- /dev/null
@@ -0,0 +1,169 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.main;
+
+import java.util.Arrays;
+import java.util.Map.Entry;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.service.parameters.ApexParameterHandler;
+import org.onap.policy.apex.service.parameters.ApexParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This class initiates Apex as a complete service from the command line.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ApexMain {
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexMain.class);
+
+    // The Apex Activator that activates the Apex engine
+    private ApexActivator activator;
+
+    // The parameters read in from JSON
+    private ApexParameters parameters;
+
+    /**
+     * Instantiates the Apex Apex service.
+     *
+     * @param args the commaind line arguments
+     */
+    public ApexMain(final String[] args) {
+        System.out.println("Starting Apex service with parameters " + Arrays.toString(args) + " . . .");
+        LOGGER.entry("Starting Apex service with parameters " + Arrays.toString(args) + " . . .");
+
+        // Check the arguments
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments();
+        try {
+            // The arguments return a string if there is a message to print and we should exit
+            final String argumentMessage = arguments.parse(args);
+            if (argumentMessage != null) {
+                LOGGER.info(argumentMessage);
+                System.out.println(argumentMessage);
+                return;
+            }
+
+            // Validate that the arguments are sane
+            arguments.validate();
+        } catch (final ApexException e) {
+            System.err.println("start of Apex service failed: " + e.getMessage());
+            LOGGER.error("start of Apex service failed", e);
+            System.err.println(arguments.help(ApexMain.class.getCanonicalName()));
+            return;
+        }
+
+        // Read the parameters
+        try {
+            parameters = new ApexParameterHandler().getParameters(arguments);
+        } catch (final Exception e) {
+            System.err.println("start of Apex service failed\n" + e.getMessage());
+            LOGGER.error("start of Apex service failed", e);
+            return;
+        }
+
+        // Set the name of the event handler parameters for producers and consumers
+        for (final Entry<String, EventHandlerParameters> ehParameterEntry : parameters.getEventOutputParameters()
+                .entrySet()) {
+            if (!ehParameterEntry.getValue().checkSetName()) {
+                ehParameterEntry.getValue().setName(ehParameterEntry.getKey());
+            }
+        }
+        for (final Entry<String, EventHandlerParameters> ehParameterEntry : parameters.getEventInputParameters()
+                .entrySet()) {
+            if (!ehParameterEntry.getValue().checkSetName()) {
+                ehParameterEntry.getValue().setName(ehParameterEntry.getKey());
+            }
+        }
+
+        // Now, create the activator for the Apex service
+        activator = new ApexActivator(parameters);
+
+        // Start the activator
+        try {
+            activator.initialize();
+        } catch (final ApexActivatorException e) {
+            System.err.println("start of Apex service failed, used parameters are " + Arrays.toString(args));
+            e.printStackTrace(System.err);
+            LOGGER.error("start of Apex service failed, used parameters are " + Arrays.toString(args), e);
+            return;
+        }
+
+        // Add a shutdown hook to shut everything down in an orderly manner
+        Runtime.getRuntime().addShutdownHook(new ApexMainShutdownHookClass());
+        LOGGER.exit("Started Apex");
+        System.out.println("Started Apex service");
+    }
+
+    /**
+     * Get the parameters specified in JSON.
+     *
+     * @return the parameters
+     */
+    public ApexParameters getParameters() {
+        return parameters;
+    }
+
+    /**
+     * Shut down Execution.
+     *
+     * @throws ApexException on shutdown errors
+     */
+    public void shutdown() throws ApexException {
+        if (activator != null) {
+            activator.terminate();
+        }
+    }
+
+    /**
+     * The Class ApexMainShutdownHookClass terminates the Apex engine for the Apex service when its
+     * run method is called.
+     *
+     * @author Liam Fallon (liam.fallon@ericsson.com)
+     */
+    private class ApexMainShutdownHookClass extends Thread {
+        /*
+         * (non-Javadoc)
+         *
+         * @see java.lang.Runnable#run()
+         */
+        @Override
+        public void run() {
+            try {
+                // Shutdown the Apex engine and wait for everything to stop
+                activator.terminate();
+            } catch (final ApexException e) {
+                LOGGER.warn("error occured during shut down of the Apex service", e);
+            }
+        }
+    }
+
+    /**
+     * The main method.
+     *
+     * @param args the arguments
+     */
+    public static void main(final String[] args) {
+        new ApexMain(args);
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/main/package-info.java
new file mode 100644 (file)
index 0000000..488d5ab
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Provides the APEX as a complete service together with all its context, executor and event
+ * handling plugins. A main method to allow APEX execution from the command line is also provided.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.main;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/package-info.java
new file mode 100644 (file)
index 0000000..cdd6c5e
--- /dev/null
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Provides Java APIs for Apex. APIs are provided to give access to the APEX engine runtime, to give
+ * access to APEX event handling, and to give access to the ApexEngDep protocol for engine
+ * management.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/ApexEventListener.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/ApexEventListener.java
new file mode 100644 (file)
index 0000000..a498bcf
--- /dev/null
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.runtime;
+
+import org.onap.policy.apex.service.engine.event.ApexEvent;
+
+/**
+ * The listener interface for receiving apexEvent events. The class that is interested in processing
+ * a apexEvent event implements this interface, and the object created with that class is registered
+ * with a component using the component's {@code addApexEventListener} method. When the apexEvent
+ * event occurs, that object's appropriate method is invoked.
+ *
+ * @author Sajeevan Achuthan (sajeevan.achuthan@ericsson.com)
+ */
+public interface ApexEventListener {
+
+    /**
+     * Callback method called on implementations of this interface when APEX emits an event.
+     *
+     * @param apexEvent the apex event emitted by APEX
+     */
+    void onApexEvent(ApexEvent apexEvent);
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/EngineService.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/EngineService.java
new file mode 100644 (file)
index 0000000..e6fc332
--- /dev/null
@@ -0,0 +1,214 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.runtime;
+
+import java.util.Collection;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.enginemodel.concepts.AxEngineState;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
+
+/**
+ * The administration interface for Apex engine users. Apex engine implementations expose this
+ * interface and external users use it to manage Apex engines.
+ *
+ * @author Sajeevan Achuthan (sajeevan.achuthan@ericsson.com)
+ */
+public interface EngineService {
+    /**
+     * A method to attach a listener to the engine.
+     *
+     * @param listenerName a unique name for the listener
+     * @param listener is a callback interface to the engine.
+     */
+    void registerActionListener(String listenerName, ApexEventListener listener);
+
+    /**
+     * A method to detach a listener from the engine.
+     *
+     * @param listenerName the unique name of the listener to deregister
+     */
+    void deregisterActionListener(String listenerName);
+
+    /**
+     * This method gets the current runtime information for the running Apex engines.
+     *
+     * @return the engine service event interface
+     */
+    EngineServiceEventInterface getEngineServiceEventInterface();
+
+    /**
+     * Gets the key of the engine service or worker.
+     *
+     * @return the key
+     */
+    AxArtifactKey getKey();
+
+    /**
+     * This method gets the keys of the engines on the engine service.
+     *
+     * @return the engine keys
+     */
+    Collection<AxArtifactKey> getEngineKeys();
+
+    /**
+     * The the key of the Apex model the engine service is running on.
+     *
+     * @return the Apex model key
+     */
+    AxArtifactKey getApexModelKey();
+
+    /**
+     * This method updates the Apex model on Apex execution engines using a string representation of
+     * the model.
+     *
+     * @param engineServiceKey The key of the engine service on which to update the model
+     * @param apexModelString the apex model string
+     * @param forceFlag if true, model updates will be executed even on incompatible models
+     *        (different model names) and versions (different model version)
+     * @throws ApexException on model update errors
+     */
+    void updateModel(AxArtifactKey engineServiceKey, String apexModelString, boolean forceFlag) throws ApexException;
+
+    /**
+     * This method updates the Apex model on Apex execution engines using a policy model as input.
+     *
+     * @param engineServiceKey The key of the engine service on which to update the model
+     * @param apexModel is a policy definition model
+     * @param forceFlag if true, model updates will be executed even on incompatible models
+     *        (different model names) and versions (different model version)
+     * @throws ApexException on model update errors
+     */
+    void updateModel(AxArtifactKey engineServiceKey, AxPolicyModel apexModel, boolean forceFlag) throws ApexException;
+
+    /**
+     * This method returns the state of an engine service or engine.
+     *
+     * @return The engine service or engine state
+     */
+    AxEngineState getState();
+
+    /**
+     * This method starts all Apex engines in the engine service.
+     *
+     * @throws ApexException on start errors
+     */
+    void startAll() throws ApexException;
+
+    /**
+     * This method starts an Apex engine in the engine service.
+     *
+     * @param engineKey The key of the Apex engine to start
+     * @throws ApexException on start errors
+     */
+    void start(AxArtifactKey engineKey) throws ApexException;
+
+    /**
+     * This method stops all Apex engines in the engine service.
+     *
+     * @throws ApexException on stop errors
+     */
+    void stop() throws ApexException;
+
+    /**
+     * This method stops an Apex engine in the engine service.
+     *
+     * @param engineKey The key of the Apex engine to stop
+     * @throws ApexException on stop errors
+     */
+    void stop(AxArtifactKey engineKey) throws ApexException;
+
+    /**
+     * This method checks if all Apex engines in the engine service are started.
+     * <p>
+     * Note: an engine can be both not stopped and not started, for example, when it is starting or
+     * stopping
+     *
+     * @return true if all Apex engines in the engine service are started.
+     */
+    boolean isStarted();
+
+    /**
+     * This method checks if an Apex engine in the engine service is started.
+     * <p>
+     * Note: an engine can be both not stopped and not started, for example, when it is starting or
+     * stopping
+     *
+     * @param engineKey The key of the Apex engine to check
+     * @return true if all Apex engines in the engine service are started.
+     */
+    boolean isStarted(AxArtifactKey engineKey);
+
+    /**
+     * This method checks if all Apex engines in the engine service are stopped.
+     * <p>
+     * Note: an engine can be both not stopped and not started, for example, when it is starting or
+     * stopping
+     *
+     * @return true if all Apex engines in the engine service are stopped.
+     */
+    boolean isStopped();
+
+    /**
+     * This method checks if an Apex engine in the engine service is stopped.
+     * <p>
+     * Note: an engine can be both not stopped and not started, for example, when it is starting or
+     * stopping
+     *
+     * @param engineKey The key of the Apex engine to check
+     * @return true if all Apex engines in the engine service are stopped.
+     */
+    boolean isStopped(AxArtifactKey engineKey);
+
+    /**
+     * This method starts periodic event generation.
+     *
+     * @param period The period in milliseconds between periodic events
+     * @throws ApexException On periodic event start errors
+     */
+    void startPeriodicEvents(long period) throws ApexException;
+
+    /**
+     * This method stops periodic event generation.
+     *
+     * @throws ApexException On periodic event stop errors
+     */
+    void stopPeriodicEvents() throws ApexException;
+
+    /**
+     * This method gets the status of an Apex engine in the engine service.
+     *
+     * @param engineKey the engine key
+     * @return the engine runtime information
+     * @throws ApexException on status read errors
+     */
+    String getStatus(AxArtifactKey engineKey) throws ApexException;
+
+    /**
+     * This method gets the runtime information of all Apex engines in the engine service.
+     *
+     * @param engineKey the engine key
+     * @return the engine runtime information
+     * @throws ApexException on runtime information read errors
+     */
+    String getRuntimeInfo(AxArtifactKey engineKey) throws ApexException;
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/EngineServiceEventInterface.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/EngineServiceEventInterface.java
new file mode 100644 (file)
index 0000000..8e4cb82
--- /dev/null
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.runtime;
+
+import org.onap.policy.apex.service.engine.event.ApexEvent;
+
+/**
+ * The run time interface for APEX engine users. APEX engine implementations expose this interface
+ * and external users use it to send events to the engine.
+ *
+ * @author Sajeevan Achuthan (sajeevan.achuthan@ericsson.com), John Keeney
+ *         (john.keeney@ericsson.com)
+ */
+public interface EngineServiceEventInterface {
+    /**
+     * This method forwards an event to the APEX engine.
+     *
+     * @param event is an instance {@link ApexEvent}
+     */
+    void sendEvent(ApexEvent event);
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EnEventListenerImpl.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EnEventListenerImpl.java
new file mode 100644 (file)
index 0000000..abd6db2
--- /dev/null
@@ -0,0 +1,71 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.runtime.impl;
+
+import org.onap.policy.apex.core.engine.engine.EnEventListener;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.service.engine.event.ApexEvent;
+import org.onap.policy.apex.service.engine.event.impl.enevent.ApexEvent2EnEventConverter;
+import org.onap.policy.apex.service.engine.runtime.ApexEventListener;
+
+/**
+ * The Class EnEventListenerImpl is used by the Apex engine implementation to listen for events
+ * coming from the core APEX engine. This listener converts the {@link EnEvent} instances into
+ * {@link ApexEvent} instances using an {@link ApexEvent2EnEventConverter} instance and forwards the
+ * events to an {@link ApexEventListener} instance for outputting to listening applications. The
+ * {@link ApexEventListener} is implemented in the external application communicating with Apex.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public final class EnEventListenerImpl implements EnEventListener {
+    // Listener for ApexEvents
+    private ApexEventListener apexEventListener = null;
+
+    // Converter for Engine events to Apex Events
+    private ApexEvent2EnEventConverter apexEnEventConverter = null;
+
+    /**
+     * Instantiates a new listener implementation.
+     *
+     * @param apexEventListener the apex event listener
+     * @param apexEnEventConverter the ApexEvent to enEvent converter
+     */
+    public EnEventListenerImpl(final ApexEventListener apexEventListener,
+            final ApexEvent2EnEventConverter apexEnEventConverter) {
+        this.apexEventListener = apexEventListener;
+        this.apexEnEventConverter = apexEnEventConverter;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.core.engine.engine.EnEventListener#onEnEvent(org.onap.policy.apex.core.
+     * engine.event.EnEvent)
+     */
+    @Override
+    public void onEnEvent(final EnEvent enEvent) throws ApexException {
+        for (final ApexEvent apexEvent : apexEnEventConverter.toApexEvent(enEvent.getName(), enEvent)) {
+            apexEventListener.onApexEvent(apexEvent);
+        }
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EngineServiceImpl.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EngineServiceImpl.java
new file mode 100644 (file)
index 0000000..24d8263
--- /dev/null
@@ -0,0 +1,682 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.runtime.impl;
+
+import java.io.ByteArrayInputStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.core.infrastructure.threading.ApplicationThreadFactory;
+import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.handling.ApexModelException;
+import org.onap.policy.apex.model.basicmodel.handling.ApexModelReader;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.enginemodel.concepts.AxEngineState;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
+import org.onap.policy.apex.service.engine.event.ApexEvent;
+import org.onap.policy.apex.service.engine.event.ApexPeriodicEventGenerator;
+import org.onap.policy.apex.service.engine.runtime.ApexEventListener;
+import org.onap.policy.apex.service.engine.runtime.EngineService;
+import org.onap.policy.apex.service.engine.runtime.EngineServiceEventInterface;
+import org.onap.policy.apex.service.parameters.engineservice.EngineServiceParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The Class EngineServiceImpl controls a thread pool that runs a set of Apex engine workers, each
+ * of which is running on an identical Apex model. This class handles the management of the engine
+ * worker instances, their threads, and event forwarding to and from the engine workers.
+ *
+ * @author Sajeevan Achuthan (sajeevan.achuthan@ericsson.com)
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @author John Keeney (john.keeney@ericsson.com)
+ */
+public final class EngineServiceImpl implements EngineService, EngineServiceEventInterface {
+    // Logging static variables
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(EngineServiceImpl.class);
+    private static final boolean DEBUG_ENABLED = LOGGER.isDebugEnabled();
+
+    // Constants for timing
+    private static final long MAX_START_WAIT_TIME = 5000; // 5 seconds
+    private static final long MAX_STOP_WAIT_TIME = 5000; // 5 seconds
+    private static final int ENGINE_SERVICE_STOP_START_WAIT_INTERVAL = 200;
+
+    // The ID of this engine
+    private AxArtifactKey engineServiceKey = null;
+
+    // The Apex engine workers this engine service is handling
+    private final Map<AxArtifactKey, EngineService> engineWorkerMap =
+            Collections.synchronizedMap(new LinkedHashMap<AxArtifactKey, EngineService>());
+
+    // Event queue for events being sent into the Apex engines, it used by all engines within a
+    // group.
+    private final BlockingQueue<ApexEvent> queue = new LinkedBlockingQueue<>();
+
+    // Thread factory for thread management
+    private final ApplicationThreadFactory tFactory = new ApplicationThreadFactory("apex-engine-service", 512);
+
+    // Periodic event generator and its period in milliseconds
+    private ApexPeriodicEventGenerator periodicEventGenerator = null;
+    private long periodicEventPeriod;
+
+    /**
+     * This constructor instantiates engine workers and adds them to the set of engine workers to be
+     * managed. The constructor is private to prevent subclassing.
+     *
+     * @param engineServiceKey the engine service key
+     * @param incomingThreadCount the thread count, the number of engine workers to start
+     * @param periodicEventPeriod the period in milliseconds at which periodic events are generated
+     * @throws ApexException on worker instantiation errors
+     */
+    private EngineServiceImpl(final AxArtifactKey engineServiceKey, final int incomingThreadCount,
+            final long periodicEventPeriod) throws ApexException {
+        LOGGER.entry(engineServiceKey, incomingThreadCount);
+
+        this.engineServiceKey = engineServiceKey;
+        this.periodicEventPeriod = periodicEventPeriod;
+
+        int threadCount = incomingThreadCount;
+        if (threadCount <= 0) {
+            // Just start one engine worker
+            threadCount = 1;
+        }
+
+        // Start engine workers
+        for (int engineCounter = 0; engineCounter < threadCount; engineCounter++) {
+            final AxArtifactKey engineWorkerKey =
+                    new AxArtifactKey(engineServiceKey.getName() + '-' + engineCounter, engineServiceKey.getVersion());
+            engineWorkerMap.put(engineWorkerKey, new EngineWorker(engineWorkerKey, queue, tFactory));
+            LOGGER.info("Created apex engine {} .", engineWorkerKey.getID());
+        }
+
+        LOGGER.info("APEX service created.");
+        LOGGER.exit();
+    }
+
+    /**
+     * Create an Apex Engine Service instance. This method is deprecated and will be removed in the
+     * next version.
+     *
+     * @param engineServiceKey the engine service key
+     * @param threadCount the thread count, the number of engine workers to start
+     * @return the Engine Service instance
+     * @throws ApexException on worker instantiation errors
+     * @deprecated Do not use this version. Use {@link #create(EngineServiceParameters)}
+     */
+    @Deprecated
+    public static EngineServiceImpl create(final AxArtifactKey engineServiceKey, final int threadCount)
+            throws ApexException {
+        // Check if the Apex model specified is sane
+        if (engineServiceKey == null) {
+            LOGGER.warn("engine service key is null");
+            throw new ApexException("engine service key is null");
+        }
+        return new EngineServiceImpl(engineServiceKey, threadCount, 0);
+    }
+
+    /**
+     * Create an Apex Engine Service instance. This method does not load the policy so
+     * {@link #updateModel(AxArtifactKey, AxPolicyModel, boolean)} or
+     * {@link #updateModel(AxArtifactKey, AxPolicyModel, boolean)} must be used to load a model.
+     * This method does not start the Engine Service so {@link #start(AxArtifactKey)} or
+     * {@link #startAll()} must be used.
+     *
+     * @param config the configuration for this Apex Engine Service.
+     * @return the Engine Service instance
+     * @throws ApexException on worker instantiation errors
+     */
+    public static EngineServiceImpl create(final EngineServiceParameters config) throws ApexException {
+        if (config == null) {
+            LOGGER.warn("Engine service configuration parameters is null");
+            throw new ApexException("engine service configuration parameters is null");
+        }
+        final String validation = config.validate();
+        if (validation != null && validation.length() > 0) {
+            LOGGER.warn("Invalid engine service configuration parameters: " + validation);
+            throw new ApexException("Invalid engine service configuration parameters: " + validation);
+        }
+        final AxArtifactKey engineServiceKey = config.getEngineKey();
+        final int threadCount = config.getInstanceCount();
+
+        // Check if the Apex model specified is sane
+        if (engineServiceKey == null) {
+            LOGGER.warn("engine service key is null");
+            throw new ApexException("engine service key is null");
+        }
+
+        return new EngineServiceImpl(engineServiceKey, threadCount, config.getPeriodicEventPeriod());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.ericsson.apex.service.engine.runtime.EngineService#registerActionListener(java.lang.
+     * String, com.ericsson.apex.service.engine.runtime.ApexEventListener)
+     */
+    @Override
+    public void registerActionListener(final String listenerName, final ApexEventListener apexEventListener) {
+        LOGGER.entry(apexEventListener);
+
+        // Register the Apex event listener on all engine workers, each worker will return Apex
+        // events to the listening application
+        for (final EngineService engineWorker : engineWorkerMap.values()) {
+            engineWorker.registerActionListener(listenerName, apexEventListener);
+        }
+
+        LOGGER.info("Added the action listener to the engine");
+        LOGGER.exit();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * com.ericsson.apex.service.engine.runtime.EngineService#deregisterActionListener(java.lang.
+     * String)
+     */
+    @Override
+    public void deregisterActionListener(final String listenerName) {
+        LOGGER.entry(listenerName);
+
+        // Register the Apex event listener on all engine workers, each worker will return Apex
+        // events to the listening application
+        for (final EngineService engineWorker : engineWorkerMap.values()) {
+            engineWorker.deregisterActionListener(listenerName);
+        }
+
+        LOGGER.info("Removed the action listener from the engine");
+        LOGGER.exit();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.apex.service.engine.runtime.EngineService#getEngineServiceEventInterface()
+     */
+    @Override
+    public EngineServiceEventInterface getEngineServiceEventInterface() {
+        return this;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.apex.service.engine.runtime.EngineService#getKey()
+     */
+    @Override
+    public AxArtifactKey getKey() {
+        return engineServiceKey;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.apex.service.engine.runtime.EngineService#getInfo()
+     */
+    @Override
+    public Collection<AxArtifactKey> getEngineKeys() {
+        return engineWorkerMap.keySet();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.apex.service.engine.runtime.EngineService#getApexModelKey()
+     */
+    @Override
+    public AxArtifactKey getApexModelKey() {
+        if (engineWorkerMap.size() == 0) {
+            return null;
+        }
+
+        return engineWorkerMap.entrySet().iterator().next().getValue().getApexModelKey();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * com.ericsson.apex.service.engine.runtime.EngineService#updateModel(com.ericsson.apex.model.
+     * basicmodel.concepts.AxArtifactKey, java.lang.String, boolean)
+     */
+    @Override
+    public void updateModel(final AxArtifactKey incomingEngineServiceKey, final String apexModelString,
+            final boolean forceFlag) throws ApexException {
+        // Check if the Apex model specified is sane
+        if (apexModelString == null || apexModelString.trim().length() == 0) {
+            LOGGER.warn(
+                    "model for updating on engine service with key " + incomingEngineServiceKey.getID() + " is empty");
+            throw new ApexException(
+                    "model for updating on engine service with key " + incomingEngineServiceKey.getID() + " is empty");
+        }
+
+        // Read the Apex model into memory using the Apex Model Reader
+        AxPolicyModel apexPolicyModel = null;
+        try {
+            final ApexModelReader<AxPolicyModel> modelReader = new ApexModelReader<>(AxPolicyModel.class);
+            apexPolicyModel = modelReader.read(new ByteArrayInputStream(apexModelString.getBytes()));
+        } catch (final ApexModelException e) {
+            LOGGER.error("failed to unmarshal the apex model on engine service " + incomingEngineServiceKey.getID(), e);
+            throw new ApexException(
+                    "failed to unmarshal the apex model on engine service " + incomingEngineServiceKey.getID(), e);
+        }
+
+        if (apexPolicyModel == null) {
+            LOGGER.error("apex model null on engine service " + incomingEngineServiceKey.getID());
+            throw new ApexException("apex model null on engine service " + incomingEngineServiceKey.getID());
+        }
+
+        // Update the model
+        updateModel(incomingEngineServiceKey, apexPolicyModel, forceFlag);
+
+        LOGGER.exit();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * com.ericsson.apex.service.engine.runtime.EngineService#updateModel(com.ericsson.apex.model.
+     * basicmodel.concepts.AxArtifactKey,
+     * com.ericsson.apex.model.policymodel.concepts.AxPolicyModel, boolean)
+     */
+    @Override
+    public void updateModel(final AxArtifactKey incomingEngineServiceKey, final AxPolicyModel apexModel,
+            final boolean forceFlag) throws ApexException {
+        LOGGER.entry(incomingEngineServiceKey);
+
+        // Check if the Apex model specified is sane
+        if (apexModel == null) {
+            LOGGER.warn(
+                    "model for updating on engine service with key " + incomingEngineServiceKey.getID() + " is null");
+            throw new ApexException(
+                    "model for updating on engine service with key " + incomingEngineServiceKey.getID() + " is null");
+        }
+
+        // Check if the key on the update request is correct
+        if (!this.engineServiceKey.equals(incomingEngineServiceKey)) {
+            LOGGER.warn("engine service key " + incomingEngineServiceKey.getID() + " does not match the key"
+                    + engineServiceKey.getID() + " of this engine service");
+            throw new ApexException("engine service key " + incomingEngineServiceKey.getID() + " does not match the key"
+                    + engineServiceKey.getID() + " of this engine service");
+        }
+
+        // Check model compatibility
+        if (ModelService.existsModel(AxPolicyModel.class)) {
+            // The current policy model may or may not be defined
+            final AxPolicyModel currentModel = ModelService.getModel(AxPolicyModel.class);
+            if (!currentModel.getKey().isCompatible(apexModel.getKey())) {
+                if (forceFlag) {
+                    LOGGER.warn("apex model update forced, supplied model with key \"" + apexModel.getKey().getID()
+                            + "\" is not a compatible model update from the existing engine model with key \""
+                            + currentModel.getKey().getID() + "\"");
+                } else {
+                    throw new ContextException(
+                            "apex model update failed, supplied model with key \"" + apexModel.getKey().getID()
+                                    + "\" is not a compatible model update from the existing engine model with key \""
+                                    + currentModel.getKey().getID() + "\"");
+                }
+            }
+        }
+
+        final boolean wasstopped = isStopped();
+
+        if (!wasstopped) {
+            // Stop all engines on this engine service
+            stop();
+            final long stoptime = System.currentTimeMillis();
+            while (!isStopped() && System.currentTimeMillis() - stoptime < MAX_STOP_WAIT_TIME) {
+                ThreadUtilities.sleep(ENGINE_SERVICE_STOP_START_WAIT_INTERVAL);
+            }
+            // Check if all engines are stopped
+            final StringBuilder notStoppedEngineIDBuilder = new StringBuilder();
+            for (final Entry<AxArtifactKey, EngineService> engineWorkerEntry : engineWorkerMap.entrySet()) {
+                if (engineWorkerEntry.getValue().getState() != AxEngineState.STOPPED) {
+                    notStoppedEngineIDBuilder.append(engineWorkerEntry.getKey().getID());
+                    notStoppedEngineIDBuilder.append('(');
+                    notStoppedEngineIDBuilder.append(engineWorkerEntry.getValue().getState());
+                    notStoppedEngineIDBuilder.append(") ");
+                }
+            }
+            if (notStoppedEngineIDBuilder.length() > 0) {
+                final String errorString = "cannot update model on engine service with key "
+                        + incomingEngineServiceKey.getID() + ", engines not stopped after " + MAX_STOP_WAIT_TIME
+                        + "ms are: " + notStoppedEngineIDBuilder.toString().trim();
+                LOGGER.warn(errorString);
+                throw new ApexException(errorString);
+            }
+        }
+
+        // Update the engines
+        for (final Entry<AxArtifactKey, EngineService> engineWorkerEntry : engineWorkerMap.entrySet()) {
+            LOGGER.info("Registering apex model on engine {}", engineWorkerEntry.getKey().getID());
+            engineWorkerEntry.getValue().updateModel(engineWorkerEntry.getKey(), apexModel, forceFlag);
+        }
+
+        if (!wasstopped) {
+            // start all engines on this engine service if it was not stopped before the update
+            startAll();
+            final long starttime = System.currentTimeMillis();
+            while (!isStarted() && System.currentTimeMillis() - starttime < MAX_START_WAIT_TIME) {
+                ThreadUtilities.sleep(ENGINE_SERVICE_STOP_START_WAIT_INTERVAL);
+            }
+            // Check if all engines are running
+            final StringBuilder notRunningEngineIDBuilder = new StringBuilder();
+            for (final Entry<AxArtifactKey, EngineService> engineWorkerEntry : engineWorkerMap.entrySet()) {
+                if (engineWorkerEntry.getValue().getState() != AxEngineState.READY
+                        && engineWorkerEntry.getValue().getState() != AxEngineState.EXECUTING) {
+                    notRunningEngineIDBuilder.append(engineWorkerEntry.getKey().getID());
+                    notRunningEngineIDBuilder.append('(');
+                    notRunningEngineIDBuilder.append(engineWorkerEntry.getValue().getState());
+                    notRunningEngineIDBuilder.append(") ");
+                }
+            }
+            if (notRunningEngineIDBuilder.length() > 0) {
+                final String errorString = "engine start error on model update on engine service with key "
+                        + incomingEngineServiceKey.getID() + ", engines not running are: "
+                        + notRunningEngineIDBuilder.toString().trim();
+                LOGGER.warn(errorString);
+                throw new ApexException(errorString);
+            }
+        }
+
+        LOGGER.exit();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.apex.service.engine.runtime.EngineService#getState()
+     */
+    @Override
+    public AxEngineState getState() {
+        // If one worker is running then we are running, otherwise we are stopped
+        for (final EngineService engine : engineWorkerMap.values()) {
+            if (engine.getState() != AxEngineState.STOPPED) {
+                return AxEngineState.EXECUTING;
+            }
+        }
+
+        return AxEngineState.STOPPED;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.apex.service.engine.runtime.EngineService#startAll()
+     */
+    @Override
+    public void startAll() throws ApexException {
+        for (final EngineService engine : engineWorkerMap.values()) {
+            start(engine.getKey());
+        }
+
+        // Check if periodic events should be turned on
+        if (periodicEventPeriod > 0) {
+            startPeriodicEvents(periodicEventPeriod);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * com.ericsson.apex.service.engine.runtime.EngineService#start(com.ericsson.apex.core.model.
+     * concepts.AxArtifactKey)
+     */
+    @Override
+    public void start(final AxArtifactKey engineKey) throws ApexException {
+        LOGGER.entry(engineKey);
+
+        // Check if we have this key on our map
+        if (!engineWorkerMap.containsKey(engineKey)) {
+            LOGGER.warn("engine with key " + engineKey.getID() + " not found in engine service");
+            throw new ApexException("engine with key " + engineKey.getID() + " not found in engine service");
+        }
+
+        // Start the engine
+        engineWorkerMap.get(engineKey).start(engineKey);
+
+        LOGGER.exit(engineKey);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.apex.service.engine.runtime.EngineService#stop()
+     */
+    @Override
+    public void stop() throws ApexException {
+        LOGGER.entry();
+
+        // Stop each engine
+        for (final EngineService engine : engineWorkerMap.values()) {
+            if (engine.getState() != AxEngineState.STOPPED) {
+                engine.stop();
+            }
+        }
+
+        LOGGER.exit();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * com.ericsson.apex.service.engine.runtime.EngineService#stop(com.ericsson.apex.core.model.
+     * concepts.AxArtifactKey)
+     */
+    @Override
+    public void stop(final AxArtifactKey engineKey) throws ApexException {
+        LOGGER.entry(engineKey);
+
+        // Check if we have this key on our map
+        if (!engineWorkerMap.containsKey(engineKey)) {
+            LOGGER.warn("engine with key " + engineKey.getID() + " not found in engine service");
+            throw new ApexException("engine with key " + engineKey.getID() + " not found in engine service");
+        }
+
+        // Stop the engine
+        engineWorkerMap.get(engineKey).stop(engineKey);
+
+        LOGGER.exit(engineKey);
+    }
+
+    /**
+     * Check all engines are started.
+     *
+     * @return true if <i>all</i> engines are started
+     * @see org.onap.policy.apex.service.engine.runtime.EngineService#isStarted()
+     */
+    @Override
+    public boolean isStarted() {
+        for (final EngineService engine : engineWorkerMap.values()) {
+            if (!engine.isStarted()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * com.ericsson.apex.service.engine.runtime.EngineService#isStarted(com.ericsson.apex.model.
+     * basicmodel.concepts.AxArtifactKey)
+     */
+    @Override
+    public boolean isStarted(final AxArtifactKey engineKey) {
+        // Check if we have this key on our map
+        if (!engineWorkerMap.containsKey(engineKey)) {
+            LOGGER.warn("engine with key " + engineKey.getID() + " not found in engine service");
+        }
+        return engineWorkerMap.get(engineKey).isStarted();
+    }
+
+    /**
+     * Check all engines are stopped.
+     *
+     * @return true if <i>all</i> engines are stopped
+     * @see org.onap.policy.apex.service.engine.runtime.EngineService#isStopped()
+     */
+    @Override
+    public boolean isStopped() {
+        for (final EngineService engine : engineWorkerMap.values()) {
+            if (!engine.isStopped()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * com.ericsson.apex.service.engine.runtime.EngineService#isStopped(com.ericsson.apex.model.
+     * basicmodel.concepts.AxArtifactKey)
+     */
+    @Override
+    public boolean isStopped(final AxArtifactKey engineKey) {
+        // Check if we have this key on our map
+        if (!engineWorkerMap.containsKey(engineKey)) {
+            LOGGER.warn("engine with key " + engineKey.getID() + " not found in engine service");
+        }
+        return engineWorkerMap.get(engineKey).isStopped();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.apex.service.engine.runtime.EngineService#startPeriodicEvents(long)
+     */
+    @Override
+    public void startPeriodicEvents(final long period) throws ApexException {
+        // Check if periodic events are already started
+        if (periodicEventGenerator != null) {
+            LOGGER.warn("Peiodic event geneation already running on engine " + engineServiceKey.getID() + ", "
+                    + periodicEventGenerator.toString());
+            throw new ApexException("Peiodic event geneation already running on engine " + engineServiceKey.getID()
+                    + ", " + periodicEventGenerator.toString());
+        }
+
+        // Set up periodic event execution, its a Java Timer/TimerTask
+        periodicEventGenerator = new ApexPeriodicEventGenerator(this.getEngineServiceEventInterface(), period);
+
+        // Record the periodic event period because it may have been set over the Web Socket admin
+        // interface
+        this.periodicEventPeriod = period;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.apex.service.engine.runtime.EngineService#stopPeriodicEvents()
+     */
+    @Override
+    public void stopPeriodicEvents() throws ApexException {
+        // Check if periodic events are already started
+        if (periodicEventGenerator == null) {
+            LOGGER.warn("Peiodic event geneation not running on engine " + engineServiceKey.getID());
+            throw new ApexException("Peiodic event geneation not running on engine " + engineServiceKey.getID());
+        }
+
+        // Stop periodic events
+        periodicEventGenerator.cancel();
+        periodicEventGenerator = null;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * com.ericsson.apex.service.engine.runtime.EngineService#getStatus(com.ericsson.apex.core.model
+     * .concepts.AxArtifactKey)
+     */
+    @Override
+    public String getStatus(final AxArtifactKey engineKey) throws ApexException {
+        // Check if we have this key on our map
+        if (!engineWorkerMap.containsKey(engineKey)) {
+            LOGGER.warn("engine with key " + engineKey.getID() + " not found in engine service");
+            throw new ApexException("engine with key " + engineKey.getID() + " not found in engine service");
+        }
+
+        // Return the information for this worker
+        return engineWorkerMap.get(engineKey).getStatus(engineKey);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * com.ericsson.apex.service.engine.runtime.EngineService#getRuntimeInfo(com.ericsson.apex.core.
+     * model.concepts.AxArtifactKey)
+     */
+    @Override
+    public String getRuntimeInfo(final AxArtifactKey engineKey) throws ApexException {
+        // Check if we have this key on our map
+        if (!engineWorkerMap.containsKey(engineKey)) {
+            LOGGER.warn("engine with key " + engineKey.getID() + " not found in engine service");
+            throw new ApexException("engine with key " + engineKey.getID() + " not found in engine service");
+        }
+
+        // Return the information for this worker
+        return engineWorkerMap.get(engineKey).getRuntimeInfo(engineKey);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * com.ericsson.apex.service.engine.runtime.EngineServiceEventInterface#sendEvent(com.ericsson.
+     * apex.service.engine.event.ApexEvent)
+     */
+    @Override
+    public void sendEvent(final ApexEvent event) {
+        // Check if we have this key on our map
+        if (getState() == AxEngineState.STOPPED) {
+            LOGGER.warn("event " + event.getName() + " not processed, no engines on engine service "
+                    + engineServiceKey.getID() + " are running");
+            return;
+        }
+
+        if (event == null) {
+            LOGGER.warn("Null events cannot be processed, in engine service " + engineServiceKey.getID());
+            return;
+        }
+
+        if (DEBUG_ENABLED) {
+            LOGGER.debug("Forwarding Apex Event {} to the processing engine", event);
+        }
+
+        // Add the incoming event to the queue, the next available worker will process it
+        queue.add(event);
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EngineWorker.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/EngineWorker.java
new file mode 100644 (file)
index 0000000..20f8aaf
--- /dev/null
@@ -0,0 +1,674 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.runtime.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.BlockingQueue;
+
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.context.ContextRuntimeException;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.core.engine.engine.ApexEngine;
+import org.onap.policy.apex.core.engine.engine.impl.ApexEngineFactory;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.core.infrastructure.threading.ApplicationThreadFactory;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.handling.ApexModelException;
+import org.onap.policy.apex.model.basicmodel.handling.ApexModelReader;
+import org.onap.policy.apex.model.basicmodel.handling.ApexModelWriter;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbums;
+import org.onap.policy.apex.model.enginemodel.concepts.AxEngineModel;
+import org.onap.policy.apex.model.enginemodel.concepts.AxEngineState;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
+import org.onap.policy.apex.service.engine.event.ApexEvent;
+import org.onap.policy.apex.service.engine.event.impl.enevent.ApexEvent2EnEventConverter;
+import org.onap.policy.apex.service.engine.runtime.ApexEventListener;
+import org.onap.policy.apex.service.engine.runtime.EngineService;
+import org.onap.policy.apex.service.engine.runtime.EngineServiceEventInterface;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+
+/**
+ * The Class EngineWorker encapsulates a core {@link ApexEngine} instance, which runs policies
+ * defined in the {@link org.onap.policy.apex.model.basicmodel.concepts.AxModelAxModel}. Each policy
+ * is triggered by an Apex event, and when the policy is triggered it runs through to completion in
+ * the ApexEngine.
+ *
+ * This class acts as a container for an {@link ApexEngine}, running it in a thread, sending it
+ * events, and receiving events from it.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+final class EngineWorker implements EngineService {
+    // Logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(EngineService.class);
+
+    // The ID of this engine
+    private final AxArtifactKey engineWorkerKey;
+
+    // The Apex engine which is running the policies in this worker
+    private final ApexEngine engine;
+
+    // The event processor is an inner class, an instance of which runs as a thread that reads
+    // incoming events from a queue and forwards them to the Apex engine
+    private EventProcessor processor = null;
+
+    // Thread handling for the worker
+    private final ApplicationThreadFactory threadFactory;
+    private Thread processorThread;
+
+    // Converts ApexEvent instances to and from EnEvent instances
+    private ApexEvent2EnEventConverter apexEnEventConverter = null;
+
+    /**
+     * Constructor that creates an Apex engine, an event processor for events to be sent to that
+     * engine, and an {@link ApexModelReader} instance to read Apex models using JAXB.
+     *
+     * @param engineWorkerKey the engine worker key
+     * @param queue the queue on which events for this Apex worker will come
+     * @param threadFactory the thread factory to use for creating the event processing thread
+     * @throws ApexException thrown on errors on worker instantiation
+     */
+    EngineWorker(final AxArtifactKey engineWorkerKey, final BlockingQueue<ApexEvent> queue,
+            final ApplicationThreadFactory threadFactory) throws ApexException {
+        LOGGER.entry(engineWorkerKey);
+
+        this.engineWorkerKey = engineWorkerKey;
+        this.threadFactory = threadFactory;
+
+        // Create the Apex engine
+        engine = new ApexEngineFactory().createApexEngine(engineWorkerKey);
+
+        // Create and run the event processor
+        processor = new EventProcessor(queue);
+
+        // Set the Event converter up
+        apexEnEventConverter = new ApexEvent2EnEventConverter(engine);
+
+        LOGGER.exit();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.onap.policy.apex.service.engine.runtime.EngineService#registerActionListener(java.lang.
+     * String, org.onap.policy.apex.service.engine.runtime.ApexEventListener)
+     */
+    @Override
+    public void registerActionListener(final String listenerName, final ApexEventListener apexEventListener) {
+        // Sanity checks on the Apex model
+        if (engine == null) {
+            LOGGER.warn("listener registration on engine with key " + engineWorkerKey.getID()
+                    + ", failed, listener is null");
+            return;
+        }
+
+        engine.addEventListener(listenerName, new EnEventListenerImpl(apexEventListener, apexEnEventConverter));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.onap.policy.apex.service.engine.runtime.EngineService#deregisterActionListener(java.lang.
+     * String)
+     */
+    @Override
+    public void deregisterActionListener(final String listenerName) {
+        // Sanity checks on the Apex model
+        if (engine == null) {
+            LOGGER.warn("listener deregistration on engine with key " + engineWorkerKey.getID()
+                    + ", failed, listener is null");
+            return;
+        }
+
+        engine.removeEventListener(listenerName);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.runtime.EngineService#getEngineServiceEventInterface()
+     */
+    @Override
+    public EngineServiceEventInterface getEngineServiceEventInterface() {
+        throw new UnsupportedOperationException(
+                "getEngineServiceEventInterface() call is not allowed on an Apex Engine Worker");
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.engine.runtime.EngineService#getKey()
+     */
+    @Override
+    public AxArtifactKey getKey() {
+        return engineWorkerKey;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.engine.runtime.EngineService#getInfo()
+     */
+    @Override
+    public Collection<AxArtifactKey> getEngineKeys() {
+        return Arrays.asList(engineWorkerKey);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.engine.runtime.EngineService#getApexModelKey()
+     */
+    @Override
+    public AxArtifactKey getApexModelKey() {
+        if (ModelService.existsModel(AxPolicyModel.class)) {
+            return ModelService.getModel(AxPolicyModel.class).getKey();
+        } else {
+            return null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.runtime.EngineService#updateModel(org.onap.policy.apex.
+     * model. basicmodel.concepts.AxArtifactKey, java.lang.String, boolean)
+     */
+    @Override
+    public void updateModel(final AxArtifactKey engineKey, final String engineModel, final boolean forceFlag)
+            throws ApexException {
+        LOGGER.entry(engineKey);
+
+        // Read the Apex model into memory using the Apex Model Reader
+        AxPolicyModel apexPolicyModel = null;
+        try {
+            final ApexModelReader<AxPolicyModel> modelReader = new ApexModelReader<>(AxPolicyModel.class);
+            apexPolicyModel = modelReader.read(new ByteArrayInputStream(engineModel.getBytes()));
+        } catch (final ApexModelException e) {
+            LOGGER.error("failed to unmarshal the apex model on engine " + engineKey.getID(), e);
+            throw new ApexException("failed to unmarshal the apex model on engine " + engineKey.getID(), e);
+        }
+
+        if (apexPolicyModel == null) {
+            LOGGER.error("apex model null on engine " + engineKey.getID());
+            throw new ApexException("apex model null on engine " + engineKey.getID());
+        }
+
+        // Update the Apex model in the Apex engine
+        updateModel(engineKey, apexPolicyModel, forceFlag);
+
+        LOGGER.exit();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.runtime.EngineService#updateModel(org.onap.policy.apex.
+     * model. basicmodel.concepts.AxArtifactKey,
+     * org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel, boolean)
+     */
+    @Override
+    public void updateModel(final AxArtifactKey engineKey, final AxPolicyModel apexModel, final boolean forceFlag)
+            throws ApexException {
+        LOGGER.entry(engineKey);
+
+        // Check if the key on the update request is correct
+        if (!engineWorkerKey.equals(engineKey)) {
+            LOGGER.warn("engine key " + engineKey.getID() + " does not match the key" + engineWorkerKey.getID()
+                    + " of this engine");
+            throw new ApexException("engine key " + engineKey.getID() + " does not match the key"
+                    + engineWorkerKey.getID() + " of this engine");
+        }
+
+        // Sanity checks on the Apex model
+        if (engine == null) {
+            LOGGER.warn("engine with key " + engineKey.getID() + " not initialized");
+            throw new ApexException("engine with key " + engineKey.getID() + " not initialized");
+        }
+
+        // Check model compatibility
+        if (ModelService.existsModel(AxPolicyModel.class)) {
+            // The current policy model may or may not be defined
+            final AxPolicyModel currentModel = ModelService.getModel(AxPolicyModel.class);
+            if (!currentModel.getKey().isCompatible(apexModel.getKey())) {
+                if (forceFlag) {
+                    LOGGER.warn("apex model update forced, supplied model with key \"" + apexModel.getKey().getID()
+                            + "\" is not a compatible model update from the existing engine model with key \""
+                            + currentModel.getKey().getID() + "\"");
+                } else {
+                    throw new ContextException(
+                            "apex model update failed, supplied model with key \"" + apexModel.getKey().getID()
+                                    + "\" is not a compatible model update from the existing engine model with key \""
+                                    + currentModel.getKey().getID() + "\"");
+                }
+            }
+        }
+
+        // Update the Apex model in the Apex engine
+        engine.updateModel(apexModel);
+
+        LOGGER.debug("engine model {} added to the engine-{}", apexModel.getKey().getID(), engineWorkerKey);
+        LOGGER.exit();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.engine.runtime.EngineService#getState()
+     */
+    @Override
+    public AxEngineState getState() {
+        return engine.getState();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.engine.runtime.EngineService#startAll()
+     */
+    @Override
+    public void startAll() throws ApexException {
+        start(this.getKey());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.runtime.EngineService#start(org.onap.policy.apex.core.
+     * model. concepts.AxArtifactKey)
+     */
+    @Override
+    public void start(final AxArtifactKey engineKey) throws ApexException {
+        LOGGER.entry(engineKey);
+
+        // Check if the key on the start request is correct
+        if (!engineWorkerKey.equals(engineKey)) {
+            LOGGER.warn("engine key " + engineKey.getID() + " does not match the key" + engineWorkerKey.getID()
+                    + " of this engine");
+            throw new ApexException("engine key " + engineKey.getID() + " does not match the key"
+                    + engineWorkerKey.getID() + " of this engine");
+        }
+
+        if (engine == null) {
+            LOGGER.error("apex engine for engine key" + engineWorkerKey.getID() + " null");
+            throw new ApexException("apex engine for engine key" + engineWorkerKey.getID() + " null");
+        }
+
+        // Starts the event processing thread that handles incoming events
+        if (processorThread != null && processorThread.isAlive()) {
+            LOGGER.error("apex engine for engine key" + engineWorkerKey.getID() + " is already running with state "
+                    + getState());
+            throw new ApexException("apex engine for engine key" + engineWorkerKey.getID()
+                    + " is already running with state " + getState());
+        }
+
+        // Start the engine
+        engine.start();
+
+        // Start a thread to process events for the engine
+        processorThread = threadFactory.newThread(processor);
+        processorThread.start();
+
+        LOGGER.exit(engineKey);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.engine.runtime.EngineService#stop()
+     */
+    @Override
+    public void stop() throws ApexException {
+        stop(this.getKey());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.runtime.EngineService#stop(org.onap.policy.apex.core.
+     * model. concepts.AxArtifactKey)
+     */
+    @Override
+    public void stop(final AxArtifactKey engineKey) throws ApexException {
+        // Check if the key on the start request is correct
+        if (!engineWorkerKey.equals(engineKey)) {
+            LOGGER.warn("engine key " + engineKey.getID() + " does not match the key" + engineWorkerKey.getID()
+                    + " of this engine");
+            throw new ApexException("engine key " + engineKey.getID() + " does not match the key"
+                    + engineWorkerKey.getID() + " of this engine");
+        }
+
+        if (engine == null) {
+            LOGGER.error("apex engine for engine key" + engineWorkerKey.getID() + " null");
+            throw new ApexException("apex engine for engine key" + engineWorkerKey.getID() + " null");
+        }
+
+        // Interrupt the worker to stop its thread
+        if (processorThread == null || !processorThread.isAlive()) {
+            processorThread = null;
+
+            LOGGER.warn("apex engine for engine key" + engineWorkerKey.getID() + " is already stopped with state "
+                    + getState());
+            return;
+        }
+
+        // Interrupt the thread that is handling events toward the engine
+        processorThread.interrupt();
+
+        // Stop the engine
+        engine.stop();
+
+        LOGGER.exit(engineKey);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.engine.runtime.EngineService#isStarted()
+     */
+    @Override
+    public boolean isStarted() {
+        return isStarted(this.getKey());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.runtime.EngineService#isStarted(org.onap.policy.apex.
+     * model. basicmodel.concepts.AxArtifactKey)
+     */
+    @Override
+    public boolean isStarted(final AxArtifactKey engineKey) {
+        final AxEngineState engstate = getState();
+        switch (engstate) {
+            case STOPPED:
+            case STOPPING:
+            case UNDEFINED:
+                return false;
+            case EXECUTING:
+            case READY:
+                return processorThread != null && processorThread.isAlive() && !processorThread.isInterrupted();
+            default:
+                break;
+        }
+        return false;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.engine.runtime.EngineService#isStopped()
+     */
+    @Override
+    public boolean isStopped() {
+        return isStopped(this.getKey());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.runtime.EngineService#isStopped(org.onap.policy.apex.
+     * model. basicmodel.concepts.AxArtifactKey)
+     */
+    @Override
+    public boolean isStopped(final AxArtifactKey engineKey) {
+        final AxEngineState engstate = getState();
+        switch (engstate) {
+            case STOPPING:
+            case UNDEFINED:
+            case EXECUTING:
+            case READY:
+                return false;
+            case STOPPED:
+                return processorThread == null || !processorThread.isAlive();
+            default:
+                break;
+        }
+        return false;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.engine.runtime.EngineService#startPeriodicEvents(long)
+     */
+    @Override
+    public void startPeriodicEvents(final long period) {
+        throw new UnsupportedOperationException("startPeriodicEvents() call is not allowed on an Apex Engine Worker");
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.engine.runtime.EngineService#stopPeriodicEvents()
+     */
+    @Override
+    public void stopPeriodicEvents() {
+        throw new UnsupportedOperationException("stopPeriodicEvents() call is not allowed on an Apex Engine Worker");
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.runtime.EngineService#getStatus(org.onap.policy.apex.core
+     * .model .concepts.AxArtifactKey)
+     */
+    @Override
+    public String getStatus(final AxArtifactKey engineKey) {
+        // Get the information from the engine that we want to return
+        final AxEngineModel apexEngineModel = engine.getEngineStatus();
+        apexEngineModel.getKeyInformation().generateKeyInfo(apexEngineModel);
+
+        // Convert that information into a string
+        try {
+            final ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
+            final ApexModelWriter<AxEngineModel> modelWriter = new ApexModelWriter<>(AxEngineModel.class);
+            modelWriter.write(apexEngineModel, baOutputStream);
+            return baOutputStream.toString();
+        } catch (final Exception e) {
+            LOGGER.warn("error outputting runtime information for engine {}", engineWorkerKey, e);
+            return null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.service.engine.runtime.EngineService#getRuntimeInfo(org.onap.policy.apex
+     * .core.model.concepts.AxArtifactKey)
+     */
+    @Override
+    public String getRuntimeInfo(final AxArtifactKey engineKey) {
+        // We'll build up the JSON string for runtime information bit by bit
+        final StringBuilder runtimeJsonStringBuilder = new StringBuilder();
+
+        // Get the engine information
+        final AxEngineModel engineModel = engine.getEngineStatus();
+        final Map<AxArtifactKey, Map<String, Object>> engineContextAlbums = engine.getEngineContext();
+
+        // Use GSON to convert our context information into JSON
+        final Gson gson = new GsonBuilder().setPrettyPrinting().create();
+
+        // Get context into a JSON string
+        runtimeJsonStringBuilder.append("{\"TimeStamp\":");
+        runtimeJsonStringBuilder.append(engineModel.getTimestamp());
+        runtimeJsonStringBuilder.append(",\"State\":");
+        runtimeJsonStringBuilder.append(engineModel.getState());
+        runtimeJsonStringBuilder.append(",\"Stats\":");
+        runtimeJsonStringBuilder.append(gson.toJson(engineModel.getStats()));
+
+        // Get context into a JSON string
+        runtimeJsonStringBuilder.append(",\"ContextAlbums\":[");
+
+        boolean firstAlbum = true;
+        for (final Entry<AxArtifactKey, Map<String, Object>> contextAlbumEntry : engineContextAlbums.entrySet()) {
+            if (firstAlbum) {
+                firstAlbum = false;
+            } else {
+                runtimeJsonStringBuilder.append(",");
+            }
+
+            runtimeJsonStringBuilder.append("{\"AlbumKey\":");
+            runtimeJsonStringBuilder.append(gson.toJson(contextAlbumEntry.getKey()));
+            runtimeJsonStringBuilder.append(",\"AlbumContent\":[");
+
+
+            // Get the schema helper to use to marshal context album objects to JSON
+            final AxContextAlbum axContextAlbum =
+                    ModelService.getModel(AxContextAlbums.class).get(contextAlbumEntry.getKey());
+            SchemaHelper schemaHelper = null;
+
+            try {
+                // Get a schema helper to manage the translations between objects on the album map
+                // for this album
+                schemaHelper = new SchemaHelperFactory().createSchemaHelper(axContextAlbum.getKey(),
+                        axContextAlbum.getItemSchema());
+            } catch (final ContextRuntimeException e) {
+                final String resultString =
+                        "could not find schema helper to marshal context album \"" + axContextAlbum + "\" to JSON";
+                LOGGER.warn(resultString, e);
+
+                // End of context album entry
+                runtimeJsonStringBuilder.append(resultString);
+                runtimeJsonStringBuilder.append("]}");
+
+                continue;
+            }
+
+            boolean firstEntry = true;
+            for (final Entry<String, Object> contextEntry : contextAlbumEntry.getValue().entrySet()) {
+                if (firstEntry) {
+                    firstEntry = false;
+                } else {
+                    runtimeJsonStringBuilder.append(",");
+                }
+                runtimeJsonStringBuilder.append("{\"EntryName\":");
+                runtimeJsonStringBuilder.append(gson.toJson(contextEntry.getKey()));
+                runtimeJsonStringBuilder.append(",\"EntryContent\":");
+                runtimeJsonStringBuilder.append(gson.toJson(schemaHelper.marshal2Json(contextEntry.getValue())));
+
+                // End of context entry
+                runtimeJsonStringBuilder.append("}");
+            }
+
+            // End of context album entry
+            runtimeJsonStringBuilder.append("]}");
+        }
+
+        runtimeJsonStringBuilder.append("]}");
+
+        // Tidy up the JSON string
+        final JsonParser jsonParser = new JsonParser();
+        final JsonElement jsonElement = jsonParser.parse(runtimeJsonStringBuilder.toString());
+        final String tidiedRuntimeString = gson.toJson(jsonElement);
+
+        LOGGER.debug("runtime information=" + tidiedRuntimeString);
+
+        return tidiedRuntimeString;
+    }
+
+    /**
+     * This is an event processor thread, this class decouples the events handling logic from core
+     * business logic. This class runs its own thread and continuously querying the blocking queue
+     * for the events that have been sent to the worker for processing by the Apex engine.
+     *
+     * @author Liam Fallon (liam.fallon@ericsson.com)
+     */
+    private class EventProcessor implements Runnable {
+        private final boolean debugEnabled = LOGGER.isDebugEnabled();
+        // the events queue
+        private BlockingQueue<ApexEvent> eventProcessingQueue = null;
+
+        /**
+         * Constructor accepts {@link ApexEngine} and {@link BlockingQueue} type objects.
+         *
+         * @param eventProcessingQueue is reference of {@link BlockingQueue} which contains trigger
+         *        events.
+         */
+        EventProcessor(final BlockingQueue<ApexEvent> eventProcessingQueue) {
+            this.eventProcessingQueue = eventProcessingQueue;
+        }
+
+        /*
+         * (non-Javadoc)
+         *
+         * @see java.lang.Runnable#run()
+         */
+        @Override
+        public void run() {
+            LOGGER.debug("Engine {} processing ... ", engineWorkerKey);
+
+            // Take events from the event processing queue of the worker and pass them to the engine
+            // for processing
+            while (!processorThread.isInterrupted()) {
+                ApexEvent event = null;
+                try {
+                    event = eventProcessingQueue.take();
+                } catch (final InterruptedException e) {
+                    LOGGER.debug("Engine {} processing interrupted ", engineWorkerKey);
+                    break;
+                }
+
+                try {
+                    if (event != null) {
+                        if (debugEnabled) {
+                            LOGGER.debug("Trigger Event {} forwarded to the Apex engine", event);
+                        }
+                        final EnEvent enevent = apexEnEventConverter.fromApexEvent(event);
+                        engine.handleEvent(enevent);
+                    }
+                } catch (final ApexException e) {
+                    LOGGER.warn("Engine {} failed to process event {}", engineWorkerKey, event.toString(), e);
+                } catch (final Exception e) {
+                    LOGGER.warn("Engine {} terminated processing event {}", engineWorkerKey, event.toString(), e);
+                    break;
+                }
+            }
+            LOGGER.debug("Engine {} completed processing", engineWorkerKey);
+        }
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/impl/package-info.java
new file mode 100644 (file)
index 0000000..b0acca8
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Provides the implementation of the APEX engine runtime interfaces. It uses the APEX core engine
+ * as its implementation.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.runtime.impl;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/engine/runtime/package-info.java
new file mode 100644 (file)
index 0000000..b54a903
--- /dev/null
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Provides Java APIs for APEX engines at runtime. The {@link EngineService} is used to start, stop
+ * and manage APEX engines. {@link EngineServiceEventInterface} is used to send events to an APEX
+ * engine. {@link ApexEventListener} interface is used to receive events from an APEX engine.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.engine.runtime;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterException.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterException.java
new file mode 100644 (file)
index 0000000..229250b
--- /dev/null
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+
+/**
+ * This exception will be called if an error occurs in Apex parameter handling.
+ *
+ * @author Liam Fallon
+ */
+public class ApexParameterException extends ApexException {
+    private static final long serialVersionUID = -8507246953751956974L;
+
+    /**
+     * Instantiates a new apex parameter handling exception with a message.
+     *
+     * @param message the message
+     */
+    public ApexParameterException(final String message) {
+        super(message);
+    }
+
+    /**
+     * Instantiates a new apex parameter handling exception with a message and a caused by
+     * exception.
+     *
+     * @param message the message
+     * @param e the exception that caused this exception to be thrown
+     */
+    public ApexParameterException(final String message, final Exception e) {
+        super(message, e);
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterHandler.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterHandler.java
new file mode 100644 (file)
index 0000000..79f10bd
--- /dev/null
@@ -0,0 +1,100 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters;
+
+import java.io.FileReader;
+
+import org.onap.policy.apex.core.engine.EngineParameters;
+import org.onap.policy.apex.service.engine.main.ApexCommandLineArguments;
+import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters;
+import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParametersJSONAdapter;
+import org.onap.policy.apex.service.parameters.engineservice.EngineServiceParametersJSONAdapter;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParametersJSONAdapter;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * This class handles reading, parsing and validating of Apex parameters from JSON files.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ApexParameterHandler {
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexParameterHandler.class);
+
+    /**
+     * Read the parameters from the parameter file.
+     *
+     * @param arguments the arguments passed to Apex
+     * @return the parameters read from the configuration file
+     * @throws ApexParameterException on parameter exceptions
+     */
+    public ApexParameters getParameters(final ApexCommandLineArguments arguments) throws ApexParameterException {
+        ApexParameters parameters = null;
+
+        // Read the parameters
+        try {
+            // Register the adapters for our carrier technologies and event protocols with GSON
+            // @formatter:off
+            final Gson gson = new GsonBuilder()
+                    .registerTypeAdapter(EngineParameters           .class, new EngineServiceParametersJSONAdapter())
+                    .registerTypeAdapter(CarrierTechnologyParameters.class, new CarrierTechnologyParametersJSONAdapter())
+                    .registerTypeAdapter(EventProtocolParameters    .class, new EventProtocolParametersJSONAdapter())
+                    .create();
+            // @formatter:on
+            parameters = gson.fromJson(new FileReader(arguments.getFullConfigurationFilePath()), ApexParameters.class);
+        } catch (final Exception e) {
+            final String errorMessage = "error reading parameters from \"" + arguments.getConfigurationFilePath()
+                    + "\"\n" + "(" + e.getClass().getSimpleName() + "):" + e.getMessage();
+            LOGGER.error(errorMessage, e);
+            throw new ApexParameterException(errorMessage, e);
+        }
+
+        // The JSON processing returns null if there is an empty file
+        if (parameters == null) {
+            final String errorMessage = "no parameters found in \"" + arguments.getConfigurationFilePath() + "\"";
+            LOGGER.error(errorMessage);
+            throw new ApexParameterException(errorMessage);
+        }
+
+        // Check if we should override the model file parameter
+        final String modelFilePath = arguments.getModelFilePath();
+        if (modelFilePath != null && modelFilePath.replaceAll("\\s+", "").length() > 0) {
+            parameters.getEngineServiceParameters().setPolicyModelFileName(modelFilePath);
+        }
+
+        // validate the parameters
+        final String validationResult = parameters.validate();
+        if (!validationResult.isEmpty()) {
+            String returnMessage =
+                    "validation error(s) on parameters from \"" + arguments.getConfigurationFilePath() + "\"\n";
+            returnMessage += validationResult;
+
+            LOGGER.error(returnMessage);
+            throw new ApexParameterException(returnMessage);
+        }
+
+        return parameters;
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterRuntimeException.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterRuntimeException.java
new file mode 100644 (file)
index 0000000..2334a7e
--- /dev/null
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException;
+
+/**
+ * This exception will be called if an error occurs in Apex parameter handling.
+ *
+ * @author Liam Fallon
+ */
+public class ApexParameterRuntimeException extends ApexRuntimeException {
+    private static final long serialVersionUID = -8507246953751956974L;
+
+    /**
+     * Instantiates a new apex parameter handling exception with a message.
+     *
+     * @param message the message
+     */
+    public ApexParameterRuntimeException(final String message) {
+        super(message);
+    }
+
+    /**
+     * Instantiates a new apex parameter handling exception with a message and a caused by
+     * exception.
+     *
+     * @param message the message
+     * @param e the exception that caused this exception to be thrown
+     */
+    public ApexParameterRuntimeException(final String message, final Exception e) {
+        super(message, e);
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterValidator.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameterValidator.java
new file mode 100644 (file)
index 0000000..a8cbe3b
--- /dev/null
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters;
+
+/**
+ * This interface is implemented by Apex parameter classes so that they can be validated.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public interface ApexParameterValidator {
+    /**
+     * Validate a parameter java bean, if the parameter bean is valid, an empty string is returned,
+     * otherwise the string gives details of the invalid parameters.
+     *
+     * @return the string with validation errors
+     */
+    String validate();
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameters.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/ApexParameters.java
new file mode 100644 (file)
index 0000000..52c6f49
--- /dev/null
@@ -0,0 +1,357 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.onap.policy.apex.context.parameters.ContextParameters;
+import org.onap.policy.apex.model.basicmodel.service.AbstractParameters;
+import org.onap.policy.apex.model.basicmodel.service.ParameterService;
+import org.onap.policy.apex.service.parameters.engineservice.EngineServiceParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+
+/**
+ * The main container parameter class for an Apex service.
+ * <p>
+ * The following parameters are defined:
+ * <ol>
+ * <li>engineServiceParameters: The parameters for the Apex engine service itself, such as the
+ * number of engine threads to run and the deployment port number to use.
+ * <li>eventOutputParameters: A map of parameters for event outputs that Apex will use to emit
+ * events. Apex emits events on all outputs
+ * <li>eventInputParameters: A map or parameters for event inputs from which Apex will consume
+ * events. Apex reads events from all its event inputs.
+ * <li>synchronousEventHandlerParameters: A map of parameters for synchronous event handlers That
+ * Apex receives events from and replies immediately to those events.
+ * </ol>
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ApexParameters extends AbstractParameters implements ApexParameterValidator {
+    /**
+     * Constructor to create an apex parameters instance and register the instance with the
+     * parameter service.
+     */
+    public ApexParameters() {
+        super(ContextParameters.class.getCanonicalName());
+        ParameterService.registerParameters(ApexParameters.class, this);
+    }
+
+    // Parameters for the engine service and the engine threads in the engine service
+    private EngineServiceParameters engineServiceParameters;
+
+    // Parameters for the event outputs that Apex will use to send events on its outputs
+    private Map<String, EventHandlerParameters> eventOutputParameters = new LinkedHashMap<>();
+
+    // Parameters for the event inputs that Apex will use to receive events on its inputs
+    private Map<String, EventHandlerParameters> eventInputParameters = new LinkedHashMap<>();
+
+    /**
+     * Gets the parameters for the Apex engine service.
+     *
+     * @return the engine service parameters
+     */
+    public EngineServiceParameters getEngineServiceParameters() {
+        return engineServiceParameters;
+    }
+
+    /**
+     * Sets the engine service parameters.
+     *
+     * @param engineServiceParameters the engine service parameters
+     */
+    public void setEngineServiceParameters(final EngineServiceParameters engineServiceParameters) {
+        this.engineServiceParameters = engineServiceParameters;
+    }
+
+    /**
+     * Gets the event output parameter map.
+     *
+     * @return the parameters for all event outputs
+     */
+    public Map<String, EventHandlerParameters> getEventOutputParameters() {
+        return eventOutputParameters;
+    }
+
+    /**
+     * Sets the event output parameters.
+     *
+     * @param eventOutputParameters the event outputs parameters
+     */
+    public void setEventOutputParameters(final Map<String, EventHandlerParameters> eventOutputParameters) {
+        this.eventOutputParameters = eventOutputParameters;
+    }
+
+    /**
+     * Gets the event input parameter map.
+     *
+     * @return the parameters for all event inputs
+     */
+    public Map<String, EventHandlerParameters> getEventInputParameters() {
+        return eventInputParameters;
+    }
+
+    /**
+     * Sets the event input parameters.
+     *
+     * @param eventInputParameters the event input parameters
+     */
+    public void setEventInputParameters(final Map<String, EventHandlerParameters> eventInputParameters) {
+        this.eventInputParameters = eventInputParameters;
+    }
+
+    /**
+     * This method formats a validation result with a header if the result is not empty.
+     *
+     * @param validationResultMessage The incoming message
+     * @param heading The heading to prepend on the message
+     * @return the formatted message
+     */
+    private String validationResultFormatter(final String validationResultMessage, final String heading) {
+        final StringBuilder errorMessageBuilder = new StringBuilder();
+
+        if (validationResultMessage.length() > 0) {
+            errorMessageBuilder.append(heading);
+            errorMessageBuilder.append(validationResultMessage);
+        }
+
+        return errorMessageBuilder.toString();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.apps.uservice.parameters.ApexParameterValidator#validate()
+     */
+    @Override
+    public String validate() {
+        final StringBuilder errorMessageBuilder = new StringBuilder();
+
+        if (engineServiceParameters == null) {
+            errorMessageBuilder.append(" engine service parameters are not specified\n");
+        } else {
+            errorMessageBuilder.append(validationResultFormatter(engineServiceParameters.validate(),
+                    " engine service parameters invalid\n"));
+        }
+
+        // Sanity check, we must have an entry in both output and input maps
+        if (eventOutputParameters.isEmpty() || eventInputParameters.isEmpty()) {
+            errorMessageBuilder.append(" at least one event output and one event input must be specified\n");
+        }
+
+        // Validate that the values of all parameters are ok
+        validateEventHandlerMap("event input", errorMessageBuilder, eventInputParameters);
+        validateEventHandlerMap("event output", errorMessageBuilder, eventOutputParameters);
+
+        // Only do peer mode validate if there are no other errors
+        if (errorMessageBuilder.length() == 0) {
+            for (final EventHandlerPeeredMode peeredMode : EventHandlerPeeredMode.values()) {
+                validatePeeredMode(errorMessageBuilder, peeredMode);
+            }
+        }
+
+        // Check if we have any errors
+        if (errorMessageBuilder.length() > 0) {
+            errorMessageBuilder.insert(0, "Apex parameters invalid\n");
+        }
+
+        return errorMessageBuilder.toString().trim();
+    }
+
+    /**
+     * This method validates the parameters in an event handler map.
+     * 
+     * @param eventHandlerType the type of the event handler to use on error messages
+     * @param errorMessageBuilder the builder to use to return validation messages
+     * @param parsForValidation The event handler parameters to validate (input or output)
+     */
+    // CHECKSTYLE:OFF: checkstyle:finalParameter
+    private void validateEventHandlerMap(final String eventHandlerType, final StringBuilder errorMessageBuilder,
+            final Map<String, EventHandlerParameters> parsForValidation) {
+        // CHECKSTYLE:ON: checkstyle:finalParameter
+        for (final Entry<String, EventHandlerParameters> parameterEntry : parsForValidation.entrySet()) {
+            if (parameterEntry.getKey() == null || parameterEntry.getKey().trim().isEmpty()) {
+                errorMessageBuilder
+                        .append(" invalid " + eventHandlerType + " name \"" + parameterEntry.getKey() + "\" \n");
+            } else if (parameterEntry.getValue() == null) {
+                errorMessageBuilder.append(" invalid/Null event input prameters specified for " + eventHandlerType
+                        + " name \"" + parameterEntry.getKey() + "\" \n");
+            } else {
+                errorMessageBuilder.append(validationResultFormatter(parameterEntry.getValue().validate(),
+                        " " + eventHandlerType + " (" + parameterEntry.getKey() + ") parameters invalid\n"));
+            }
+
+            parameterEntry.getValue().setName(parameterEntry.getKey());
+
+            // Validate parameters for peered mode settings
+            for (final EventHandlerPeeredMode peeredMode : EventHandlerPeeredMode.values()) {
+                validatePeeredModeParameters(eventHandlerType, errorMessageBuilder, parameterEntry, peeredMode);
+            }
+        }
+    }
+
+    /**
+     * Validate parameter values for event handlers in a peered mode
+     * 
+     * @param eventHandlerType The event handler type we are checking
+     * @param errorMessageBuilder The builder to which to append any error messages
+     * @param parameterEntry The entry to check the peered mode on
+     * @param peeredMode The mode to check
+     */
+    private void validatePeeredModeParameters(final String eventHandlerType, final StringBuilder errorMessageBuilder,
+            final Entry<String, EventHandlerParameters> parameterEntry, final EventHandlerPeeredMode peeredMode) {
+        final String messagePreamble = " specified peered mode \"" + peeredMode + "\"";
+        final String peer = parameterEntry.getValue().getPeer(peeredMode);
+
+        if (parameterEntry.getValue().isPeeredMode(peeredMode)) {
+            if (peer == null || peer.trim().isEmpty()) {
+                errorMessageBuilder.append(messagePreamble + " mandatory parameter not specified or is null on "
+                        + eventHandlerType + " \"" + parameterEntry.getKey() + "\" \n");
+            }
+            if (parameterEntry.getValue().getPeerTimeout(peeredMode) < 0) {
+                errorMessageBuilder.append(
+                        messagePreamble + " timeout value \"" + parameterEntry.getValue().getPeerTimeout(peeredMode)
+                                + "\" is illegal on " + eventHandlerType + " \"" + parameterEntry.getKey()
+                                + "\", specify a non-negative timeout value in milliseconds\n");
+            }
+        } else {
+            if (peer != null) {
+                errorMessageBuilder.append(messagePreamble + " peer is illegal on non synchronous " + eventHandlerType
+                        + " \"" + parameterEntry.getKey() + "\" \n");
+            }
+            if (parameterEntry.getValue().getPeerTimeout(peeredMode) != 0) {
+                errorMessageBuilder.append(messagePreamble + " timeout is illegal on non synchronous "
+                        + eventHandlerType + " \"" + parameterEntry.getKey() + "\" \n");
+            }
+        }
+    }
+
+    /**
+     * This method validates that the settings are valid for the given peered mode
+     * 
+     * @param errorMessageBuilder The builder to which to append any error messages
+     * @param peeredMode The peered mode to check
+     */
+    private void validatePeeredMode(final StringBuilder errorMessageBuilder, final EventHandlerPeeredMode peeredMode) {
+        // Find the input and output event handlers that use this peered mode
+        final Map<String, EventHandlerParameters> inputParametersUsingMode = new HashMap<>();
+        final Map<String, EventHandlerParameters> outputParametersUsingMode = new HashMap<>();
+
+        // Find input and output parameters using this mode
+        for (final Entry<String, EventHandlerParameters> inputParameterEntry : eventInputParameters.entrySet()) {
+            if (inputParameterEntry.getValue().isPeeredMode(peeredMode)) {
+                inputParametersUsingMode.put(inputParameterEntry.getKey(), inputParameterEntry.getValue());
+            }
+        }
+        for (final Entry<String, EventHandlerParameters> outputParameterEntry : eventOutputParameters.entrySet()) {
+            if (outputParameterEntry.getValue().isPeeredMode(peeredMode)) {
+                outputParametersUsingMode.put(outputParameterEntry.getKey(), outputParameterEntry.getValue());
+            }
+        }
+
+        // Validate the parameters for each side of the peered mode parameters
+        validatePeeredModePeers(" event input for peered mode \"" + peeredMode + "\": ", errorMessageBuilder,
+                peeredMode, inputParametersUsingMode, outputParametersUsingMode);
+        validatePeeredModePeers(" event output for peered mode \"" + peeredMode + "\": ", errorMessageBuilder,
+                peeredMode, outputParametersUsingMode, inputParametersUsingMode);
+    }
+
+    /**
+     * This method validates that the settings are valid for the event handlers on one
+     * 
+     * @param messagePreamble the preamble for messages indicating the peered mode side
+     * @param errorMessageBuilder The builder to which to append any error messages
+     * @param leftModeParameters The mode parameters being checked
+     * @param rightModeParameters The mode parameters being referenced by the checked parameters
+     */
+    private void validatePeeredModePeers(final String messagePreamble, final StringBuilder errorMessageBuilder,
+            final EventHandlerPeeredMode peeredMode, final Map<String, EventHandlerParameters> leftModeParameterMap,
+            final Map<String, EventHandlerParameters> rightModeParameterMap) {
+
+        // These sets are used to check for duplicate references on the both sides
+        final Set<String> leftCheckDuplicateSet = new HashSet<>();
+        final Set<String> rightCheckDuplicateSet = new HashSet<>();
+
+        // Check for missing peers, all peers are set because we have checked them previously so no
+        // need for null checks
+        for (final Entry<String, EventHandlerParameters> leftModeParameterEntry : leftModeParameterMap.entrySet()) {
+            final String leftSidePeer = leftModeParameterEntry.getValue().getPeer(peeredMode);
+
+            final EventHandlerParameters leftModeParameters = leftModeParameterEntry.getValue();
+            final EventHandlerParameters rightModeParameters = rightModeParameterMap.get(leftSidePeer);
+
+            // Check that the peer reference is OK
+            if (rightModeParameters == null) {
+                errorMessageBuilder.append(messagePreamble + "peer \"" + leftModeParameters.getPeer(peeredMode)
+                        + "\" for event handler \"" + leftModeParameterEntry.getKey()
+                        + "\" does not exist or is not defined as being synchronous\n");
+                continue;
+            }
+
+            // Now check that the right side peer is the left side event handler
+            final String rightSidePeer = rightModeParameters.getPeer(peeredMode);
+            if (!rightSidePeer.equals(leftModeParameterEntry.getKey())) {
+                errorMessageBuilder
+                        .append(messagePreamble + "peer value \"" + rightSidePeer + "\" on peer \"" + leftSidePeer
+                                + "\" does not equal event handler \"" + leftModeParameterEntry.getKey() + "\"\n");
+            } else {
+                // Check for duplicates
+                if (!leftCheckDuplicateSet.add(leftSidePeer)) {
+                    errorMessageBuilder
+                            .append(messagePreamble + "peer value \"" + leftSidePeer + "\" on event handler \""
+                                    + leftModeParameterEntry.getKey() + "\" is used more than once\n");
+                }
+                if (!rightCheckDuplicateSet.add(rightSidePeer)) {
+                    errorMessageBuilder.append(messagePreamble + "peer value \"" + rightSidePeer + "\" on peer \""
+                            + leftSidePeer + "\" on event handler \"" + leftModeParameterEntry.getKey()
+                            + "\" is used more than once\n");
+                }
+            }
+
+            // Cross-set the timeouts if they are not specified
+            if (leftModeParameters.getPeerTimeout(peeredMode) != 0) {
+                if (rightModeParameters.getPeerTimeout(peeredMode) != 0) {
+                    if (leftModeParameters.getPeerTimeout(peeredMode) != rightModeParameters
+                            .getPeerTimeout(peeredMode)) {
+                        errorMessageBuilder.append(messagePreamble + "timeout "
+                                + leftModeParameters.getPeerTimeout(peeredMode) + "on event handler \""
+                                + leftModeParameters.getName() + "\" does not equal timeout value "
+                                + rightModeParameters.getPeerTimeout(peeredMode) + "on event handler \""
+                                + rightModeParameters.getName() + "\"\n");
+                    }
+                } else {
+                    rightModeParameters.setPeerTimeout(peeredMode, leftModeParameters.getPeerTimeout(peeredMode));
+                }
+            } else {
+                if (rightModeParameters.getPeerTimeout(peeredMode) != 0) {
+                    leftModeParameters.setPeerTimeout(peeredMode, rightModeParameters.getPeerTimeout(peeredMode));
+                }
+            }
+        }
+
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/carriertechnology/CarrierTechnologyParameters.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/carriertechnology/CarrierTechnologyParameters.java
new file mode 100644 (file)
index 0000000..ba0327d
--- /dev/null
@@ -0,0 +1,161 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters.carriertechnology;
+
+import org.onap.policy.apex.model.basicmodel.service.AbstractParameters;
+import org.onap.policy.apex.service.parameters.ApexParameterValidator;
+
+/**
+ * The default carrier technology parameter class that may be specialized by carrier technology
+ * plugins that require plugin specific parameters.
+ * <p>
+ * The following parameters are defined:
+ * <ol>
+ * <li>label: The label of the carrier technology.
+ * <li>eventProducerPluginClass: The name of the plugin class that will be used by Apex to produce
+ * and emit output events for this carrier technology
+ * <li>eventConsumerPluginClass: The name of the plugin class that will be used by Apex to receive
+ * and process input events from this carrier technology carrier technology
+ * </ol>
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public abstract class CarrierTechnologyParameters extends AbstractParameters implements ApexParameterValidator {
+
+    // The carrier technology label
+    private String label = null;
+
+    // Producer and Consumer plugin classes for the event producer and consumer for this carrier
+    // technology
+    private String eventProducerPluginClass = null;
+    private String eventConsumerPluginClass = null;
+
+    /**
+     * Constructor to create a carrier technology parameters instance with the name of a sub class
+     * of this class and register the instance with the parameter service.
+     *
+     * @param parameterClassName the class name of a sub class of this class
+     */
+    public CarrierTechnologyParameters(final String parameterClassName) {
+        super(parameterClassName);
+    }
+
+    /**
+     * Gets the label of the carrier technology.
+     *
+     * @return the label of the carrier technology
+     */
+    public String getLabel() {
+        return label;
+    }
+
+    /**
+     * Sets the label of the carrier technology.
+     *
+     * @param label the label of the carrier technology
+     */
+    public void setLabel(final String label) {
+        if (label != null) {
+            this.label = label.replaceAll("\\s+", "");
+        } else {
+            this.label = null;
+        }
+    }
+
+    /**
+     * Gets the event producer plugin class.
+     *
+     * @return the event producer plugin class
+     */
+    public String getEventProducerPluginClass() {
+        return eventProducerPluginClass;
+    }
+
+    /**
+     * Sets the event producer plugin class.
+     *
+     * @param eventProducerPluginClass the new event producer plugin class
+     */
+    public void setEventProducerPluginClass(final String eventProducerPluginClass) {
+        if (eventProducerPluginClass != null) {
+            this.eventProducerPluginClass = eventProducerPluginClass.replaceAll("\\s+", "");
+        } else {
+            this.eventProducerPluginClass = null;
+        }
+    }
+
+    /**
+     * Gets the event consumer plugin class.
+     *
+     * @return the event consumer plugin class
+     */
+    public String getEventConsumerPluginClass() {
+        return eventConsumerPluginClass;
+    }
+
+    /**
+     * Sets the event consumer plugin class.
+     *
+     * @param eventConsumerPluginClass the new event consumer plugin class
+     */
+    public void setEventConsumerPluginClass(final String eventConsumerPluginClass) {
+        if (eventConsumerPluginClass != null) {
+            this.eventConsumerPluginClass = eventConsumerPluginClass.replaceAll("\\s+", "");
+        } else {
+            this.eventConsumerPluginClass = null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "CarrierTechnologyParameters [label=" + label + ", eventProducerPluginClass=" + eventProducerPluginClass
+                + ", eventConsumerPluginClass=" + eventConsumerPluginClass + "]";
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.parameters.ApexParameterValidator#validate()
+     */
+    @Override
+    public String validate() {
+        final StringBuilder errorMessageBuilder = new StringBuilder();
+
+        if (label == null || label.length() == 0) {
+            errorMessageBuilder.append("  carrier technology label not specified or is blank\n");
+        }
+
+        if (eventProducerPluginClass == null || eventProducerPluginClass.length() == 0) {
+            errorMessageBuilder.append("  carrier technology eventProducerPluginClass not specified or is blank\n");
+        }
+
+        if (eventConsumerPluginClass == null || eventConsumerPluginClass.length() == 0) {
+            errorMessageBuilder.append("  carrier technology eventConsumerPluginClass not specified or is blank\n");
+        }
+
+        return errorMessageBuilder.toString();
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/carriertechnology/CarrierTechnologyParametersJSONAdapter.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/carriertechnology/CarrierTechnologyParametersJSONAdapter.java
new file mode 100644 (file)
index 0000000..5aa7d64
--- /dev/null
@@ -0,0 +1,176 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters.carriertechnology;
+
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onap.policy.apex.service.engine.event.impl.eventrequestor.EventRequestorCarrierTechnologyParameters;
+import org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.FILECarrierTechnologyParameters;
+import org.onap.policy.apex.service.parameters.ApexParameterRuntimeException;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+/**
+ * This class deserialises various type of carrier technology parameters from JSON.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class CarrierTechnologyParametersJSONAdapter
+        implements JsonSerializer<CarrierTechnologyParameters>, JsonDeserializer<CarrierTechnologyParameters> {
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(CarrierTechnologyParametersJSONAdapter.class);
+
+    private static final String PARAMETER_CLASS_NAME = "parameterClassName";
+
+    private static final String CARRIER_TECHNOLOGY_TOKEN = "carrierTechnology";
+    private static final String CARRIER_TECHNOLOGY_PARAMETERS = "parameters";
+
+    // Built in technology parameters
+    private static final Map<String, String> BUILT_IN_CARRIER_TECHNOLOGY_PARMETER_CLASS_MAP = new HashMap<>();
+    static {
+        BUILT_IN_CARRIER_TECHNOLOGY_PARMETER_CLASS_MAP.put("FILE",
+                FILECarrierTechnologyParameters.class.getCanonicalName());
+        BUILT_IN_CARRIER_TECHNOLOGY_PARMETER_CLASS_MAP.put("EVENT_REQUESTOR",
+                EventRequestorCarrierTechnologyParameters.class.getCanonicalName());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.google.gson.JsonSerializer#serialize(java.lang.Object, java.lang.reflect.Type,
+     * com.google.gson.JsonSerializationContext)
+     */
+    @Override
+    public JsonElement serialize(final CarrierTechnologyParameters src, final Type typeOfSrc,
+            final JsonSerializationContext context) {
+        final String returnMessage = "serialization of Apex carrier technology parameters to Json is not supported";
+        LOGGER.error(returnMessage);
+        throw new ApexParameterRuntimeException(returnMessage);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.google.gson.JsonDeserializer#deserialize(com.google.gson.JsonElement,
+     * java.lang.reflect.Type, com.google.gson.JsonDeserializationContext)
+     */
+    @Override
+    public CarrierTechnologyParameters deserialize(final JsonElement json, final Type typeOfT,
+            final JsonDeserializationContext context) throws JsonParseException {
+        final JsonObject jsonObject = json.getAsJsonObject();
+
+        // Get the carrier technology label primitive
+        final JsonPrimitive labelJsonPrimitive = (JsonPrimitive) jsonObject.get(CARRIER_TECHNOLOGY_TOKEN);
+
+        // Check if we found our carrier technology
+        if (labelJsonPrimitive == null) {
+            LOGGER.warn("carrier technology parameter \"" + CARRIER_TECHNOLOGY_TOKEN + "\" not found in JSON file");
+            return null;
+        }
+
+        // Get and check the carrier technology label
+        final String carrierTechnologyLabel = labelJsonPrimitive.getAsString().replaceAll("\\s+", "");
+        if (carrierTechnologyLabel == null || carrierTechnologyLabel.length() == 0) {
+            final String errorMessage = "carrier technology parameter \"" + CARRIER_TECHNOLOGY_TOKEN + "\" value \""
+                    + labelJsonPrimitive.getAsString() + "\" invalid in JSON file";
+            LOGGER.warn(errorMessage);
+            throw new ApexParameterRuntimeException(errorMessage);
+        }
+
+        // We now get the technology carrier parameter class
+        String carrierTechnologyParameterClassName = null;
+
+        // Get the technology carrier parameter class for the carrier technology plugin class from
+        // the configuration parameters
+        final JsonPrimitive classNameJsonPrimitive = (JsonPrimitive) jsonObject.get(PARAMETER_CLASS_NAME);
+
+        // If no technology carrier parameter class was specified, we try to use a built in carrier
+        // technology
+        if (classNameJsonPrimitive == null) {
+            carrierTechnologyParameterClassName =
+                    BUILT_IN_CARRIER_TECHNOLOGY_PARMETER_CLASS_MAP.get(carrierTechnologyLabel);
+        } else {
+            // We use the specified one
+            carrierTechnologyParameterClassName = classNameJsonPrimitive.getAsString().replaceAll("\\s+", "");
+        }
+
+        // Check the carrier technology parameter class
+        if (carrierTechnologyParameterClassName == null || carrierTechnologyParameterClassName.length() == 0) {
+            final String errorMessage =
+                    "carrier technology \"" + carrierTechnologyLabel + "\" parameter \"" + PARAMETER_CLASS_NAME
+                            + "\" value \"" + classNameJsonPrimitive.getAsString() + "\" invalid in JSON file";
+            LOGGER.warn(errorMessage);
+            throw new ApexParameterRuntimeException(errorMessage);
+        }
+
+        // Get the class for the carrier technology
+        Class<?> carrierTechnologyParameterClass = null;
+        try {
+            carrierTechnologyParameterClass = Class.forName(carrierTechnologyParameterClassName);
+        } catch (final ClassNotFoundException e) {
+            final String errorMessage =
+                    "carrier technology \"" + carrierTechnologyLabel + "\" parameter \"" + PARAMETER_CLASS_NAME
+                            + "\" value \"" + carrierTechnologyParameterClassName + "\", could not find class";
+            LOGGER.warn(errorMessage, e);
+            throw new ApexParameterRuntimeException(errorMessage, e);
+        }
+
+        // Deserialise the class
+        CarrierTechnologyParameters carrierTechnologyParameters =
+                context.deserialize(jsonObject.get(CARRIER_TECHNOLOGY_PARAMETERS), carrierTechnologyParameterClass);
+        if (carrierTechnologyParameters == null) {
+            // OK no parameters for the carrier technology have been specified, just instantiate the
+            // default parameters
+            try {
+                carrierTechnologyParameters =
+                        (CarrierTechnologyParameters) carrierTechnologyParameterClass.newInstance();
+            } catch (final Exception e) {
+                final String errorMessage = "could not create default parameters for carrier technology \""
+                        + carrierTechnologyLabel + "\"\n" + e.getMessage();
+                LOGGER.warn(errorMessage, e);
+                throw new ApexParameterRuntimeException(errorMessage, e);
+            }
+        }
+
+        // Check that the carrier technology label matches the label in the carrier technology
+        // parameters object
+        if (!carrierTechnologyParameters.getLabel().equals(carrierTechnologyLabel)) {
+            final String errorMessage = "carrier technology \"" + carrierTechnologyLabel + "\" does not match plugin \""
+                    + carrierTechnologyParameters.getLabel() + "\" in \"" + carrierTechnologyParameterClassName
+                    + "\", specify correct carrier technology parameter plugin in parameter \"" + PARAMETER_CLASS_NAME
+                    + "\"";
+            LOGGER.warn(errorMessage);
+            throw new ApexParameterRuntimeException(errorMessage);
+        }
+
+        return carrierTechnologyParameters;
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/carriertechnology/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/carriertechnology/package-info.java
new file mode 100644 (file)
index 0000000..5912c01
--- /dev/null
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Defines the structure of carrier technology parameters for APEX.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.parameters.carriertechnology;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/engineservice/EngineServiceParameters.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/engineservice/EngineServiceParameters.java
new file mode 100644 (file)
index 0000000..6b60732
--- /dev/null
@@ -0,0 +1,329 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters.engineservice;
+
+import java.io.File;
+import java.net.URL;
+
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.service.AbstractParameters;
+import org.onap.policy.apex.model.basicmodel.service.ParameterService;
+import org.onap.policy.apex.model.utilities.ResourceUtils;
+import org.onap.policy.apex.service.parameters.ApexParameterValidator;
+
+import org.onap.policy.apex.core.engine.EngineParameters;
+
+/**
+ * This class holds the parameters for an Apex Engine Service with multiple engine threads running
+ * multiple engines.
+ *
+ * <p>
+ * The following parameters are defined:
+ * <ol>
+ * <li>name: The name of the Apex engine service, which can be set to any value that matches the
+ * regular expression {@link org.onap.policy.apex.model.basicmodel.concepts.AxKey#NAME_REGEXP}.
+ * <li>version: The name of the Apex engine service, which can be set to any value that matches the
+ * regular expression {@link org.onap.policy.apex.model.basicmodel.concepts.AxKey#VERSION_REGEXP}.
+ * <li>id: The ID of the Apex engine service, which can be set to any integer value by a user.
+ * <li>instanceCount: The number of Apex engines to spawn in this engine service. Each engine
+ * executes in its own thread.
+ * <li>deploymentPort: The port that the Apex Engine Service will open so that it can be managed
+ * using the EngDep protocol. The EngDep protocol allows the engine service to be monitored, to
+ * start and stop engines in the engine service, and to update the policy model of the engine
+ * service.
+ * <li>engineParameters: Parameters (a {@link EngineParameters} instance) that all of the engines in
+ * the engine service will use. All engine threads use the same parameters and act as a pool of
+ * engines. Engine parameters specify the executors and context management for the engines.
+ * <li>policyModelFileName: The full path to the policy model file name to deploy on the engine
+ * service.
+ * <li>periodicEventPeriod: The period in milliseconds at which the periodic event PERIOIC_EVENT
+ * will be generated by APEX, 0 means no periodic event generation, negative values are illegal.
+ * </ol>
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class EngineServiceParameters extends AbstractParameters implements ApexParameterValidator {
+    private static final int MAX_PORT = 65535;
+
+    // @formatter:off
+    /** The default name of the Apex engine service. */
+    public static final String DEFAULT_NAME = "ApexEngineService";
+
+    /** The default version of the Apex engine service. */
+    public static final String DEFAULT_VERSION = "1.0.0";
+
+    /** The default ID of the Apex engine service. */
+    public static final int DEFAULT_ID = -1;
+
+    /** The default instance count for the Apex engine service. */
+    public static final int DEFAULT_INSTANCE_COUNT  = 1;
+
+    /** The default EngDep deployment port of the Apex engine service. */
+    public static final int DEFAULT_DEPLOYMENT_PORT = 34421;
+
+    // Apex engine service parameters
+    private String name                = DEFAULT_NAME;
+    private String version             = DEFAULT_VERSION;
+    private int    id                  = DEFAULT_ID;
+    private int    instanceCount       = DEFAULT_INSTANCE_COUNT;
+    private int    deploymentPort      = DEFAULT_DEPLOYMENT_PORT;
+    private String policyModelFileName = null;
+    private long   periodicEventPeriod = 0;
+    // @formatter:on
+
+    // Apex engine internal parameters
+    private EngineParameters engineParameters = new EngineParameters();
+
+    /**
+     * Constructor to create an apex engine service parameters instance and register the instance
+     * with the parameter service.
+     */
+    public EngineServiceParameters() {
+        super(EngineServiceParameters.class.getCanonicalName());
+        ParameterService.registerParameters(EngineServiceParameters.class, this);
+    }
+
+    /**
+     * Gets the key of the Apex engine service.
+     *
+     * @return the Apex engine service key
+     */
+    public AxArtifactKey getEngineKey() {
+        return new AxArtifactKey(name, version);
+    }
+
+    /**
+     * Sets the key of the Apex engine service.
+     * 
+     * @param key the the Apex engine service key
+     */
+    public void setEngineKey(final AxArtifactKey key) {
+        this.setName(key.getName());
+        this.setVersion(key.getVersion());
+    }
+
+    /**
+     * Gets the name of the engine service.
+     *
+     * @return the name of the engine service
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the name of the engine service.
+     *
+     * @param name the name of the engine service
+     */
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Gets the version of the engine service.
+     *
+     * @return the version of the engine service
+     */
+    public String getVersion() {
+        return version;
+    }
+
+    /**
+     * Sets the version of the engine service.
+     *
+     * @param version the version of the engine service
+     */
+    public void setVersion(final String version) {
+        this.version = version;
+    }
+
+    /**
+     * Gets the id of the engine service.
+     *
+     * @return the id of the engine service
+     */
+    public int getId() {
+        return id;
+    }
+
+    /**
+     * Sets the id of the engine service.
+     *
+     * @param id the id of the engine service
+     */
+    public void setId(final int id) {
+        this.id = id;
+    }
+
+    /**
+     * Gets the instance count of the engine service.
+     *
+     * @return the instance count of the engine service
+     */
+    public int getInstanceCount() {
+        return instanceCount;
+    }
+
+    /**
+     * Sets the instance count of the engine service.
+     *
+     * @param instanceCount the instance count of the engine service
+     */
+    public void setInstanceCount(final int instanceCount) {
+        this.instanceCount = instanceCount;
+    }
+
+    /**
+     * Gets the deployment port of the engine service.
+     *
+     * @return the deployment port of the engine service
+     */
+    public int getDeploymentPort() {
+        return deploymentPort;
+    }
+
+    /**
+     * Sets the deployment port of the engine service.
+     *
+     * @param deploymentPort the deployment port of the engine service
+     */
+    public void setDeploymentPort(final int deploymentPort) {
+        this.deploymentPort = deploymentPort;
+    }
+
+    /**
+     * Gets the file name of the policy engine for deployment on the engine service.
+     *
+     * @return the file name of the policy engine for deployment on the engine service
+     */
+    public String getPolicyModelFileName() {
+        return ResourceUtils.getFilePath4Resource(policyModelFileName);
+    }
+
+    /**
+     * Sets the file name of the policy engine for deployment on the engine service.
+     *
+     * @param policyModelFileName the file name of the policy engine for deployment on the engine
+     *        service
+     */
+    public void setPolicyModelFileName(final String policyModelFileName) {
+        this.policyModelFileName = policyModelFileName;
+    }
+
+    /**
+     * Get the period in milliseconds at which periodic events are sent, zero means no periodic
+     * events are being sent.
+     * 
+     * @return the periodic period
+     */
+    public long getPeriodicEventPeriod() {
+        return periodicEventPeriod;
+    }
+
+    /**
+     * Set the period in milliseconds at which periodic events are sent, zero means no periodic
+     * events are to be sent, negative values are illegal.
+     * 
+     * @param periodicEventPeriod the periodic period
+     */
+    public void setPeriodicEventPeriod(final long periodicEventPeriod) {
+        this.periodicEventPeriod = periodicEventPeriod;
+    }
+
+    /**
+     * Gets the engine parameters for engines in the engine service.
+     *
+     * @return the engine parameters for engines in the engine service
+     */
+    public EngineParameters getEngineParameters() {
+        return engineParameters;
+    }
+
+    /**
+     * Sets the engine parameters for engines in the engine service.
+     *
+     * @param engineParameters the engine parameters for engines in the engine service
+     */
+    public void setEngineParameters(final EngineParameters engineParameters) {
+        this.engineParameters = engineParameters;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.apps.uservice.parameters.ApexParameterValidator#validate()
+     */
+    @Override
+    public String validate() {
+        final StringBuilder errorMessageBuilder = new StringBuilder();
+
+        try {
+            new AxArtifactKey(name, version);
+        } catch (final Exception e) {
+            errorMessageBuilder.append("  name [" + name + "] and/or version [" + version + "] invalid\n");
+            errorMessageBuilder.append("   " + e.getMessage() + "\n");
+        }
+
+        if (id < 0) {
+            errorMessageBuilder.append(
+                    "  id not specified or specified value [" + id + "] invalid, must be specified as id >= 0\n");
+        }
+
+        if (instanceCount < 1) {
+            errorMessageBuilder.append(
+                    "  instanceCount [" + instanceCount + "] invalid, must be specified as instanceCount >= 1\n");
+        }
+
+        if (deploymentPort < 1 || deploymentPort > MAX_PORT) {
+            errorMessageBuilder.append(
+                    "  deploymentPort [" + deploymentPort + "] invalid, must be specified as 1024 <= port <= 65535\n");
+        }
+
+        if (policyModelFileName != null) {
+            if (policyModelFileName.trim().length() == 0) {
+                errorMessageBuilder.append("  policyModelFileName [" + policyModelFileName
+                        + "] invalid, must be specified as a non-empty string\n");
+            } else {
+                // The file name can refer to a resource on the local file system or on the class
+                // path
+                final URL fileURL = ResourceUtils.getURL4Resource(policyModelFileName);
+                if (fileURL == null) {
+                    errorMessageBuilder.append(
+                            "  policyModelFileName [" + policyModelFileName + "] not found or is not a plain file\n");
+                } else {
+                    final File policyModelFile = new File(fileURL.getPath());
+                    if (!policyModelFile.isFile()) {
+                        errorMessageBuilder.append("  policyModelFileName [" + policyModelFileName
+                                + "] not found or is not a plain file\n");
+                    }
+                }
+            }
+        }
+
+        if (periodicEventPeriod < 0) {
+            errorMessageBuilder.append("  periodicEventPeriod [" + periodicEventPeriod
+                    + "] invalid, must be specified in milliseconds as >=0\n");
+        }
+
+        return errorMessageBuilder.toString();
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/engineservice/EngineServiceParametersJSONAdapter.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/engineservice/EngineServiceParametersJSONAdapter.java
new file mode 100644 (file)
index 0000000..9fca2fd
--- /dev/null
@@ -0,0 +1,287 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters.engineservice;
+
+import java.lang.reflect.Type;
+import java.util.Map.Entry;
+
+import org.onap.policy.apex.context.impl.schema.java.JavaSchemaHelperParameters;
+import org.onap.policy.apex.context.parameters.ContextParameters;
+import org.onap.policy.apex.context.parameters.DistributorParameters;
+import org.onap.policy.apex.context.parameters.LockManagerParameters;
+import org.onap.policy.apex.context.parameters.PersistorParameters;
+import org.onap.policy.apex.context.parameters.SchemaHelperParameters;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.core.engine.EngineParameters;
+import org.onap.policy.apex.core.engine.ExecutorParameters;
+import org.onap.policy.apex.model.basicmodel.service.AbstractParameters;
+import org.onap.policy.apex.service.parameters.ApexParameterRuntimeException;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+/**
+ * This class deserializes engine service parameters from JSON format. The class produces an
+ * {@link EngineServiceParameters} instance from incoming JSON read from a configuration file in
+ * JSON format.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class EngineServiceParametersJSONAdapter
+        implements JsonSerializer<EngineParameters>, JsonDeserializer<EngineParameters> {
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(EngineServiceParametersJSONAdapter.class);
+
+    private static final String PARAMETER_CLASS_NAME = "parameterClassName";
+
+    // @formatter:off
+    private static final String CONTEXT_PARAMETERS      = "contextParameters";
+    private static final String DISTRIBUTOR_PARAMETERS  = "distributorParameters";
+    private static final String LOCK_MANAGER_PARAMETERS = "lockManagerParameters";
+    private static final String PERSISTOR_PARAMETERS    = "persistorParameters";
+    private static final String SCHEMA_PARAMETERS       = "schemaParameters";
+    private static final String EXECUTOR_PARAMETERS     = "executorParameters";
+    // @formatter:on
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.google.gson.JsonSerializer#serialize(java.lang.Object, java.lang.reflect.Type,
+     * com.google.gson.JsonSerializationContext)
+     */
+    @Override
+    public JsonElement serialize(final EngineParameters src, final Type typeOfSrc,
+            final JsonSerializationContext context) {
+        final String returnMessage = "serialization of Apex parameters to Json is not supported";
+        LOGGER.error(returnMessage);
+        throw new ApexParameterRuntimeException(returnMessage);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.google.gson.JsonDeserializer#deserialize(com.google.gson.JsonElement,
+     * java.lang.reflect.Type, com.google.gson.JsonDeserializationContext)
+     */
+    @Override
+    public EngineParameters deserialize(final JsonElement json, final Type typeOfT,
+            final JsonDeserializationContext context) throws JsonParseException {
+        final JsonObject engineParametersJsonObject = json.getAsJsonObject();
+
+        final EngineParameters engineParameters = new EngineParameters();
+
+        // Deserialise context parameters, they may be a subclass of the ContextParameters class
+        engineParameters.setContextParameters(
+                (ContextParameters) context.deserialize(engineParametersJsonObject, ContextParameters.class));
+
+        // Context parameter wrangling
+        getContextParameters(engineParametersJsonObject, engineParameters, context);
+
+        // Executor parameter wrangling
+        getExecutorParameters(engineParametersJsonObject, engineParameters, context);
+
+        return engineParameters;
+    }
+
+    /**
+     * Get the context parameters for Apex.
+     *
+     * @param engineParametersJsonObject The input JSON
+     * @param engineParameters The output parameters
+     * @param context the JSON context
+     */
+    private void getContextParameters(final JsonObject engineParametersJsonObject,
+            final EngineParameters engineParameters, final JsonDeserializationContext context) {
+        final JsonElement contextParametersElement = engineParametersJsonObject.get(CONTEXT_PARAMETERS);
+
+        // Context parameters are optional so if the element does not exist, just return
+        if (contextParametersElement == null) {
+            return;
+        }
+
+        // We do this because the JSON parameters may be for a subclass of ContextParameters
+        final ContextParameters contextParameters =
+                (ContextParameters) deserializeParameters(CONTEXT_PARAMETERS, contextParametersElement, context);
+
+        // We know this will work because if the context parameters was not a Json object, the
+        // previous deserializeParameters() call would not have worked
+        final JsonObject contextParametersObject = engineParametersJsonObject.get(CONTEXT_PARAMETERS).getAsJsonObject();
+
+        // Now get the distributor, lock manager, and persistence parameters
+        final JsonElement distributorParametersElement = contextParametersObject.get(DISTRIBUTOR_PARAMETERS);
+        if (distributorParametersElement != null) {
+            contextParameters
+                    .setDistributorParameters((DistributorParameters) deserializeParameters(DISTRIBUTOR_PARAMETERS,
+                            distributorParametersElement, context));
+        }
+
+        final JsonElement lockManagerParametersElement = contextParametersObject.get(LOCK_MANAGER_PARAMETERS);
+        if (lockManagerParametersElement != null) {
+            contextParameters
+                    .setLockManagerParameters((LockManagerParameters) deserializeParameters(LOCK_MANAGER_PARAMETERS,
+                            lockManagerParametersElement, context));
+        }
+
+        final JsonElement persistorParametersElement = contextParametersObject.get(PERSISTOR_PARAMETERS);
+        if (persistorParametersElement != null) {
+            contextParameters.setPersistorParameters((PersistorParameters) deserializeParameters(PERSISTOR_PARAMETERS,
+                    persistorParametersElement, context));
+        }
+
+        // Schema Handler parameter wrangling
+        getSchemaHandlerParameters(contextParametersObject, contextParameters, context);
+
+        // Get the engine plugin parameters
+        engineParameters.setContextParameters(contextParameters);
+    }
+
+    /**
+     * Get the executor parameters for Apex.
+     *
+     * @param engineParametersJsonObject The input JSON
+     * @param engineParameters The output parameters
+     * @param context the JSON context
+     */
+    private void getExecutorParameters(final JsonObject engineParametersJsonObject,
+            final EngineParameters engineParameters, final JsonDeserializationContext context) {
+        final JsonElement executorParametersElement = engineParametersJsonObject.get(EXECUTOR_PARAMETERS);
+
+        // Executor parameters are mandatory so if the element does not exist throw an exception
+        if (executorParametersElement == null) {
+            final String returnMessage = "no \"" + EXECUTOR_PARAMETERS
+                    + "\" entry found in parameters, at least one executor parameter entry must be specified";
+            LOGGER.error(returnMessage);
+            throw new ApexParameterRuntimeException(returnMessage);
+        }
+
+        // Deserialize the executor parameters
+        final JsonObject executorParametersJsonObject =
+                engineParametersJsonObject.get(EXECUTOR_PARAMETERS).getAsJsonObject();
+
+        for (final Entry<String, JsonElement> executorEntries : executorParametersJsonObject.entrySet()) {
+            final ExecutorParameters executorParameters =
+                    (ExecutorParameters) deserializeParameters(EXECUTOR_PARAMETERS + ':' + executorEntries.getKey(),
+                            executorEntries.getValue(), context);
+            engineParameters.getExecutorParameterMap().put(executorEntries.getKey(), executorParameters);
+        }
+    }
+
+    /**
+     * Get the schema parameters for Apex.
+     *
+     * @param contextParametersJsonObject The input JSON
+     * @param contextParameters The output parameters
+     * @param context the JSON context
+     */
+    private void getSchemaHandlerParameters(final JsonObject contextParametersJsonObject,
+            final ContextParameters contextParameters, final JsonDeserializationContext context) {
+        final JsonElement schemaParametersElement = contextParametersJsonObject.get(SCHEMA_PARAMETERS);
+
+        // Insert the default Java schema helper
+        contextParameters.getSchemaParameters().getSchemaHelperParameterMap()
+                .put(SchemaParameters.DEFAULT_SCHEMA_FLAVOUR, new JavaSchemaHelperParameters());
+
+        // Context parameters are optional so if the element does not exist, just return
+        if (schemaParametersElement == null) {
+            return;
+        }
+
+        // Deserialize the executor parameters
+        final JsonObject schemaHelperParametersJsonObject =
+                contextParametersJsonObject.get(SCHEMA_PARAMETERS).getAsJsonObject();
+
+        for (final Entry<String, JsonElement> schemaHelperEntries : schemaHelperParametersJsonObject.entrySet()) {
+            contextParameters.getSchemaParameters().getSchemaHelperParameterMap().put(schemaHelperEntries.getKey(),
+                    (SchemaHelperParameters) deserializeParameters(
+                            SCHEMA_PARAMETERS + ':' + schemaHelperEntries.getKey(), schemaHelperEntries.getValue(),
+                            context));
+        }
+    }
+
+    /**
+     * Deserialize a parameter object that's a superclass of the AbstractParameters class.
+     *
+     * @param parametersLabel Label to use for error messages
+     * @param parametersElement The JSON object holding the parameters
+     * @param context The GSON context
+     * @return the parameters
+     * @throws ApexParameterRuntimeException on errors reading the parameters
+     */
+    private AbstractParameters deserializeParameters(final String parametersLabel, final JsonElement parametersElement,
+            final JsonDeserializationContext context) throws ApexParameterRuntimeException {
+        JsonObject parametersObject = null;
+
+        // Check that the JSON element is a JSON object
+        if (parametersElement.isJsonObject()) {
+            parametersObject = parametersElement.getAsJsonObject();
+        } else {
+            final String returnMessage = "value of \"" + parametersLabel + "\" entry is not a parameter JSON object";
+            LOGGER.error(returnMessage);
+            throw new ApexParameterRuntimeException(returnMessage);
+        }
+
+        // Get the parameter class name for instantiation in deserialization
+        final JsonElement parameterClassNameElement = parametersObject.get(PARAMETER_CLASS_NAME);
+        if (parameterClassNameElement == null) {
+            final String returnMessage =
+                    "could not find field \"" + PARAMETER_CLASS_NAME + "\" in \"" + parametersLabel + "\" entry";
+            LOGGER.error(returnMessage);
+            throw new ApexParameterRuntimeException(returnMessage);
+        }
+
+        // Check the parameter is a JSON primitive
+        if (!parameterClassNameElement.isJsonPrimitive()) {
+            final String returnMessage = "value for field \"" + PARAMETER_CLASS_NAME + "\" in \"" + parametersLabel
+                    + "\" entry is not a plain string";
+            LOGGER.error(returnMessage);
+            throw new ApexParameterRuntimeException(returnMessage);
+        }
+
+        // Check the parameter has a value
+        final String parameterClassName = parameterClassNameElement.getAsString();
+        if (parameterClassName == null || parameterClassName.trim().length() == 0) {
+            final String returnMessage = "value for field \"" + PARAMETER_CLASS_NAME + "\" in \"" + parametersLabel
+                    + "\" entry is not specified or is blank";
+            LOGGER.error(returnMessage);
+            throw new ApexParameterRuntimeException(returnMessage);
+        }
+
+        // Deserialize the parameters using GSON
+        AbstractParameters parameters = null;
+        try {
+            parameters = context.deserialize(parametersObject, Class.forName(parameterClassName));
+        } catch (JsonParseException | ClassNotFoundException e) {
+            final String returnMessage =
+                    "failed to deserialize the parameters for \"" + parametersLabel + "\" " + "to parameter class \""
+                            + parameterClassName + "\"\n" + e.getClass().getCanonicalName() + ": " + e.getMessage();
+            LOGGER.error(returnMessage, e);
+            throw new ApexParameterRuntimeException(returnMessage, e);
+        }
+
+        return parameters;
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/engineservice/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/engineservice/package-info.java
new file mode 100644 (file)
index 0000000..e724ce4
--- /dev/null
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Defines the parameters for the APEX Engine Service and for engines running in the engine service.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.parameters.engineservice;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventhandler/EventHandlerParameters.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventhandler/EventHandlerParameters.java
new file mode 100644 (file)
index 0000000..34589f3
--- /dev/null
@@ -0,0 +1,362 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters.eventhandler;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.onap.policy.apex.model.basicmodel.service.AbstractParameters;
+import org.onap.policy.apex.service.parameters.ApexParameterValidator;
+import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters;
+
+/**
+ * The parameters for a single event producer, event consumer or synchronous event handler.
+ * <p>
+ * Event producers, consumers, and synchronous event handlers all use a carrier technology and an
+ * event protocol so the actual parameters for each one are the same. Therefore, we use the same
+ * class for the parameters of each one.
+ * <p>
+ * The following parameters are defined:
+ * <ol>
+ * <li>carrierTechnologyParameters: The carrier technology is the type of messaging infrastructure
+ * used to carry events. Examples are File, Kafka or REST.
+ * <li>eventProtocolParameters: The format that the events are in when being carried. Examples are
+ * JSON, XML, or Java Beans. carrier technology
+ * <li>synchronousMode: true if the event handler is working in synchronous mode, defaults to false
+ * <li>synchronousPeer: the peer event handler (consumer for producer or producer for consumer) of
+ * this event handler in synchronous mode
+ * <li>synchronousTimeout: the amount of time to wait for the reply to synchronous events before
+ * they are timed out
+ * <li>requestorMode: true if the event handler is working in requestor mode, defaults to false
+ * <li>requestorPeer: the peer event handler (consumer for producer or producer for consumer) of
+ * this event handler in requestor mode
+ * <li>requestorTimeout: the amount of time to wait for the reply to synchronous events before they
+ * are timed out
+ * <li>eventNameFilter: a regular expression to apply to events on this event handler. If specified,
+ * events not matching the given regular expression are ignored. If it is null, all events are
+ * handledDefaults to null.
+ * </ol>
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class EventHandlerParameters extends AbstractParameters implements ApexParameterValidator {
+    private String name = null;
+    private CarrierTechnologyParameters carrierTechnologyParameters = null;
+    private EventProtocolParameters eventProtocolParameters = null;
+    private boolean synchronousMode = false;
+    private String synchronousPeer = null;
+    private long synchronousTimeout = 0;
+    private boolean requestorMode = false;
+    private String requestorPeer = null;
+    private long requestorTimeout = 0;
+    private String eventName = null;
+    private String eventNameFilter = null;
+
+    /**
+     * Constructor to create an event handler parameters instance.
+     */
+    public EventHandlerParameters() {
+        super(EventHandlerParameters.class.getCanonicalName());
+    }
+
+    /**
+     * Constructor to create an event handler parameters instance with the name of a sub class of
+     * this class.
+     *
+     * @param parameterClassName the class name of a sub class of this class
+     */
+    public EventHandlerParameters(final String parameterClassName) {
+        super(parameterClassName);
+    }
+
+    /**
+     * Gets the name of the event handler.
+     *
+     * @return the event handler name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the name of the event handler.
+     *
+     * @param name the event handler name
+     */
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Checks if the name of the event handler is set.
+     * 
+     * @return true if the name is set
+     */
+    public boolean checkSetName() {
+        return !(name == null || name.trim().length() == 0);
+    }
+
+    /**
+     * Gets the carrier technology parameters of the event handler.
+     *
+     * @return the carrierTechnologyParameters of the event handler
+     */
+    public CarrierTechnologyParameters getCarrierTechnologyParameters() {
+        return carrierTechnologyParameters;
+    }
+
+    /**
+     * Sets the carrier technology parameters of the event handler.
+     *
+     * @param carrierTechnologyParameters the carrierTechnologyParameters to set
+     */
+    public void setCarrierTechnologyParameters(final CarrierTechnologyParameters carrierTechnologyParameters) {
+        this.carrierTechnologyParameters = carrierTechnologyParameters;
+    }
+
+    /**
+     * Gets the event protocol parameters of the event handler.
+     *
+     * @return the eventProtocolParameters
+     */
+    public EventProtocolParameters getEventProtocolParameters() {
+        return eventProtocolParameters;
+    }
+
+    /**
+     * Sets the event protocol parameters.
+     *
+     * @param eventProtocolParameters the eventProtocolParameters to set
+     */
+    public void setEventProtocolParameters(final EventProtocolParameters eventProtocolParameters) {
+        this.eventProtocolParameters = eventProtocolParameters;
+    }
+
+
+    /**
+     * Checks if the event handler is in the given peered mode.
+     *
+     * @param peeredMode the peer mode
+     * @return true, if the event handler is in the peered mode
+     */
+    public boolean isPeeredMode(final EventHandlerPeeredMode peeredMode) {
+        switch (peeredMode) {
+            case SYNCHRONOUS:
+                return synchronousMode;
+            case REQUESTOR:
+                return requestorMode;
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Sets a peered mode as true or false on the event handler.
+     *
+     * @param peeredMode the peered mode to set
+     * @param peeredModeValue the value to set the peered mode to
+     */
+    public void setPeeredMode(final EventHandlerPeeredMode peeredMode, final boolean peeredModeValue) {
+        switch (peeredMode) {
+            case SYNCHRONOUS:
+                synchronousMode = peeredModeValue;
+                return;
+            case REQUESTOR:
+                requestorMode = peeredModeValue;
+                return;
+            default:
+                return;
+        }
+    }
+
+    /**
+     * Gets the peer for the event handler in this peered mode.
+     *
+     * @param peeredMode the peered mode to get the peer for
+     * @return the peer
+     */
+    public String getPeer(final EventHandlerPeeredMode peeredMode) {
+        switch (peeredMode) {
+            case SYNCHRONOUS:
+                return synchronousPeer;
+            case REQUESTOR:
+                return requestorPeer;
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * Sets the peer for the event handler in this peered mode.
+     *
+     * @param peeredMode the peered mode to set the peer for
+     * @param peer the peer
+     */
+    public void setPeer(final EventHandlerPeeredMode peeredMode, final String peer) {
+        switch (peeredMode) {
+            case SYNCHRONOUS:
+                synchronousPeer = peer;
+                return;
+            case REQUESTOR:
+                requestorPeer = peer;
+                return;
+            default:
+                return;
+        }
+    }
+
+    /**
+     * Get the timeout value for the event handler in peered mode.
+     * 
+     * @param peeredMode the peered mode to get the timeout for
+     * @return the timeout value
+     */
+    public long getPeerTimeout(final EventHandlerPeeredMode peeredMode) {
+        switch (peeredMode) {
+            case SYNCHRONOUS:
+                return synchronousTimeout;
+            case REQUESTOR:
+                return requestorTimeout;
+            default:
+                return -1;
+        }
+    }
+
+    /**
+     * Set the timeout value for the event handler in peered mode.
+     * 
+     * @param peeredMode the peered mode to set the timeout for
+     * @param timeout the timeout value
+     */
+    public void setPeerTimeout(final EventHandlerPeeredMode peeredMode, final long timeout) {
+        switch (peeredMode) {
+            case SYNCHRONOUS:
+                synchronousTimeout = timeout;
+                return;
+            case REQUESTOR:
+                requestorTimeout = timeout;
+                return;
+            default:
+                return;
+        }
+    }
+
+    /**
+     * Check if an event name is being used.
+     *
+     * @return true if an event name is being used
+     */
+    public boolean isSetEventName() {
+        return eventName != null;
+    }
+
+    /**
+     * Gets the event name for this event handler.
+     *
+     * @return the event name
+     */
+    public String getEventName() {
+        return eventName;
+    }
+
+    /**
+     * Sets the event name for this event handler.
+     *
+     * @param eventName the event name
+     */
+    public void setEventName(final String eventName) {
+        this.eventName = eventName;
+    }
+
+    /**
+     * Check if event name filtering is being used.
+     *
+     * @return true if event name filtering is being used
+     */
+    public boolean isSetEventNameFilter() {
+        return eventNameFilter != null;
+    }
+
+    /**
+     * Gets the event name filter for this event handler.
+     *
+     * @return the event name filter
+     */
+    public String getEventNameFilter() {
+        return eventNameFilter;
+    }
+
+    /**
+     * Sets the event name filter for this event handler.
+     *
+     * @param eventNameFilter the event name filter
+     */
+    public void setEventNameFilter(final String eventNameFilter) {
+        this.eventNameFilter = eventNameFilter;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.parameters.ApexParameterValidator#validate()
+     */
+    @Override
+    public String validate() {
+        final StringBuilder errorMessageBuilder = new StringBuilder();
+
+        if (eventProtocolParameters == null) {
+            errorMessageBuilder.append("  event handler eventProtocolParameters not specified or blank\n");
+        } else {
+            errorMessageBuilder.append(eventProtocolParameters.validate());
+        }
+
+        if (carrierTechnologyParameters == null) {
+            errorMessageBuilder.append("  event handler carrierTechnologyParameters not specified or blank\n");
+        } else {
+            errorMessageBuilder.append(carrierTechnologyParameters.validate());
+        }
+
+        if (eventNameFilter != null) {
+            try {
+                Pattern.compile(eventNameFilter);
+            } catch (final PatternSyntaxException pse) {
+                errorMessageBuilder.append("  event handler eventNameFilter is not a valid regular expression: "
+                        + pse.getMessage() + "\n");
+            }
+        }
+        return errorMessageBuilder.toString();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "EventHandlerParameters [name=" + name + ", carrierTechnologyParameters=" + carrierTechnologyParameters
+                + ", eventProtocolParameters=" + eventProtocolParameters + ", synchronousMode=" + synchronousMode
+                + ", synchronousPeer=" + synchronousPeer + ", synchronousTimeout=" + synchronousTimeout
+                + ", requestorMode=" + requestorMode + ", requestorPeer=" + requestorPeer + ", requestorTimeout="
+                + requestorTimeout + ", eventName=" + eventName + ", eventNameFilter=" + eventNameFilter + "]";
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventhandler/EventHandlerPeeredMode.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventhandler/EventHandlerPeeredMode.java
new file mode 100644 (file)
index 0000000..b7ee667
--- /dev/null
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters.eventhandler;
+
+/**
+ * This enum specifies the peered mode that an event handler may be in.
+ * 
+ * <p>
+ * The following values are defined:
+ * <ol>
+ * <li>SYNCHRONOUS: The event handler is tied to another event handler for event handling in APEX,
+ * used for request-response calls where APEX is the receiver.
+ * <li>REQUESTOR: The event handler is tied another event handler for event handling in APEX, used
+ * for request-response calls where APEX is the sender.
+ * </ol>
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * 
+ * @author liam.fallon@ericsson.com
+ *
+ */
+public enum EventHandlerPeeredMode {
+    SYNCHRONOUS, REQUESTOR
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventhandler/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventhandler/package-info.java
new file mode 100644 (file)
index 0000000..2866358
--- /dev/null
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Defines the structure of producer parameters for APEX.
+ *
+ * @author John Keeney (john.keeney@ericsson.com)
+ */
+package org.onap.policy.apex.service.parameters.eventhandler;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/EventProtocolParameters.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/EventProtocolParameters.java
new file mode 100644 (file)
index 0000000..6e66a18
--- /dev/null
@@ -0,0 +1,123 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters.eventprotocol;
+
+import org.onap.policy.apex.model.basicmodel.service.AbstractParameters;
+import org.onap.policy.apex.service.parameters.ApexParameterValidator;
+
+/**
+ * A default event protocol parameter class that may be specialized by event protocol plugins that
+ * require plugin specific parameters.
+ *
+ * <p>
+ * The following parameters are defined:
+ * <ol>
+ * <li>label: The label of the event protocol technology.
+ * <li>eventProducerPluginClass: The name of the plugin class that will be used by Apex to produce
+ * and emit output events for this carrier technology
+ * </ol>
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public abstract class EventProtocolParameters extends AbstractParameters implements ApexParameterValidator {
+    // The event protocol label
+    private String label = null;
+
+    // Event protocol converter plugin class for this event protocol
+    private String eventProtocolPluginClass;
+
+    /**
+     * Constructor to create an event protocol parameters instance with the name of a sub class of
+     * this class and register the instance with the parameter service.
+     *
+     * @param parameterClassName the class name of a sub class of this class
+     */
+    public EventProtocolParameters(final String parameterClassName) {
+        super(parameterClassName);
+    }
+
+    /**
+     * Gets the label of the event protocol.
+     *
+     * @return the label of the event protocol
+     */
+    public String getLabel() {
+        return label;
+    }
+
+    /**
+     * Sets the label of the event protocol.
+     *
+     * @param label the label of the event protocol
+     */
+    public void setLabel(final String label) {
+        this.label = label.replaceAll("\\s+", "");
+    }
+
+    /**
+     * Gets the event event protocol plugin class.
+     *
+     * @return the event event protocol plugin class
+     */
+    public String getEventProtocolPluginClass() {
+        return eventProtocolPluginClass;
+    }
+
+    /**
+     * Sets the event event protocol plugin class.
+     *
+     * @param eventProtocolPluginClass the event event protocol plugin class
+     */
+    public void setEventProtocolPluginClass(final String eventProtocolPluginClass) {
+        this.eventProtocolPluginClass = eventProtocolPluginClass.replaceAll("\\s+", "");
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.model.basicmodel.service.AbstractParameters#toString()
+     */
+    @Override
+    public String toString() {
+        return "CarrierTechnologyParameters [label=" + label + ", EventProtocolPluginClass=" + eventProtocolPluginClass
+                + "]";
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.parameters.ApexParameterValidator#validate()
+     */
+    @Override
+    public String validate() {
+        final StringBuilder errorMessageBuilder = new StringBuilder();
+
+        if (label == null || label.length() == 0) {
+            errorMessageBuilder.append("  event protocol label not specified or is blank\n");
+        }
+
+        if (eventProtocolPluginClass == null || eventProtocolPluginClass.length() == 0) {
+            errorMessageBuilder.append("  event protocol eventProtocolPluginClass not specified or is blank\n");
+        }
+
+        return errorMessageBuilder.toString();
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/EventProtocolParametersJSONAdapter.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/EventProtocolParametersJSONAdapter.java
new file mode 100644 (file)
index 0000000..c880756
--- /dev/null
@@ -0,0 +1,172 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters.eventprotocol;
+
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onap.policy.apex.service.engine.event.impl.apexprotocolplugin.ApexEventProtocolParameters;
+import org.onap.policy.apex.service.engine.event.impl.jsonprotocolplugin.JSONEventProtocolParameters;
+import org.onap.policy.apex.service.parameters.ApexParameterRuntimeException;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+/**
+ * This class serialises and deserialises various type of event protocol parameters to and from
+ * JSON.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class EventProtocolParametersJSONAdapter
+        implements JsonSerializer<EventProtocolParameters>, JsonDeserializer<EventProtocolParameters> {
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(EventProtocolParametersJSONAdapter.class);
+
+    private static final String PARAMETER_CLASS_NAME = "parameterClassName";
+
+    private static final String EVENT_PROTOCOL_TOKEN = "eventProtocol";
+    private static final String EVENT_PROTOCOL_PARAMETERS = "parameters";
+
+    // Built in event protocol parameters
+    private static final Map<String, String> BUILT_IN_EVENT_RPOTOCOL_PARMETER_CLASS_MAP = new HashMap<>();
+    static {
+        BUILT_IN_EVENT_RPOTOCOL_PARMETER_CLASS_MAP.put("JSON", JSONEventProtocolParameters.class.getCanonicalName());
+        BUILT_IN_EVENT_RPOTOCOL_PARMETER_CLASS_MAP.put("APEX", ApexEventProtocolParameters.class.getCanonicalName());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.google.gson.JsonSerializer#serialize(java.lang.Object, java.lang.reflect.Type,
+     * com.google.gson.JsonSerializationContext)
+     */
+    @Override
+    public JsonElement serialize(final EventProtocolParameters src, final Type typeOfSrc,
+            final JsonSerializationContext context) {
+        final String returnMessage = "serialization of Apex event protocol parameters to Json is not supported";
+        LOGGER.error(returnMessage);
+        throw new ApexParameterRuntimeException(returnMessage);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.google.gson.JsonDeserializer#deserialize(com.google.gson.JsonElement,
+     * java.lang.reflect.Type, com.google.gson.JsonDeserializationContext)
+     */
+    @Override
+    public EventProtocolParameters deserialize(final JsonElement json, final Type typeOfT,
+            final JsonDeserializationContext context) throws JsonParseException {
+        final JsonObject jsonObject = json.getAsJsonObject();
+
+        // Get the event protocol label primitive
+        final JsonPrimitive labelJsonPrimitive = (JsonPrimitive) jsonObject.get(EVENT_PROTOCOL_TOKEN);
+
+        // Check if we found our event protocol
+        if (labelJsonPrimitive == null) {
+            LOGGER.warn("event protocol parameter \"" + EVENT_PROTOCOL_TOKEN + "\" not found in JSON file");
+            return null;
+        }
+
+        // Get and check the event protocol label
+        final String eventProtocolLabel = labelJsonPrimitive.getAsString().replaceAll("\\s+", "");
+        if (eventProtocolLabel == null || eventProtocolLabel.length() == 0) {
+            final String errorMessage = "event protocol parameter \"" + EVENT_PROTOCOL_TOKEN + "\" value \""
+                    + labelJsonPrimitive.getAsString() + "\" invalid in JSON file";
+            LOGGER.warn(errorMessage);
+            throw new ApexParameterRuntimeException(errorMessage);
+        }
+
+        // We now get the event protocol parameter class
+        String eventProtocolParameterClassName = null;
+
+        // Get the event protocol parameter class for the event protocol plugin class from the
+        // configuration parameters
+        final JsonPrimitive classNameJsonPrimitive = (JsonPrimitive) jsonObject.get(PARAMETER_CLASS_NAME);
+
+        // If no event protocol parameter class was specified, we use the default
+        if (classNameJsonPrimitive == null) {
+            eventProtocolParameterClassName = BUILT_IN_EVENT_RPOTOCOL_PARMETER_CLASS_MAP.get(eventProtocolLabel);
+        } else {
+            // We use the specified one
+            eventProtocolParameterClassName = classNameJsonPrimitive.getAsString().replaceAll("\\s+", "");
+        }
+
+        // Check the event protocol parameter class
+        if (eventProtocolParameterClassName == null || eventProtocolParameterClassName.length() == 0) {
+            final String errorMessage =
+                    "event protocol \"" + eventProtocolLabel + "\" parameter \"" + PARAMETER_CLASS_NAME + "\" value \""
+                            + classNameJsonPrimitive.getAsString() + "\" invalid in JSON file";
+            LOGGER.warn(errorMessage);
+            throw new ApexParameterRuntimeException(errorMessage);
+        }
+
+        // Get the class for the event protocol
+        Class<?> eventProtocolParameterClass = null;
+        try {
+            eventProtocolParameterClass = Class.forName(eventProtocolParameterClassName);
+        } catch (final ClassNotFoundException e) {
+            final String errorMessage =
+                    "event protocol \"" + eventProtocolLabel + "\" parameter \"" + PARAMETER_CLASS_NAME + "\" value \""
+                            + eventProtocolParameterClassName + "\", could not find class";
+            LOGGER.warn(errorMessage, e);
+            throw new ApexParameterRuntimeException(errorMessage, e);
+        }
+
+        // Deserialise the class
+        EventProtocolParameters eventProtocolParameters =
+                context.deserialize(jsonObject.get(EVENT_PROTOCOL_PARAMETERS), eventProtocolParameterClass);
+        if (eventProtocolParameters == null) {
+            // OK no parameters for the event protocol have been specified, just instantiate the
+            // default parameters
+            try {
+                eventProtocolParameters = (EventProtocolParameters) eventProtocolParameterClass.newInstance();
+            } catch (final Exception e) {
+                final String errorMessage = "could not create default parameters for event protocol \""
+                        + eventProtocolLabel + "\"\n" + e.getMessage();
+                LOGGER.warn(errorMessage, e);
+                throw new ApexParameterRuntimeException(errorMessage, e);
+            }
+        }
+
+        // Check that the event protocol label matches the label in the event protocol parameters
+        // object
+        if (!eventProtocolParameters.getLabel().equals(eventProtocolLabel)) {
+            final String errorMessage = "event protocol \"" + eventProtocolLabel + "\" does not match plugin \""
+                    + eventProtocolParameters.getLabel() + "\" in \"" + eventProtocolParameterClassName
+                    + "\", specify correct event protocol parameter plugin in parameter \"" + PARAMETER_CLASS_NAME
+                    + "\"";
+            LOGGER.warn(errorMessage);
+            throw new ApexParameterRuntimeException(errorMessage);
+        }
+
+        return eventProtocolParameters;
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/EventProtocolTextCharDelimitedParameters.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/EventProtocolTextCharDelimitedParameters.java
new file mode 100644 (file)
index 0000000..f8873ad
--- /dev/null
@@ -0,0 +1,122 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters.eventprotocol;
+
+import org.onap.policy.apex.service.parameters.ApexParameterValidator;
+
+/**
+ * An event protocol parameter class for character delimited textual event protocols that may be
+ * specialized by event protocol plugins that require plugin specific parameters.
+ *
+ * <p>
+ * The following parameters are defined:
+ * <ol>
+ * <li>startChar: starting character delimiter for text blocks containing an event.
+ * <li>endChar: ending character delimiter for text blocks containing an event.
+ * </ol>
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public abstract class EventProtocolTextCharDelimitedParameters extends EventProtocolParameters
+        implements ApexParameterValidator {
+    // The starting and ending character delimiter
+    private char startChar = '\0';
+    private char endChar = '\0';
+
+    /**
+     * Constructor to create an event protocol parameters instance with the name of a sub class of
+     * this class.
+     *
+     * @param parameterClassName the class name of a sub class of this class
+     */
+    public EventProtocolTextCharDelimitedParameters(final String parameterClassName) {
+        super(parameterClassName);
+    }
+
+    /**
+     * Gets the start character that delimits the start of text blocks.
+     *
+     * @return the start char
+     */
+    public char getStartChar() {
+        return startChar;
+    }
+
+    /**
+     * Sets the start character that delimits the start of text blocks.
+     *
+     * @param startChar the start character
+     */
+    public void setStartChar(final char startChar) {
+        this.startChar = startChar;
+    }
+
+    /**
+     * Gets the end character that delimits the end of text blocks.
+     *
+     * @return the end character
+     */
+    public char getEndChar() {
+        return endChar;
+    }
+
+    /**
+     * Sets the end character that delimits the end of text blocks.
+     *
+     * @param endChar the end character
+     */
+    public void setEndChar(final char endChar) {
+        this.endChar = endChar;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters#toString()
+     */
+    @Override
+    public String toString() {
+        return "EventProtocolTextCharDelimitedParameters {" + super.toString() + "} [startChar=" + startChar
+                + ", endChar=" + endChar + "]";
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters#validate()
+     */
+    @Override
+    public String validate() {
+        final StringBuilder errorMessageBuilder = new StringBuilder();
+
+        errorMessageBuilder.append(super.validate());
+
+        if (startChar == '\0') {
+            errorMessageBuilder.append("  text character delimited start character has not been specified\n");
+        }
+
+        if (endChar == '\0') {
+            errorMessageBuilder.append("  text character delimited end character has not been specified\n");
+        }
+
+        return errorMessageBuilder.toString();
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/EventProtocolTextTokenDelimitedParameters.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/EventProtocolTextTokenDelimitedParameters.java
new file mode 100644 (file)
index 0000000..37fbd32
--- /dev/null
@@ -0,0 +1,95 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.parameters.eventprotocol;
+
+import org.onap.policy.apex.service.parameters.ApexParameterValidator;
+
+/**
+ * An event protocol parameter class for token delimited textual event protocols that may be
+ * specialized by event protocol plugins that require plugin specific parameters.
+ *
+ * <p>
+ * The following parameters are defined:
+ * <ol>
+ * <li>delimiterToken: the token string that delimits text blocks that contain events.
+ * </ol>
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public abstract class EventProtocolTextTokenDelimitedParameters extends EventProtocolParameters
+        implements ApexParameterValidator {
+    // The delimiter token for text blocks
+    private String delimiterToken = null;
+
+    /**
+     * Constructor to create an event protocol parameters instance with the name of a sub class of
+     * this class.
+     *
+     * @param parameterClassName the class name of a sub class of this class
+     */
+    public EventProtocolTextTokenDelimitedParameters(final String parameterClassName) {
+        super(parameterClassName);
+    }
+
+    /**
+     * Gets the delimiter token that delimits events in the text.
+     *
+     * @return the delimiter token
+     */
+    public String getDelimiterToken() {
+        return delimiterToken;
+    }
+
+
+    /**
+     * Sets the delimiter token that delimits events in the text.
+     *
+     * @param delimiterToken the delimiter token
+     */
+    public void setDelimiterToken(final String delimiterToken) {
+        this.delimiterToken = delimiterToken;
+    }
+
+
+    @Override
+    public String toString() {
+        return "EventProtocolTextCharDelimitedParameters {" + super.toString() + "} [delimiterToken=" + delimiterToken
+                + "]";
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.service.parameters.ApexParameterValidator#validate()
+     */
+    @Override
+    public String validate() {
+        final StringBuilder errorMessageBuilder = new StringBuilder();
+
+        errorMessageBuilder.append(super.validate());
+
+        if (delimiterToken == null || delimiterToken.length() == 0) {
+            errorMessageBuilder.append("  text delimiter token not specified or is blank\n");
+        }
+
+        return errorMessageBuilder.toString();
+    }
+}
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/eventprotocol/package-info.java
new file mode 100644 (file)
index 0000000..967198a
--- /dev/null
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Defines the structure of event protocol parameters for APEX.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.parameters.eventprotocol;
diff --git a/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/package-info.java b/services/services-engine/src/main/java/org/onap/policy/apex/service/parameters/package-info.java
new file mode 100644 (file)
index 0000000..2c64737
--- /dev/null
@@ -0,0 +1,29 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * Implements parameter handling for all parameters in APEX. It uses specializations of (@link
+ * {@link org.onap.policy.apex.model.basicmodel.service.AbstractParameters} for all parameters and
+ * works with {@link org.onap.policy.apex.model.basicmodel.service.ParameterService} for storing and
+ * finding parameters.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.service.parameters;
diff --git a/services/services-engine/src/main/resources/version.txt b/services/services-engine/src/main/resources/version.txt
new file mode 100644 (file)
index 0000000..f1ce558
--- /dev/null
@@ -0,0 +1,4 @@
+Apex Adaptive Policy Engine
+Version: ${project.version}
+Built (UTC): ${timestamp}
+ONAP https://wiki.onap.org
\ No newline at end of file
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/event/JSONEventGenerator.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/event/JSONEventGenerator.java
new file mode 100644 (file)
index 0000000..4da8c42
--- /dev/null
@@ -0,0 +1,442 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import java.util.Random;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class JSONEventGenerator {
+    private static int nextEventNo = 0;
+
+    public static String jsonEvents(final int eventCount) {
+        final StringBuilder builder = new StringBuilder();
+
+        for (int i = 0; i < eventCount; i++) {
+            if (i > 0) {
+                builder.append("\n");
+            }
+            builder.append(jsonEvent());
+        }
+
+        return builder.toString();
+    }
+
+    public static String jsonEvent() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final String eventName = (nextEventNo == 0 ? "Event0000" : "Event0100");
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"" + eventName + "\",\n");
+        builder.append("  \"version\": \"0.0.1\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventNoName() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final String eventName = (nextEventNo == 0 ? "Event0000" : "Event0100");
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"namez\": \"" + eventName + "\",\n");
+        builder.append("  \"version\": \"0.0.1\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventBadName() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"%%%%\",\n");
+        builder.append("  \"version\": \"0.0.1\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventNoExName() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"I_DONT_EXIST\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventNoVersion() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final String eventName = (nextEventNo == 0 ? "Event0000" : "Event0100");
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"" + eventName + "\",\n");
+        builder.append("  \"versiion\": \"0.0.1\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventBadVersion() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final String eventName = (nextEventNo == 0 ? "Event0000" : "Event0100");
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"" + eventName + "\",\n");
+        builder.append("  \"version\": \"#####\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventNoExVersion() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"Event0000\",\n");
+        builder.append("  \"version\": \"1.2.3\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventNoNamespace() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final String eventName = (nextEventNo == 0 ? "Event0000" : "Event0100");
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpacee\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"" + eventName + "\",\n");
+        builder.append("  \"version\": \"0.0.1\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventBadNamespace() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final String eventName = (nextEventNo == 0 ? "Event0000" : "Event0100");
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"hello.&&&&\",\n");
+        builder.append("  \"name\": \"" + eventName + "\",\n");
+        builder.append("  \"version\": \"0.0.1\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventNoExNamespace() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"pie.in.the.sky\",\n");
+        builder.append("  \"name\": \"Event0000\",\n");
+        builder.append("  \"version\": \"0.0.1\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventNoSource() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final String eventName = (nextEventNo == 0 ? "Event0000" : "Event0100");
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"" + eventName + "\",\n");
+        builder.append("  \"version\": \"0.0.1\",\n");
+        builder.append("  \"sourcee\": \"test\",\n");
+        builder.append("  \"target\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventBadSource() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final String eventName = (nextEventNo == 0 ? "Event0000" : "Event0100");
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"" + eventName + "\",\n");
+        builder.append("  \"version\": \"0.0.1\",\n");
+        builder.append("  \"source\": \"%!@**@!\",\n");
+        builder.append("  \"target\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventNoTarget() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final String eventName = (nextEventNo == 0 ? "Event0000" : "Event0100");
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"" + eventName + "\",\n");
+        builder.append("  \"version\": \"0.0.1\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"targett\": \"apex\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventBadTarget() {
+        final Random rand = new Random();
+
+        final StringBuilder builder = new StringBuilder();
+
+        int nextEventNo = rand.nextInt(2);
+        final String eventName = (nextEventNo == 0 ? "Event0000" : "Event0100");
+        final int nextMatchCase = rand.nextInt(4);
+        final float nextTestTemperature = rand.nextFloat() * 10000;
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"" + eventName + "\",\n");
+        builder.append("  \"version\": \"0.0.1\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"KNIO(*S)A(S)D\",\n");
+        builder.append("  \"TestSlogan\": \"Test slogan for External Event" + (nextEventNo++) + "\",\n");
+        builder.append("  \"TestMatchCase\": " + nextMatchCase + ",\n");
+        builder.append("  \"TestTimestamp\": " + System.currentTimeMillis() + ",\n");
+        builder.append("  \"TestTemperature\": " + nextTestTemperature + "\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventMissingFields() {
+        final StringBuilder builder = new StringBuilder();
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"Event0000\",\n");
+        builder.append("  \"version\": \"0.0.1\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"apex\"\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static String jsonEventNullFields() {
+        final StringBuilder builder = new StringBuilder();
+
+        builder.append("{\n");
+        builder.append("  \"nameSpace\": \"org.onap.policy.apex.sample.events\",\n");
+        builder.append("  \"name\": \"Event0000\",\n");
+        builder.append("  \"version\": \"0.0.1\",\n");
+        builder.append("  \"source\": \"test\",\n");
+        builder.append("  \"target\": \"Apex\",\n");
+        builder.append("  \"TestSlogan\": null,\n");
+        builder.append("  \"TestMatchCase\": -1,\n");
+        builder.append("  \"TestTimestamp\": -1,\n");
+        builder.append("  \"TestTemperature\": -1.0\n");
+        builder.append("}");
+
+        return builder.toString();
+    }
+
+    public static void main(final String[] args) {
+        if (args.length != 1) {
+            System.err.println("usage EventGenerator #events");
+            return;
+        }
+
+        int eventCount = 0;
+        try {
+            eventCount = Integer.parseInt(args[0]);
+        } catch (final Exception e) {
+            System.err.println("usage EventGenerator #events");
+            e.printStackTrace();
+            return;
+        }
+
+        System.out.println(jsonEvents(eventCount));
+    }
+
+    public static int getNextEventNo() {
+        return nextEventNo;
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/event/TestJSONEventHandler.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/event/TestJSONEventHandler.java
new file mode 100644 (file)
index 0000000..be61b16
--- /dev/null
@@ -0,0 +1,316 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.handling.ApexModelException;
+import org.onap.policy.apex.model.basicmodel.handling.ApexModelReader;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvents;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
+import org.onap.policy.apex.model.utilities.TextFileUtils;
+import org.onap.policy.apex.service.engine.event.impl.jsonprotocolplugin.Apex2JSONEventConverter;
+import org.onap.policy.apex.service.engine.event.impl.jsonprotocolplugin.JSONEventProtocolParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class TestJSONEventHandler {
+    private static final XLogger logger = XLoggerFactory.getXLogger(TestJSONEventHandler.class);
+
+    @BeforeClass
+    public static void setupEventModel() throws IOException, ApexModelException {
+        final String policyModelString =
+                TextFileUtils.getTextFileAsString("src/test/resources/policymodels/SamplePolicyModelMVEL.json");
+        final ApexModelReader<AxPolicyModel> modelReader = new ApexModelReader<AxPolicyModel>(AxPolicyModel.class);
+        final AxPolicyModel apexPolicyModel = modelReader.read(new ByteArrayInputStream(policyModelString.getBytes()));
+
+        // Set up the models in the model service
+        apexPolicyModel.register();
+    }
+
+    @Before
+    public void initializeDefaultSchemaParameters() {
+        new SchemaParameters();
+    }
+
+    @Test
+    public void testJSONtoApexEvent() throws ApexException {
+        try {
+            final Apex2JSONEventConverter jsonEventConverter = new Apex2JSONEventConverter();
+            assertNotNull(jsonEventConverter);
+            jsonEventConverter.init(new JSONEventProtocolParameters());
+
+            final String apexEventJSONStringIn = JSONEventGenerator.jsonEvent();
+
+            logger.debug("input event\n" + apexEventJSONStringIn);
+
+            final List<ApexEvent> apexEventList = jsonEventConverter.toApexEvent(null, apexEventJSONStringIn);
+            for (final ApexEvent apexEvent : apexEventList) {
+                assertNotNull(apexEvent);
+
+                logger.debug(apexEvent.toString());
+
+                assertTrue(apexEvent.getName().equals("Event0000") || apexEvent.getName().equals("Event0100"));
+                assertTrue(apexEvent.getVersion().equals("0.0.1"));
+                assertTrue(apexEvent.getNameSpace().equals("org.onap.policy.apex.sample.events"));
+                assertTrue(apexEvent.getSource().equals("test"));
+                assertTrue(apexEvent.getTarget().equals("apex"));
+                assertTrue(apexEvent.get("TestSlogan").toString().startsWith("Test slogan for External Event"));
+
+                final Object testMatchCaseSelected = apexEvent.get("TestMatchCaseSelected");
+                assertTrue(testMatchCaseSelected == null);
+            }
+        } catch (final Exception e) {
+            e.printStackTrace();
+            throw new ApexException("Exception reading Apex event JSON file", e);
+        }
+    }
+
+    @Test
+    public void testJSONtoApexBadEvent() throws ApexException {
+        try {
+            final Apex2JSONEventConverter jsonEventConverter = new Apex2JSONEventConverter();
+            assertNotNull(jsonEventConverter);
+            jsonEventConverter.init(new JSONEventProtocolParameters());
+
+            String apexEventJSONStringIn = null;
+
+            try {
+                apexEventJSONStringIn = JSONEventGenerator.jsonEventNoName();
+                jsonEventConverter.toApexEvent(null, apexEventJSONStringIn);
+                fail("Test should throw an exception here");
+            } catch (final ApexEventException e) {
+                assertEquals("Failed to unmarshal JSON event: event received without mandatory parameter \"name\" ",
+                        e.getMessage().substring(0, 82));
+            }
+
+            try {
+                apexEventJSONStringIn = JSONEventGenerator.jsonEventBadName();
+                jsonEventConverter.toApexEvent(null, apexEventJSONStringIn);
+                fail("Test should throw an exception here");
+            } catch (final ApexEventException e) {
+                assertTrue(e.getMessage()
+                        .startsWith("Failed to unmarshal JSON event: field \"name\" with value \"%%%%\" is invalid"));
+            }
+
+            try {
+                apexEventJSONStringIn = JSONEventGenerator.jsonEventNoExName();
+                jsonEventConverter.toApexEvent(null, apexEventJSONStringIn);
+                fail("Test should throw an exception here");
+            } catch (final ApexEventException e) {
+                assertEquals("Failed to unmarshal JSON event: an event definition for an event named \"I_DONT_EXI",
+                        e.getMessage().substring(0, 82));
+            }
+
+            apexEventJSONStringIn = JSONEventGenerator.jsonEventNoVersion();
+            ApexEvent event = jsonEventConverter.toApexEvent(null, apexEventJSONStringIn).get(0);
+            assertEquals("0.0.1", event.getVersion());
+
+            try {
+                apexEventJSONStringIn = JSONEventGenerator.jsonEventBadVersion();
+                jsonEventConverter.toApexEvent(null, apexEventJSONStringIn);
+                fail("Test should throw an exception here");
+            } catch (final ApexEventException e) {
+                assertTrue(e.getMessage().startsWith(
+                        "Failed to unmarshal JSON event: field \"version\" with value \"#####\" is invalid"));
+            }
+
+            try {
+                apexEventJSONStringIn = JSONEventGenerator.jsonEventNoExVersion();
+                jsonEventConverter.toApexEvent(null, apexEventJSONStringIn);
+                fail("Test should throw an exception here");
+            } catch (final ApexEventException e) {
+                assertTrue(e.getMessage().startsWith(
+                        "Failed to unmarshal JSON event: an event definition for an event named \"Event0000\" with version \"1.2.3\" not found in Apex model"));
+            }
+
+            apexEventJSONStringIn = JSONEventGenerator.jsonEventNoNamespace();
+            event = jsonEventConverter.toApexEvent(null, apexEventJSONStringIn).get(0);
+            assertEquals("org.onap.policy.apex.sample.events", event.getNameSpace());
+
+            try {
+                apexEventJSONStringIn = JSONEventGenerator.jsonEventBadNamespace();
+                jsonEventConverter.toApexEvent(null, apexEventJSONStringIn);
+                fail("Test should throw an exception here");
+            } catch (final ApexEventException e) {
+                assertTrue(e.getMessage().startsWith(
+                        "Failed to unmarshal JSON event: field \"nameSpace\" with value \"hello.&&&&\" is invalid"));
+            }
+
+            try {
+                apexEventJSONStringIn = JSONEventGenerator.jsonEventNoExNamespace();
+                jsonEventConverter.toApexEvent(null, apexEventJSONStringIn);
+                fail("Test should throw an exception here");
+            } catch (final ApexEventException e) {
+                assertTrue(e.getMessage().startsWith(
+                        "Failed to unmarshal JSON event: namespace \"pie.in.the.sky\" on event \"Event0000\" "
+                                + "does not match namespace \"org.onap.policy.apex.sample.events\" for that event in the Apex model"));
+            }
+
+            apexEventJSONStringIn = JSONEventGenerator.jsonEventNoSource();
+            event = jsonEventConverter.toApexEvent(null, apexEventJSONStringIn).get(0);
+            assertEquals("Outside", event.getSource());
+
+            try {
+                apexEventJSONStringIn = JSONEventGenerator.jsonEventBadSource();
+                jsonEventConverter.toApexEvent(null, apexEventJSONStringIn);
+                fail("Test should throw an exception here");
+            } catch (final ApexEventException e) {
+                assertTrue(e.getMessage().startsWith(
+                        "Failed to unmarshal JSON event: field \"source\" with value \"%!@**@!\" is invalid"));
+            }
+
+            apexEventJSONStringIn = JSONEventGenerator.jsonEventNoTarget();
+            event = jsonEventConverter.toApexEvent(null, apexEventJSONStringIn).get(0);
+            assertEquals("Match", event.getTarget());
+
+            try {
+                apexEventJSONStringIn = JSONEventGenerator.jsonEventBadTarget();
+                jsonEventConverter.toApexEvent(null, apexEventJSONStringIn);
+                fail("Test should throw an exception here");
+            } catch (final ApexEventException e) {
+                assertTrue(e.getMessage().startsWith(
+                        "Failed to unmarshal JSON event: field \"target\" with value \"KNIO(*S)A(S)D\" is invalid"));
+            }
+
+            try {
+                apexEventJSONStringIn = JSONEventGenerator.jsonEventMissingFields();
+                jsonEventConverter.toApexEvent(null, apexEventJSONStringIn);
+                fail("Test should throw an exception here");
+            } catch (final ApexEventException e) {
+                assertTrue(e.getMessage().startsWith("Failed to unmarshal JSON event: error parsing Event0000:0.0.1 "
+                        + "event from Json. Field \"TestMatchCase\" is missing, but is mandatory."));
+            }
+
+            apexEventJSONStringIn = JSONEventGenerator.jsonEventNullFields();
+            event = jsonEventConverter.toApexEvent(null, apexEventJSONStringIn).get(0);
+            assertEquals(event.get("TestSlogan"), null);
+            assertEquals(event.get("TestMatchCase"), (byte) -1);
+            assertEquals(event.get("TestTimestamp"), (long) -1);
+            assertEquals(event.get("TestTemperature"), -1.0);
+
+            // Set the missing fields as optional in the model
+            final AxEvent eventDefinition = ModelService.getModel(AxEvents.class).get("Event0000");
+            eventDefinition.getParameterMap().get("TestSlogan").setOptional(true);
+            eventDefinition.getParameterMap().get("TestMatchCase").setOptional(true);
+            eventDefinition.getParameterMap().get("TestTimestamp").setOptional(true);
+            eventDefinition.getParameterMap().get("TestTemperature").setOptional(true);
+
+            apexEventJSONStringIn = JSONEventGenerator.jsonEventMissingFields();
+            event = jsonEventConverter.toApexEvent(null, apexEventJSONStringIn).get(0);
+            assertEquals(null, event.get("TestSlogan"));
+            assertEquals(null, event.get("TestMatchCase"));
+            assertEquals(null, event.get("TestTimestamp"));
+            assertEquals(null, event.get("TestTemperature"));
+        } catch (final Exception e) {
+            e.printStackTrace();
+            throw new ApexException("Exception reading Apex event JSON file", e);
+        }
+    }
+
+    @Test
+    public void testApexEventToJSON() throws ApexException {
+        try {
+            final Apex2JSONEventConverter jsonEventConverter = new Apex2JSONEventConverter();
+            assertNotNull(jsonEventConverter);
+
+            final Date event0000StartTime = new Date();
+            final Map<String, Object> event0000DataMap = new HashMap<String, Object>();
+            event0000DataMap.put("TestSlogan", "This is a test slogan");
+            event0000DataMap.put("TestMatchCase", 12345);
+            event0000DataMap.put("TestTimestamp", event0000StartTime.getTime());
+            event0000DataMap.put("TestTemperature", 34.5445667);
+
+            final ApexEvent apexEvent0000 =
+                    new ApexEvent("Event0000", "0.0.1", "org.onap.policy.apex.sample.events", "test", "apex");
+            apexEvent0000.putAll(event0000DataMap);
+
+            final String apexEvent0000JSONString = (String) jsonEventConverter.fromApexEvent(apexEvent0000);
+
+            logger.debug(apexEvent0000JSONString);
+
+            assertTrue(apexEvent0000JSONString.contains("\"name\": \"Event0000\""));
+            assertTrue(apexEvent0000JSONString.contains("\"version\": \"0.0.1\""));
+            assertTrue(apexEvent0000JSONString.contains("\"nameSpace\": \"org.onap.policy.apex.sample.events\""));
+            assertTrue(apexEvent0000JSONString.contains("\"source\": \"test\""));
+            assertTrue(apexEvent0000JSONString.contains("\"target\": \"apex\""));
+            assertTrue(apexEvent0000JSONString.contains("\"TestSlogan\": \"This is a test slogan\""));
+            assertTrue(apexEvent0000JSONString.contains("\"TestMatchCase\": 12345"));
+            assertTrue(apexEvent0000JSONString.contains("\"TestTimestamp\": " + event0000StartTime.getTime()));
+            assertTrue(apexEvent0000JSONString.contains("\"TestTemperature\": 34.5445667"));
+
+            final Date event0004StartTime = new Date(1434363272000L);
+            final Map<String, Object> event0004DataMap = new HashMap<String, Object>();
+            event0004DataMap.put("TestSlogan", "Test slogan for External Event");
+            event0004DataMap.put("TestMatchCase", new Integer(2));
+            event0004DataMap.put("TestTimestamp", new Long(event0004StartTime.getTime()));
+            event0004DataMap.put("TestTemperature", new Double(1064.43));
+            event0004DataMap.put("TestMatchCaseSelected", new Integer(2));
+            event0004DataMap.put("TestMatchStateTime", new Long(1434370506078L));
+            event0004DataMap.put("TestEstablishCaseSelected", new Integer(0));
+            event0004DataMap.put("TestEstablishStateTime", new Long(1434370506085L));
+            event0004DataMap.put("TestDecideCaseSelected", new Integer(3));
+            event0004DataMap.put("TestDecideStateTime", new Long(1434370506092L));
+            event0004DataMap.put("TestActCaseSelected", new Integer(2));
+            event0004DataMap.put("TestActStateTime", new Long(1434370506095L));
+
+            final ApexEvent apexEvent0004 =
+                    new ApexEvent("Event0004", "0.0.1", "org.onap.policy.apex.sample.events", "test", "apex");
+            apexEvent0004.putAll(event0004DataMap);
+
+            final String apexEvent0004JSONString = (String) jsonEventConverter.fromApexEvent(apexEvent0004);
+
+            logger.debug(apexEvent0004JSONString);
+
+            assertTrue(apexEvent0004JSONString.contains("\"name\": \"Event0004\""));
+            assertTrue(apexEvent0004JSONString.contains("\"version\": \"0.0.1\""));
+            assertTrue(apexEvent0004JSONString.contains("\"nameSpace\": \"org.onap.policy.apex.sample.events\""));
+            assertTrue(apexEvent0004JSONString.contains("\"source\": \"test\""));
+            assertTrue(apexEvent0004JSONString.contains("\"target\": \"apex\""));
+            assertTrue(apexEvent0004JSONString.contains("\"TestSlogan\": \"Test slogan for External Event\""));
+            assertTrue(apexEvent0004JSONString.contains("1434370506078"));
+            assertTrue(apexEvent0004JSONString.contains("1064.43"));
+        } catch (final Exception e) {
+            e.printStackTrace();
+            throw new ApexException("Exception reading Apex event JSON file", e);
+        }
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/event/TestJSONTaggedEventConsumer.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/event/TestJSONTaggedEventConsumer.java
new file mode 100644 (file)
index 0000000..b19ccee
--- /dev/null
@@ -0,0 +1,130 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.junit.Test;
+import org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer.CharacterDelimitedTextBlockReader;
+import org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer.TextBlock;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class TestJSONTaggedEventConsumer {
+
+    @Test
+    public void testGarbageText() throws IOException {
+        final InputStream jsonInputStream = new ByteArrayInputStream("hello there".getBytes());
+
+        final CharacterDelimitedTextBlockReader taggedReader = new CharacterDelimitedTextBlockReader('{', '}');
+        taggedReader.init(jsonInputStream);
+
+        final TextBlock textBlock = taggedReader.readTextBlock();
+        assertNull(textBlock.getText());
+        assertTrue(textBlock.isEndOfText());
+    }
+
+    @Test
+    public void testPartialEvent() throws IOException {
+        final InputStream jsonInputStream = new ByteArrayInputStream("\"TestTimestamp\": 1469781869268}".getBytes());
+
+        final CharacterDelimitedTextBlockReader taggedReader = new CharacterDelimitedTextBlockReader('{', '}');
+        taggedReader.init(jsonInputStream);
+
+        final TextBlock textBlock = taggedReader.readTextBlock();
+        assertNull(textBlock.getText());
+        assertTrue(textBlock.isEndOfText());
+    }
+
+    @Test
+    public void testFullEvent() throws IOException {
+        final InputStream jsonInputStream = new ByteArrayInputStream("{TestTimestamp\": 1469781869268}".getBytes());
+
+        final CharacterDelimitedTextBlockReader taggedReader = new CharacterDelimitedTextBlockReader('{', '}');
+        taggedReader.init(jsonInputStream);
+
+        TextBlock textBlock = taggedReader.readTextBlock();
+        assertEquals(textBlock.getText(), "{TestTimestamp\": 1469781869268}");
+
+        textBlock = taggedReader.readTextBlock();
+        assertNull(textBlock.getText());
+        assertTrue(textBlock.isEndOfText());
+    }
+
+    @Test
+    public void testFullEventGarbageBefore() throws IOException {
+        final InputStream jsonInputStream =
+                new ByteArrayInputStream("Garbage{TestTimestamp\": 1469781869268}".getBytes());
+
+        final CharacterDelimitedTextBlockReader taggedReader = new CharacterDelimitedTextBlockReader('{', '}');
+        taggedReader.init(jsonInputStream);
+
+        TextBlock textBlock = taggedReader.readTextBlock();
+        assertEquals(textBlock.getText(), "{TestTimestamp\": 1469781869268}");
+        assertFalse(textBlock.isEndOfText());
+
+        textBlock = taggedReader.readTextBlock();
+        assertNull(textBlock.getText());
+        assertTrue(textBlock.isEndOfText());
+    }
+
+    @Test
+    public void testFullEventGarbageBeforeAfter() throws IOException {
+        final InputStream jsonInputStream =
+                new ByteArrayInputStream("Garbage{TestTimestamp\": 1469781869268}Rubbish".getBytes());
+
+        final CharacterDelimitedTextBlockReader taggedReader = new CharacterDelimitedTextBlockReader('{', '}');
+        taggedReader.init(jsonInputStream);
+
+        TextBlock textBlock = taggedReader.readTextBlock();
+        assertEquals(textBlock.getText(), "{TestTimestamp\": 1469781869268}");
+        assertFalse(textBlock.isEndOfText());
+
+        textBlock = taggedReader.readTextBlock();
+        assertNull(textBlock.getText());
+        assertTrue(textBlock.isEndOfText());
+    }
+
+    @Test
+    public void testFullEventGarbageAfter() throws IOException {
+        final InputStream jsonInputStream =
+                new ByteArrayInputStream("{TestTimestamp\": 1469781869268}Rubbish".getBytes());
+
+        final CharacterDelimitedTextBlockReader taggedReader = new CharacterDelimitedTextBlockReader('{', '}');
+        taggedReader.init(jsonInputStream);
+
+        TextBlock textBlock = taggedReader.readTextBlock();
+        assertEquals(textBlock.getText(), "{TestTimestamp\": 1469781869268}");
+        assertFalse(textBlock.isEndOfText());
+
+        textBlock = taggedReader.readTextBlock();
+        assertNull(textBlock.getText());
+        assertTrue(textBlock.isEndOfText());
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/event/TestPluginFactories.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/event/TestPluginFactories.java
new file mode 100644 (file)
index 0000000..5d77bfd
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.event;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map.Entry;
+
+import org.junit.Test;
+import org.onap.policy.apex.service.engine.event.impl.EventConsumerFactory;
+import org.onap.policy.apex.service.engine.event.impl.EventProducerFactory;
+import org.onap.policy.apex.service.engine.main.ApexCommandLineArguments;
+
+import org.onap.policy.apex.service.parameters.ApexParameterException;
+import org.onap.policy.apex.service.parameters.ApexParameterHandler;
+import org.onap.policy.apex.service.parameters.ApexParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @author John Keeney (john.keeney@ericsson.com)
+ */
+public class TestPluginFactories {
+
+    @Test
+    public void testEventConsumerFactory() throws ApexEventException, ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/factoryGoodParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+
+        for (final Entry<String, EventHandlerParameters> ce : parameters.getEventInputParameters().entrySet()) {
+            final ApexEventConsumer consumer = new EventConsumerFactory().createConsumer(
+                    parameters.getEngineServiceParameters().getName() + "_consumer_" + ce.getKey(), ce.getValue());
+            assertNotNull(consumer);
+        }
+
+        for (final Entry<String, EventHandlerParameters> pe : parameters.getEventOutputParameters().entrySet()) {
+            final ApexEventProducer producer = new EventProducerFactory().createProducer(
+                    parameters.getEngineServiceParameters().getName() + "_producer_" + pe.getKey(), pe.getValue());
+            assertNotNull(producer);
+        }
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/main/TestApexCommandLineArguments.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/main/TestApexCommandLineArguments.java
new file mode 100644 (file)
index 0000000..247f9b9
--- /dev/null
@@ -0,0 +1,186 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.main;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class TestApexCommandLineArguments {
+
+    @Test
+    public void testCommandLineArguments() {
+        final ApexCommandLineArguments apexArguments = new ApexCommandLineArguments();
+
+        final String[] args00 = {""};
+        try {
+            apexArguments.parse(args00);
+            apexArguments.validate();
+            fail("Test should throw an exception here");
+        } catch (final ApexException e) {
+            assertEquals("Apex configuration file was not specified as an argument", e.getMessage());
+        }
+
+        final String[] args01 = {"-h"};
+        try {
+            final String result = apexArguments.parse(args01);
+            assertTrue(result.startsWith("usage: org.onap.policy.apex.service.engine.main.ApexMain [options...]"));
+        } catch (final ApexException e) {
+            e.printStackTrace();
+            fail("Test should not throw an exception");
+        }
+
+        final String[] args02 = {"-v"};
+        try {
+            final String result = apexArguments.parse(args02);
+            assertTrue(result.startsWith("Apex Adaptive Policy Engine"));
+        } catch (final ApexException e) {
+            e.printStackTrace();
+            fail("Test should not throw an exception");
+        }
+
+        final String[] args03 = {"-v", "-h"};
+        try {
+            final String result = apexArguments.parse(args03);
+            assertTrue(result.startsWith("usage: org.onap.policy.apex.service.engine.main.ApexMain [options...]"));
+        } catch (final ApexException e) {
+            e.printStackTrace();
+            fail("Test should not throw an exception");
+        }
+
+        final String[] args04 = {"-h", "-v"};
+        try {
+            final String result = apexArguments.parse(args04);
+            assertTrue(result.startsWith("usage: org.onap.policy.apex.service.engine.main.ApexMain [options...]"));
+        } catch (final ApexException e) {
+            e.printStackTrace();
+            fail("Test should not throw an exception");
+        }
+
+        final String[] args05 = {"-a"};
+        try {
+            apexArguments.parse(args05);
+        } catch (final ApexException e) {
+            assertEquals("invalid command line arguments specified : Unrecognized option: -a", e.getMessage());
+        }
+
+        final String[] args06 = {"-c", "hello", "-m", "goodbye", "-h", "-v"};
+        try {
+            final String result = apexArguments.parse(args06);
+            assertTrue(result.startsWith("usage: org.onap.policy.apex.service.engine.main.ApexMain [options...]"));
+        } catch (final ApexException e) {
+            assertEquals("invalid command line arguments specified : Unrecognized option: -a", e.getMessage());
+        }
+
+        final String[] args07 = {"-c", "hello", "-m", "goodbye", "-h", "aaa"};
+        try {
+            final String result = apexArguments.parse(args07);
+            assertTrue(result.startsWith("usage: org.onap.policy.apex.service.engine.main.ApexMain [options...]"));
+        } catch (final ApexException e) {
+            assertEquals("too many command line arguments specified : [-c, hello, -m, goodbye, -h, aaa]",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void testCommandLineFileParameters() {
+        final ApexCommandLineArguments apexArguments = new ApexCommandLineArguments();
+
+        final String[] args00 = {"-c", "zooby"};
+        try {
+            apexArguments.parse(args00);
+            apexArguments.validate();
+            fail("Test should throw an exception here");
+        } catch (final ApexException e) {
+            assertEquals("Apex configuration file \"zooby\" does not exist", e.getMessage());
+        }
+
+        final String[] args01 = {"-c"};
+        try {
+            apexArguments.parse(args01);
+            apexArguments.validate();
+            fail("Test should throw an exception here");
+        } catch (final ApexException e) {
+            assertEquals("invalid command line arguments specified : Missing argument for option: c", e.getMessage());
+        }
+
+        final String[] args02 = {"-c", "src/test/resources/parameters/goodParams.json"};
+        try {
+            apexArguments.parse(args02);
+            apexArguments.validate();
+        } catch (final ApexException e) {
+            e.printStackTrace();
+            fail("Test should not throw an exception");
+        }
+
+        final String[] args03 = {"-c", "src/test/resources/parameters/goodParams.json", "-m", "zooby"};
+        try {
+            apexArguments.parse(args03);
+            apexArguments.validate();
+            fail("Test should throw an exception here");
+        } catch (final ApexException e) {
+            assertEquals("Apex model file \"zooby\" does not exist", e.getMessage());
+        }
+
+        final String[] args04 = {"-m"};
+        try {
+            apexArguments.parse(args04);
+            apexArguments.validate();
+            fail("Test should throw an exception here");
+        } catch (final ApexException e) {
+            assertEquals("invalid command line arguments specified : Missing argument for option: m", e.getMessage());
+        }
+
+        final String[] args05 = {"-c", "src/test/resources/parameters/goodParams.json", "-m"};
+        try {
+            apexArguments.parse(args05);
+            apexArguments.validate();
+            fail("Test should throw an exception here");
+        } catch (final ApexException e) {
+            assertEquals("invalid command line arguments specified : Missing argument for option: m", e.getMessage());
+        }
+
+        final String[] args06 = {"-c", "src/test/resources/parameters/goodParams.json", "-m",
+                "src/test/resources/main/DummyModelFile.json"};
+        try {
+            apexArguments.parse(args06);
+            apexArguments.validate();
+        } catch (final ApexException e) {
+            e.printStackTrace();
+            fail("Test should not throw an exception");
+        }
+
+        final String[] args07 = {"-c", "parameters/goodParams.json", "-m", "main/DummyModelFile.json"};
+        try {
+            apexArguments.parse(args07);
+            apexArguments.validate();
+        } catch (final ApexException e) {
+            e.printStackTrace();
+            fail("Test should not throw an exception");
+        }
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/ContextParameterTests.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/ContextParameterTests.java
new file mode 100644 (file)
index 0000000..33bcd0d
--- /dev/null
@@ -0,0 +1,276 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.parameters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.onap.policy.apex.service.engine.main.ApexCommandLineArguments;
+import org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperDistributorParameters;
+import org.onap.policy.apex.service.parameters.ApexParameterException;
+import org.onap.policy.apex.service.parameters.ApexParameterHandler;
+import org.onap.policy.apex.service.parameters.ApexParameters;
+
+/**
+ * Test for an empty parameter file
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ContextParameterTests {
+
+    @Test
+    public void noParamsTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceContextNoParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceContextNoParams.json\"\n"
+                            + "(ApexParameterRuntimeException):could not find field \"parameterClassName\" in \"contextParameters\" entry",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void badParamsTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceContextBadParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceContextBadParams.json\"\n"
+                            + "(ApexParameterRuntimeException):failed to deserialize the parameters for \"contextParameters\" to parameter class \"hello\"\n"
+                            + "java.lang.ClassNotFoundException: hello",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void badPluginParamNameTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceContextBadPluginNameParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceContextBadPluginNameParams.json\"\n"
+                            + "(ApexParameterRuntimeException):could not find field \"parameterClassName\" in \"contextParameters\" entry",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void badClassParamTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceContextBadClassParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceContextBadClassParams.json\"\n"
+                            + "(ApexParameterRuntimeException):failed to deserialize the parameters for \"contextParameters\" to parameter class \"java.lang.Integer\"\n"
+                            + "com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected NUMBER but was BEGIN_OBJECT at path $",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void badPluginClassTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceContextBadPluginClassParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceContextBadPluginClassParams.json\"\n"
+                            + "(ClassCastException):org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters cannot be cast to org.onap.policy.apex.context.parameters.ContextParameters",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void okFlushParamTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceContextOKFlushParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+            assertEquals("org.onap.policy.apex.context.parameters.ContextParameters", parameters
+                    .getEngineServiceParameters().getEngineParameters().getContextParameters().getParameterClassName());
+            assertEquals(123456, parameters.getEngineServiceParameters().getEngineParameters().getContextParameters()
+                    .getPersistorParameters().getFlushPeriod());
+        } catch (final ApexParameterException e) {
+            fail("This test should not throw any exception: " + e.getMessage());
+        }
+    }
+
+    @Test
+    public void okDefaultParamTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceContextOKDefaultParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+            assertEquals("org.onap.policy.apex.context.parameters.ContextParameters", parameters
+                    .getEngineServiceParameters().getEngineParameters().getContextParameters().getParameterClassName());
+            assertEquals(300000, parameters.getEngineServiceParameters().getEngineParameters().getContextParameters()
+                    .getPersistorParameters().getFlushPeriod());
+        } catch (final ApexParameterException e) {
+            fail("This test should not throw any exception: " + e.getMessage());
+        }
+    }
+
+    @Test
+    public void okDistParamTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceContextOKDistParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+            assertEquals("org.onap.policy.apex.context.parameters.ContextParameters", parameters
+                    .getEngineServiceParameters().getEngineParameters().getContextParameters().getParameterClassName());
+            assertEquals("org.onap.policy.apex.context.parameters.DistributorParameters",
+                    parameters.getEngineServiceParameters().getEngineParameters().getContextParameters()
+                            .getDistributorParameters().getParameterClassName());
+        } catch (final ApexParameterException e) {
+            fail("This test should not throw any exception: " + e.getMessage());
+        }
+    }
+
+    @Test
+    public void okFullDefaultParamTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/goodParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+            assertEquals("org.onap.policy.apex.context.parameters.ContextParameters", parameters
+                    .getEngineServiceParameters().getEngineParameters().getContextParameters().getParameterClassName());
+            assertEquals("org.onap.policy.apex.context.parameters.DistributorParameters",
+                    parameters.getEngineServiceParameters().getEngineParameters().getContextParameters()
+                            .getDistributorParameters().getParameterClassName());
+            assertEquals("org.onap.policy.apex.context.parameters.LockManagerParameters",
+                    parameters.getEngineServiceParameters().getEngineParameters().getContextParameters()
+                            .getLockManagerParameters().getParameterClassName());
+            assertEquals("org.onap.policy.apex.context.parameters.PersistorParameters",
+                    parameters.getEngineServiceParameters().getEngineParameters().getContextParameters()
+                            .getPersistorParameters().getParameterClassName());
+            assertEquals(300000, parameters.getEngineServiceParameters().getEngineParameters().getContextParameters()
+                    .getPersistorParameters().getFlushPeriod());
+        } catch (final ApexParameterException e) {
+            fail("This test should not throw any exception: " + e.getMessage());
+        }
+    }
+
+    @Test
+    public void okFullParamTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceContextOKFullParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+            assertEquals("org.onap.policy.apex.context.parameters.ContextParameters", parameters
+                    .getEngineServiceParameters().getEngineParameters().getContextParameters().getParameterClassName());
+            assertEquals("org.onap.policy.apex.context.parameters.LockManagerParameters",
+                    parameters.getEngineServiceParameters().getEngineParameters().getContextParameters()
+                            .getLockManagerParameters().getParameterClassName());
+            assertEquals("org.onap.policy.apex.context.parameters.PersistorParameters",
+                    parameters.getEngineServiceParameters().getEngineParameters().getContextParameters()
+                            .getPersistorParameters().getParameterClassName());
+            assertEquals(123456, parameters.getEngineServiceParameters().getEngineParameters().getContextParameters()
+                    .getPersistorParameters().getFlushPeriod());
+
+            final SuperDooperDistributorParameters infinispanParameters =
+                    (SuperDooperDistributorParameters) parameters.getEngineServiceParameters().getEngineParameters()
+                            .getContextParameters().getDistributorParameters();
+            assertEquals("org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperDistributorParameters",
+                    infinispanParameters.getParameterClassName());
+            assertEquals("my/lovely/configFile.xml", infinispanParameters.getConfigFile());
+            assertEquals("holy/stone.xml", infinispanParameters.getJgroupsFile());
+            assertEquals(false, infinispanParameters.preferIPv4Stack());
+            assertEquals("fatherted", infinispanParameters.getjGroupsBindAddress());
+
+        } catch (final ApexParameterException e) {
+            fail("This test should not throw any exception: " + e.getMessage());
+        }
+    }
+
+    @Test
+    public void badClassDistParamTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceContextBadClassDistParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceContextBadClassDistParams.json\"\n"
+                            + "(ClassCastException):org.onap.policy.apex.context.parameters.ContextParameters cannot be cast to org.onap.policy.apex.context.parameters.DistributorParameters",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void badClassLockParamTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceContextBadClassLockParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceContextBadClassLockParams.json\"\n"
+                            + "(ClassCastException):org.onap.policy.apex.context.parameters.ContextParameters cannot be cast to org.onap.policy.apex.context.parameters.LockManagerParameters",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void badClassPersistParamTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceContextBadClassPersistParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceContextBadClassPersistParams.json\"\n"
+                            + "(ClassCastException):org.onap.policy.apex.context.parameters.ContextParameters cannot be cast to org.onap.policy.apex.context.parameters.PersistorParameters",
+                    e.getMessage());
+        }
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/ExecutorParameterTests.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/ExecutorParameterTests.java
new file mode 100644 (file)
index 0000000..b14cc22
--- /dev/null
@@ -0,0 +1,184 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.parameters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.onap.policy.apex.service.engine.main.ApexCommandLineArguments;
+import org.onap.policy.apex.service.parameters.ApexParameterException;
+import org.onap.policy.apex.service.parameters.ApexParameterHandler;
+import org.onap.policy.apex.service.parameters.ApexParameters;
+
+/**
+ * Test for an empty parameter file
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ExecutorParameterTests {
+
+    @Test
+    public void noParamsTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceExecutorNoParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+            assertEquals(0,
+                    parameters.getEngineServiceParameters().getEngineParameters().getExecutorParameterMap().size());
+        } catch (final ApexParameterException e) {
+            fail("This test should not throw any exception: " + e.getMessage());
+        }
+    }
+
+    @Test
+    public void badParamsTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceExecutorBadParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceExecutorBadParams.json\"\n"
+                            + "(ApexParameterRuntimeException):value of \"executorParameters:ZOOBY\" entry is not a parameter JSON object",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void noExecutorParamsTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceExecutorNoExecutorParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceExecutorNoExecutorParams.json\"\n"
+                            + "(ApexParameterRuntimeException):no \"executorParameters\" entry found in parameters, at least one executor parameter entry must be specified",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void emptyParamsTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceExecutorEmptyParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceExecutorEmptyParams.json\"\n"
+                            + "(ApexParameterRuntimeException):could not find field \"parameterClassName\" in \"executorParameters:ZOOBY\" entry",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void badPluginParamNameTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceExecutorBadPluginNameParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceExecutorBadPluginNameParams.json\"\n"
+                            + "(ApexParameterRuntimeException):could not find field \"parameterClassName\" in \"executorParameters:ZOOBY\" entry",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void badPluginParamObjectTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceExecutorBadPluginValueObjectParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceExecutorBadPluginValueObjectParams.json\"\n"
+                            + "(ApexParameterRuntimeException):value for field \"parameterClassName\" in \"executorParameters:LOOBY\" entry is not a plain string",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void badPluginParamBlankTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceExecutorBadPluginValueBlankParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceExecutorBadPluginValueBlankParams.json\"\n"
+                            + "(ApexParameterRuntimeException):value for field \"parameterClassName\" in \"executorParameters:LOOBY\" entry is not specified or is blank",
+                    e.getMessage());
+        }
+    }
+
+
+    @Test
+    public void badPluginParamValueTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/serviceExecutorBadPluginValueParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/serviceExecutorBadPluginValueParams.json\"\n"
+                            + "(ApexParameterRuntimeException):failed to deserialize the parameters for \"executorParameters:LOOBY\" to parameter class \"helloworld\"\n"
+                            + "java.lang.ClassNotFoundException: helloworld",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void goodParametersTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/goodParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+
+            assertEquals("MyApexEngine", parameters.getEngineServiceParameters().getName());
+            assertEquals("0.0.1", parameters.getEngineServiceParameters().getVersion());
+            assertEquals(45, parameters.getEngineServiceParameters().getId());
+            assertEquals(19, parameters.getEngineServiceParameters().getInstanceCount());
+            assertEquals(65522, parameters.getEngineServiceParameters().getDeploymentPort());
+        } catch (final ApexParameterException e) {
+            fail("This test should not throw any exception: " + e.getMessage());
+        }
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/ParameterTests.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/ParameterTests.java
new file mode 100644 (file)
index 0000000..6ea8d59
--- /dev/null
@@ -0,0 +1,239 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.parameters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.consumer.ApexFileEventConsumer;
+import org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.producer.ApexFileEventProducer;
+import org.onap.policy.apex.service.engine.main.ApexCommandLineArguments;
+import org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters;
+import org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperEventProducer;
+import org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperEventSubscriber;
+import org.onap.policy.apex.service.parameters.ApexParameterException;
+import org.onap.policy.apex.service.parameters.ApexParameterHandler;
+import org.onap.policy.apex.service.parameters.ApexParameters;
+import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters;
+
+/**
+ * Test for an empty parameter file
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ParameterTests {
+    @Test
+    public void invalidParametersNoFileTest() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/invalidNoFile.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertTrue(e.getMessage().startsWith("error reading parameters from \"src"));
+            assertTrue(e.getMessage().contains("FileNotFoundException"));
+        }
+    }
+
+    @Test
+    public void invalidParametersEmptyTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/empty.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertTrue(e.getMessage()
+                    .startsWith("validation error(s) on parameters from \"src/test/resources/parameters/empty.json\""));
+        }
+    }
+
+    @Test
+    public void invalidParametersNoParamsTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/noParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals("validation error(s) on parameters from \"src/test/resources/parameters/noParams.json\"\n"
+                    + "Apex parameters invalid\n" + " engine service parameters are not specified\n"
+                    + " at least one event output and one event input must be specified", e.getMessage());
+        }
+    }
+
+    @Test
+    public void invalidParametersBlankParamsTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/blankParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+
+            assertEquals("validation error(s) on parameters from \"src/test/resources/parameters/blankParams.json\"\n"
+                    + "Apex parameters invalid\n" + " engine service parameters invalid\n"
+                    + "  id not specified or specified value [-1] invalid, must be specified as id >= 0\n"
+                    + " at least one event output and one event input must be specified", e.getMessage());
+        }
+    }
+
+    @Test
+    public void invalidParametersTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/badParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "validation error(s) on parameters from \"src/test/resources/parameters/badParams.json\"\n"
+                            + "Apex parameters invalid\n" + " engine service parameters invalid\n"
+                            + "  name [hello there] and/or version [PA1] invalid\n"
+                            + "   parameter \"name\": value \"hello there\", does not match regular expression \"[A-Za-z0-9\\-_\\.]+\"\n"
+                            + "  id not specified or specified value [-45] invalid, must be specified as id >= 0\n"
+                            + "  instanceCount [-345] invalid, must be specified as instanceCount >= 1\n"
+                            + "  deploymentPort [65536] invalid, must be specified as 1024 <= port <= 65535\n"
+                            + "  policyModelFileName [/some/file/name.xml] not found or is not a plain file\n"
+                            + " event input (TheFileConsumer1) parameters invalid\n"
+                            + "  fileName not specified or is blank or null, it must be specified as a valid file location\n"
+                            + " event output (FirstProducer) parameters invalid\n"
+                            + "  fileName not specified or is blank or null, it must be specified as a valid file location",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void goodParametersTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/goodParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+
+            assertEquals(2, parameters.getEventInputParameters().size());
+            assertEquals(2, parameters.getEventOutputParameters().size());
+
+            assertTrue(parameters.getEventOutputParameters().containsKey("FirstProducer"));
+            assertTrue(parameters.getEventOutputParameters().containsKey("MyOtherProducer"));
+            assertEquals("FILE", parameters.getEventOutputParameters().get("FirstProducer")
+                    .getCarrierTechnologyParameters().getLabel());
+            assertEquals("FILE", parameters.getEventOutputParameters().get("MyOtherProducer")
+                    .getCarrierTechnologyParameters().getLabel());
+            assertEquals(ApexFileEventProducer.class.getCanonicalName(), parameters.getEventOutputParameters()
+                    .get("MyOtherProducer").getCarrierTechnologyParameters().getEventProducerPluginClass());
+            assertEquals(ApexFileEventConsumer.class.getCanonicalName(), parameters.getEventOutputParameters()
+                    .get("MyOtherProducer").getCarrierTechnologyParameters().getEventConsumerPluginClass());
+            assertEquals("JSON",
+                    parameters.getEventOutputParameters().get("FirstProducer").getEventProtocolParameters().getLabel());
+            assertEquals("JSON", parameters.getEventOutputParameters().get("MyOtherProducer")
+                    .getEventProtocolParameters().getLabel());
+
+            assertTrue(parameters.getEventInputParameters().containsKey("TheFileConsumer1"));
+            assertTrue(parameters.getEventInputParameters().containsKey("MySuperDooperConsumer1"));
+            assertEquals("FILE", parameters.getEventInputParameters().get("TheFileConsumer1")
+                    .getCarrierTechnologyParameters().getLabel());
+            assertEquals("SUPER_DOOPER", parameters.getEventInputParameters().get("MySuperDooperConsumer1")
+                    .getCarrierTechnologyParameters().getLabel());
+            assertEquals("JSON", parameters.getEventInputParameters().get("TheFileConsumer1")
+                    .getEventProtocolParameters().getLabel());
+            assertEquals("SUPER_TOK_DEL", parameters.getEventInputParameters().get("MySuperDooperConsumer1")
+                    .getEventProtocolParameters().getLabel());
+            assertEquals(ApexFileEventProducer.class.getCanonicalName(), parameters.getEventInputParameters()
+                    .get("TheFileConsumer1").getCarrierTechnologyParameters().getEventProducerPluginClass());
+            assertEquals(ApexFileEventConsumer.class.getCanonicalName(), parameters.getEventInputParameters()
+                    .get("TheFileConsumer1").getCarrierTechnologyParameters().getEventConsumerPluginClass());
+            assertEquals(SuperDooperEventProducer.class.getCanonicalName(), parameters.getEventInputParameters()
+                    .get("MySuperDooperConsumer1").getCarrierTechnologyParameters().getEventProducerPluginClass());
+            assertEquals(SuperDooperEventSubscriber.class.getCanonicalName(), parameters.getEventInputParameters()
+                    .get("MySuperDooperConsumer1").getCarrierTechnologyParameters().getEventConsumerPluginClass());
+        } catch (final ApexParameterException e) {
+            fail("This test should not throw an exception");
+        }
+    }
+
+    @Test
+    public void superDooperParametersTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/superDooperParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+
+            assertEquals("MyApexEngine", parameters.getEngineServiceParameters().getName());
+            assertEquals("0.0.1", parameters.getEngineServiceParameters().getVersion());
+            assertEquals(45, parameters.getEngineServiceParameters().getId());
+            assertEquals(345, parameters.getEngineServiceParameters().getInstanceCount());
+            assertEquals(65522, parameters.getEngineServiceParameters().getDeploymentPort());
+
+            final CarrierTechnologyParameters prodCT =
+                    parameters.getEventOutputParameters().get("FirstProducer").getCarrierTechnologyParameters();
+            final EventProtocolParameters prodEP =
+                    parameters.getEventOutputParameters().get("FirstProducer").getEventProtocolParameters();
+            final CarrierTechnologyParameters consCT =
+                    parameters.getEventInputParameters().get("MySuperDooperConsumer1").getCarrierTechnologyParameters();
+            final EventProtocolParameters consEP =
+                    parameters.getEventInputParameters().get("MySuperDooperConsumer1").getEventProtocolParameters();
+
+            assertEquals("SUPER_DOOPER", prodCT.getLabel());
+            assertEquals("SUPER_TOK_DEL", prodEP.getLabel());
+            assertEquals("SUPER_DOOPER", consCT.getLabel());
+            assertEquals("JSON", consEP.getLabel());
+
+            assertTrue(prodCT instanceof SuperDooperCarrierTechnologyParameters);
+
+            final SuperDooperCarrierTechnologyParameters superDooperParameters =
+                    (SuperDooperCarrierTechnologyParameters) prodCT;
+            assertEquals("somehost:12345", superDooperParameters.getBootstrapServers());
+            assertEquals("0", superDooperParameters.getAcks());
+            assertEquals(25, superDooperParameters.getRetries());
+            assertEquals(98765, superDooperParameters.getBatchSize());
+            assertEquals(21, superDooperParameters.getLingerTime());
+            assertEquals(50505050, superDooperParameters.getBufferMemory());
+            assertEquals("first-group-id", superDooperParameters.getGroupId());
+            assertFalse(superDooperParameters.isEnableAutoCommit());
+            assertEquals(441, superDooperParameters.getAutoCommitTime());
+            assertEquals(987, superDooperParameters.getSessionTimeout());
+            assertEquals("producer-out", superDooperParameters.getProducerTopic());
+            assertEquals(101, superDooperParameters.getConsumerPollTime());
+            assertEquals("some.key.serailizer", superDooperParameters.getKeySerializer());
+            assertEquals("some.value.serailizer", superDooperParameters.getValueSerializer());
+            assertEquals("some.key.deserailizer", superDooperParameters.getKeyDeserializer());
+            assertEquals("some.value.deserailizer", superDooperParameters.getValueDeserializer());
+
+            final String[] consumerTopics = {"consumer-out-0", "consumer-out-1", "consumer-out-2"};
+            assertEquals(Arrays.asList(consumerTopics), superDooperParameters.getConsumerTopicList());
+        } catch (final ApexParameterException e) {
+            fail("This test should not throw an exception");
+        }
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/ProducerConsumerTests.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/ProducerConsumerTests.java
new file mode 100644 (file)
index 0000000..dad9899
--- /dev/null
@@ -0,0 +1,266 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.parameters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.FILECarrierTechnologyParameters;
+import org.onap.policy.apex.service.engine.main.ApexCommandLineArguments;
+import org.onap.policy.apex.service.parameters.ApexParameterException;
+import org.onap.policy.apex.service.parameters.ApexParameterHandler;
+import org.onap.policy.apex.service.parameters.ApexParameters;
+
+/**
+ * Test for an empty parameter file
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ProducerConsumerTests {
+    @Test
+    public void goodParametersTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/goodParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+
+            assertEquals("MyApexEngine", parameters.getEngineServiceParameters().getName());
+            assertEquals("0.0.1", parameters.getEngineServiceParameters().getVersion());
+            assertEquals(45, parameters.getEngineServiceParameters().getId());
+            assertEquals(19, parameters.getEngineServiceParameters().getInstanceCount());
+            assertEquals(65522, parameters.getEngineServiceParameters().getDeploymentPort());
+            assertEquals("FILE", parameters.getEventOutputParameters().get("FirstProducer")
+                    .getCarrierTechnologyParameters().getLabel());
+            assertEquals("JSON",
+                    parameters.getEventOutputParameters().get("FirstProducer").getEventProtocolParameters().getLabel());
+            assertEquals("FILE", parameters.getEventOutputParameters().get("MyOtherProducer")
+                    .getCarrierTechnologyParameters().getLabel());
+            assertEquals("JSON", parameters.getEventOutputParameters().get("MyOtherProducer")
+                    .getEventProtocolParameters().getLabel());
+            assertEquals("FILE", parameters.getEventInputParameters().get("TheFileConsumer1")
+                    .getCarrierTechnologyParameters().getLabel());
+            assertEquals("JSON", parameters.getEventInputParameters().get("TheFileConsumer1")
+                    .getEventProtocolParameters().getLabel());
+            assertEquals("SUPER_DOOPER", parameters.getEventInputParameters().get("MySuperDooperConsumer1")
+                    .getCarrierTechnologyParameters().getLabel());
+            assertEquals("SUPER_TOK_DEL", parameters.getEventInputParameters().get("MySuperDooperConsumer1")
+                    .getEventProtocolParameters().getLabel());
+        } catch (final ApexParameterException e) {
+            fail("This test should not throw an exception");
+        }
+    }
+
+    @Test
+    public void noCarrierTechnology() {
+        final String[] args = {"-c", "src/test/resources/parameters/prodConsNoCT.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals("validation error(s) on parameters from \"src/test/resources/parameters/prodConsNoCT.json\"\n"
+                    + "Apex parameters invalid\n" + " event input (aConsumer) parameters invalid\n"
+                    + "  event handler carrierTechnologyParameters not specified or blank", e.getMessage());
+        }
+    }
+
+    @Test
+    public void noEventProcol() {
+        final String[] args = {"-c", "src/test/resources/parameters/prodConsNoEP.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals("validation error(s) on parameters from \"src/test/resources/parameters/prodConsNoEP.json\"\n"
+                    + "Apex parameters invalid\n" + " event input (aConsumer) parameters invalid\n"
+                    + "  fileName not specified or is blank or null, it must be specified as a valid file location\n"
+                    + " event output (aProducer) parameters invalid\n"
+                    + "  event handler eventProtocolParameters not specified or blank", e.getMessage());
+        }
+    }
+
+    @Test
+    public void noCarrierTechnologyParClass() {
+        final String[] args = {"-c", "src/test/resources/parameters/prodConsNoCTParClass.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/prodConsNoCTParClass.json\"\n"
+                            + "(ApexParameterRuntimeException):carrier technology \"SUPER_DOOPER\" does not match plugin \"FILE\" in "
+                            + "\"com.ericsson.apex.service.engine.event.impl.filecarrierplugin.FILECarrierTechnologyParameters\", "
+                            + "specify correct carrier technology parameter plugin in parameter \"parameterClassName\"",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void mismatchCarrierTechnologyParClass() {
+        final String[] args = {"-c", "src/test/resources/parameters/prodConsMismatchCTParClass.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/prodConsMismatchCTParClass.json\"\n"
+                            + "(ApexParameterRuntimeException):carrier technology \"SUPER_LOOPER\" does not match plugin \"SUPER_DOOPER\" in "
+                            + "\"com.ericsson.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters\", "
+                            + "specify correct carrier technology parameter plugin in parameter \"parameterClassName\"",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void wrongTypeCarrierTechnologyParClass() {
+        final String[] args = {"-c", "src/test/resources/parameters/prodConsWrongTypeCTParClass.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/prodConsWrongTypeCTParClass.json\"\n"
+                            + "(ApexParameterRuntimeException):could not create default parameters for carrier technology \"SUPER_DOOPER\"\n"
+                            + "com.ericsson.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters "
+                            + "cannot be cast to com.ericsson.apex.service.parameters.carriertechnology.CarrierTechnologyParameters",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void okFileNameCarrierTechnology() {
+        final String[] args = {"-c", "src/test/resources/parameters/prodConsOKFileName.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+            final FILECarrierTechnologyParameters fileParams = (FILECarrierTechnologyParameters) parameters
+                    .getEventOutputParameters().get("aProducer").getCarrierTechnologyParameters();
+            assertEquals("/tmp/aaa.json", fileParams.getFileName());
+            assertEquals(false, fileParams.isStandardError());
+            assertEquals(false, fileParams.isStandardIO());
+            assertEquals(false, fileParams.isStreamingMode());
+        } catch (final ApexParameterException e) {
+            fail("This test should not throw an exception");
+        }
+    }
+
+    @Test
+    public void badFileNameCarrierTechnology() {
+        final String[] args = {"-c", "src/test/resources/parameters/prodConsBadFileName.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "validation error(s) on parameters from \"src/test/resources/parameters/prodConsBadFileName.json\"\n"
+                            + "Apex parameters invalid\n" + " event output (aProducer) parameters invalid\n"
+                            + "  fileName not specified or is blank or null, it must be specified as a valid file location",
+                    e.getMessage());
+        }
+    }
+
+
+    @Test
+    public void badEventProtocolParClass() {
+        final String[] args = {"-c", "src/test/resources/parameters/prodConsBadEPParClass.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/prodConsBadEPParClass.json\"\n"
+                            + "(ApexParameterRuntimeException):event protocol \"SUPER_TOK_DEL\" does not match plugin \"JSON\" in "
+                            + "\"com.ericsson.apex.service.engine.event.impl.jsonprotocolplugin.JSONEventProtocolParameters\", "
+                            + "specify correct event protocol parameter plugin in parameter \"parameterClassName\"",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void noEventProtocolParClass() {
+        final String[] args = {"-c", "src/test/resources/parameters/prodConsNoEPParClass.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/prodConsNoEPParClass.json\"\n"
+                            + "(ApexParameterRuntimeException):event protocol \"SUPER_TOK_DEL\" does not match plugin \"JSON\" in "
+                            + "\"com.ericsson.apex.service.engine.event.impl.jsonprotocolplugin.JSONEventProtocolParameters\", "
+                            + "specify correct event protocol parameter plugin in parameter \"parameterClassName\"",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void mismatchEventProtocolParClass() {
+        final String[] args = {"-c", "src/test/resources/parameters/prodConsMismatchEPParClass.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/prodConsMismatchEPParClass.json\"\n"
+                            + "(ApexParameterRuntimeException):event protocol \"SUPER_TOK_BEL\" does not match plugin \"SUPER_TOK_DEL\" in "
+                            + "\"com.ericsson.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters\", "
+                            + "specify correct event protocol parameter plugin in parameter \"parameterClassName\"",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void wrongTypeEventProtocolParClass() {
+        final String[] args = {"-c", "src/test/resources/parameters/prodConsWrongTypeEPParClass.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "error reading parameters from \"src/test/resources/parameters/prodConsWrongTypeEPParClass.json\"\n"
+                            + "(ApexParameterRuntimeException):could not create default parameters for event protocol \"SUPER_TOK_DEL\"\n"
+                            + "com.ericsson.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters "
+                            + "cannot be cast to com.ericsson.apex.service.parameters.eventprotocol.EventProtocolParameters",
+                    e.getMessage());
+        }
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/SyncParameterTests.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/SyncParameterTests.java
new file mode 100644 (file)
index 0000000..62e27ea
--- /dev/null
@@ -0,0 +1,362 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.parameters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.onap.policy.apex.service.engine.main.ApexCommandLineArguments;
+import org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters;
+import org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters;
+import org.onap.policy.apex.service.parameters.ApexParameterException;
+import org.onap.policy.apex.service.parameters.ApexParameterHandler;
+import org.onap.policy.apex.service.parameters.ApexParameters;
+import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters;
+
+/**
+ * Test for an empty parameter file
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class SyncParameterTests {
+    @Test
+    public void syncBadNoSyncWithPeer() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncBadParamsNoSyncWithPeer.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "validation error(s) on parameters from \"src/test/resources/parameters/syncBadParamsNoSyncWithPeer.json\"\n"
+                            + "Apex parameters invalid\n"
+                            + " parameter \\\"synchronousPeer\\\" is illegal on non synchronous event output \"SyncProducer0\"",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void syncBadNotSyncWithPeer() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncBadParamsNotSyncWithPeer.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "validation error(s) on parameters from \"src/test/resources/parameters/syncBadParamsNotSyncWithPeer.json\"\n"
+                            + "Apex parameters invalid\n"
+                            + " parameter \\\"synchronousPeer\\\" is illegal on non synchronous event output \"SyncProducer0\"",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void syncBadSyncBadPeers() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncBadParamsBadPeers.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "validation error(s) on parameters from \"src/test/resources/parameters/syncBadParamsBadPeers.json\"\n"
+                            + "Apex parameters invalid\n"
+                            + " specified \"synchronousPeer\" parameter value \"SyncConsumer1\" on event input \"SyncConsumer0\" does not exist or is an invalid peer for this event handler\n"
+                            + " specified \"synchronousPeer\" parameter value \"SyncConsumer0\" on event input \"SyncConsumer1\" does not exist or is an invalid peer for this event handler\n"
+                            + " specified \"synchronousPeer\" parameter value \"SyncProducer1\" on event output \"SyncProducer0\" does not exist or is an invalid peer for this event handler\n"
+                            + " specified \"synchronousPeer\" parameter value \"SyncProducer0\" on event output \"SyncProducer1\" does not exist or is an invalid peer for this event handler",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void syncBadSyncInvalidTimeout() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncBadParamsInvalidTimeout.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "validation error(s) on parameters from \"src/test/resources/parameters/syncBadParamsInvalidTimeout.json\"\n"
+                            + "Apex parameters invalid\n"
+                            + " parameter \\\"synchronousTimeout\\\" value \"-1\" is illegal on synchronous event input \"SyncConsumer0\", specify a non-negative timeout value in milliseconds\n"
+                            + " parameter \\\"synchronousTimeout\\\" value \"-99999999\" is illegal on synchronous event input \"SyncConsumer1\", specify a non-negative timeout value in milliseconds\n"
+                            + " parameter \\\"synchronousTimeout\\\" value \"-10\" is illegal on synchronous event output \"SyncProducer0\", specify a non-negative timeout value in milliseconds\n"
+                            + " parameter \\\"synchronousTimeout\\\" value \"-3\" is illegal on synchronous event output \"SyncProducer1\", specify a non-negative timeout value in milliseconds\n"
+                            + " synchronous timeout of event input \"SyncConsumer0\" and event output \"SyncProducer0\" [-1/-10] do not match\n"
+                            + " synchronous timeout of event input \"SyncConsumer1\" and event output \"SyncProducer1\" [-99999999/-3] do not match",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void syncBadSyncBadTimeout() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncBadParamsBadTimeout.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "validation error(s) on parameters from \"src/test/resources/parameters/syncBadParamsBadTimeout.json\"\n"
+                            + "Apex parameters invalid\n"
+                            + " parameter \\\"synchronousTimeout\\\" is illegal on non synchronous event output \"MyOtherProducer\"",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void syncBadSyncUnpairedTimeout() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncBadParamsUnpairedTimeout.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "validation error(s) on parameters from \"src/test/resources/parameters/syncBadParamsUnpairedTimeout.json\"\n"
+                            + "Apex parameters invalid\n"
+                            + " synchronous timeout of event input \"SyncConsumer0\" and event output \"SyncProducer0\" [1/10] do not match\n"
+                            + " synchronous timeout of event input \"SyncConsumer1\" and event output \"SyncProducer1\" [99999999/3] do not match",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void syncGoodSyncGoodTimeoutProducer() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncGoodParamsProducerTimeout.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+            assertEquals(12345, parameters.getEventInputParameters().get("SyncConsumer0")
+                    .getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+            assertEquals(1, parameters.getEventInputParameters().get("SyncConsumer1")
+                    .getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+            assertEquals(12345, parameters.getEventOutputParameters().get("SyncProducer0")
+                    .getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+            assertEquals(1, parameters.getEventOutputParameters().get("SyncProducer1")
+                    .getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+        } catch (final Exception e) {
+            fail("This test should not throw an exception");
+        }
+    }
+
+    @Test
+    public void syncGoodSyncGoodTimeoutConsumer() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncGoodParamsConsumerTimeout.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+            assertEquals(12345, parameters.getEventInputParameters().get("SyncConsumer0")
+                    .getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+            assertEquals(1, parameters.getEventInputParameters().get("SyncConsumer1")
+                    .getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+            assertEquals(12345, parameters.getEventOutputParameters().get("SyncProducer0")
+                    .getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+            assertEquals(1, parameters.getEventOutputParameters().get("SyncProducer1")
+                    .getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+        } catch (final Exception e) {
+            fail("This test should not throw an exception");
+        }
+    }
+
+    @Test
+    public void syncGoodSyncGoodTimeoutBoth() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncGoodParamsBothTimeout.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+            assertEquals(12345, parameters.getEventInputParameters().get("SyncConsumer0")
+                    .getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+            assertEquals(1, parameters.getEventInputParameters().get("SyncConsumer1")
+                    .getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+            assertEquals(12345, parameters.getEventOutputParameters().get("SyncProducer0")
+                    .getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+            assertEquals(1, parameters.getEventOutputParameters().get("SyncProducer1")
+                    .getPeerTimeout(EventHandlerPeeredMode.SYNCHRONOUS));
+        } catch (final Exception e) {
+            fail("This test should not throw an exception");
+        }
+    }
+
+    @Test
+    public void syncUnusedConsumerPeers() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncUnusedConsumerPeers.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "validation error(s) on parameters from \"src/test/resources/parameters/syncUnusedConsumerPeers.json\"\n"
+                            + "Apex parameters invalid\n"
+                            + " value of parameter \"synchronousPeer\" on event output \"SyncProducer1\" must be unique, it s used on another event output\n"
+                            + ""
+                            + " synchronous peers of event input \"SyncConsumer1\" and event output \"SyncProducer1/SyncConsumer0\" do not match",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void syncMismatchedPeers() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncMismatchedPeers.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "validation error(s) on parameters from \"src/test/resources/parameters/syncMismatchedPeers.json\"\n"
+                            + "Apex parameters invalid\n"
+                            + " synchronous peers of event input \"SyncConsumer0\" and event output \"SyncProducer0/SyncConsumer1\" do not match\n"
+                            + " synchronous peers of event input \"SyncConsumer1\" and event output \"SyncProducer1/SyncConsumer0\" do not match",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void syncUnusedProducerPeers() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncUnusedProducerPeers.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "validation error(s) on parameters from \"src/test/resources/parameters/syncUnusedProducerPeers.json\"\n"
+                            + "Apex parameters invalid\n"
+                            + " value of parameter \"synchronousPeer\" on event input \"SyncConsumer1\" must be unique, it s used on another event input\n"
+                            + " synchronous peers of event input \"SyncConsumer0\" and event output \"SyncProducer1/SyncConsumer1\" do not match",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void syncMismatchedTimeout() throws ApexParameterException {
+        final String[] args = {"-c", "src/test/resources/parameters/syncUnusedProducerPeers.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            new ApexParameterHandler().getParameters(arguments);
+            fail("This test should throw an exception");
+        } catch (final ApexParameterException e) {
+            assertEquals(
+                    "validation error(s) on parameters from \"src/test/resources/parameters/syncUnusedProducerPeers.json\"\n"
+                            + "Apex parameters invalid\n"
+                            + " value of parameter \"synchronousPeer\" on event input \"SyncConsumer1\" must be unique, it s used on another event input\n"
+                            + " synchronous peers of event input \"SyncConsumer0\" and event output \"SyncProducer1/SyncConsumer1\" do not match",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void syncGoodParametersTest() {
+        final String[] args = {"-c", "src/test/resources/parameters/SyncGoodParams.json"};
+        final ApexCommandLineArguments arguments = new ApexCommandLineArguments(args);
+
+        try {
+            final ApexParameters parameters = new ApexParameterHandler().getParameters(arguments);
+
+            assertEquals("MyApexEngine", parameters.getEngineServiceParameters().getName());
+            assertEquals("0.0.1", parameters.getEngineServiceParameters().getVersion());
+            assertEquals(45, parameters.getEngineServiceParameters().getId());
+            assertEquals(19, parameters.getEngineServiceParameters().getInstanceCount());
+            assertEquals(65522, parameters.getEngineServiceParameters().getDeploymentPort());
+
+            final CarrierTechnologyParameters prodCT0 =
+                    parameters.getEventOutputParameters().get("SyncProducer0").getCarrierTechnologyParameters();
+            final EventProtocolParameters prodEP0 =
+                    parameters.getEventOutputParameters().get("SyncProducer0").getEventProtocolParameters();
+            final CarrierTechnologyParameters consCT0 =
+                    parameters.getEventInputParameters().get("SyncConsumer0").getCarrierTechnologyParameters();
+            final EventProtocolParameters consEP0 =
+                    parameters.getEventInputParameters().get("SyncConsumer0").getEventProtocolParameters();
+            final CarrierTechnologyParameters prodCT1 =
+                    parameters.getEventOutputParameters().get("SyncProducer1").getCarrierTechnologyParameters();
+            final EventProtocolParameters prodEP1 =
+                    parameters.getEventOutputParameters().get("SyncProducer1").getEventProtocolParameters();
+            final CarrierTechnologyParameters consCT1 =
+                    parameters.getEventInputParameters().get("SyncConsumer1").getCarrierTechnologyParameters();
+            final EventProtocolParameters consEP1 =
+                    parameters.getEventInputParameters().get("SyncConsumer1").getEventProtocolParameters();
+
+            assertEquals("FILE", prodCT0.getLabel());
+            assertEquals("JSON", prodEP0.getLabel());
+            assertEquals("FILE", consCT0.getLabel());
+            assertEquals("JSON", consEP0.getLabel());
+            assertEquals("FILE", prodCT1.getLabel());
+            assertEquals("JSON", prodEP1.getLabel());
+            assertEquals("SUPER_DOOPER", consCT1.getLabel());
+            assertEquals("SUPER_TOK_DEL", consEP1.getLabel());
+
+            assertTrue(consCT1 instanceof SuperDooperCarrierTechnologyParameters);
+            assertTrue(consEP1 instanceof SuperTokenDelimitedEventProtocolParameters);
+
+            final SuperDooperCarrierTechnologyParameters superDooperParameters =
+                    (SuperDooperCarrierTechnologyParameters) consCT1;
+            assertEquals("localhost:9092", superDooperParameters.getBootstrapServers());
+            assertEquals("all", superDooperParameters.getAcks());
+            assertEquals(0, superDooperParameters.getRetries());
+            assertEquals(16384, superDooperParameters.getBatchSize());
+            assertEquals(1, superDooperParameters.getLingerTime());
+            assertEquals(33554432, superDooperParameters.getBufferMemory());
+            assertEquals("default-group-id", superDooperParameters.getGroupId());
+            assertTrue(superDooperParameters.isEnableAutoCommit());
+            assertEquals(1000, superDooperParameters.getAutoCommitTime());
+            assertEquals(30000, superDooperParameters.getSessionTimeout());
+            assertEquals("apex-out", superDooperParameters.getProducerTopic());
+            assertEquals(100, superDooperParameters.getConsumerPollTime());
+            assertEquals("org.apache.superDooper.common.serialization.StringSerializer",
+                    superDooperParameters.getKeySerializer());
+            assertEquals("org.apache.superDooper.common.serialization.StringSerializer",
+                    superDooperParameters.getValueSerializer());
+            assertEquals("org.apache.superDooper.common.serialization.StringDeserializer",
+                    superDooperParameters.getKeyDeserializer());
+            assertEquals("org.apache.superDooper.common.serialization.StringDeserializer",
+                    superDooperParameters.getValueDeserializer());
+
+            final String[] consumerTopics = {"apex-in"};
+            assertEquals(Arrays.asList(consumerTopics), superDooperParameters.getConsumerTopicList());
+        } catch (final ApexParameterException e) {
+            fail("This test should not throw an exception");
+        }
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperCarrierTechnologyParameters.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperCarrierTechnologyParameters.java
new file mode 100644 (file)
index 0000000..ffbd1c0
--- /dev/null
@@ -0,0 +1,392 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.parameters.dummyclasses;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Properties;
+
+import org.onap.policy.apex.model.basicmodel.service.ParameterService;
+import org.onap.policy.apex.service.parameters.carriertechnology.CarrierTechnologyParameters;
+
+/**
+ * Apex parameters for SuperDooper as an event carrier technology.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class SuperDooperCarrierTechnologyParameters extends CarrierTechnologyParameters {
+    // Default parameter values
+    private static final String DEFAULT_ACKS = "all";
+    private static final String DEFAULT_BOOTSTRAP_SERVERS = "localhost:9092";
+    private static final int DEFAULT_RETRIES = 0;
+    private static final int DEFAULT_BATCH_SIZE = 16384;
+    private static final int DEFAULT_LINGER_TIME = 1;
+    private static final long DEFAULT_BUFFER_MEMORY = 33554432;
+    private static final String DEFAULT_GROUP_ID = "default-group-id";
+    private static final boolean DEFAULT_ENABLE_AUTO_COMMIT = true;
+    private static final int DEFAULT_AUTO_COMMIT_TIME = 1000;
+    private static final int DEFAULT_SESSION_TIMEOUT = 30000;
+    private static final String DEFAULT_PRODUCER_TOPIC = "apex-out";
+    private static final int DEFAULT_CONSUMER_POLL_TIME = 100;
+    private static final String[] DEFAULT_CONSUMER_TOPIC_LIST = {"apex-in"};
+    private static final String DEFAULT_KEY_SERIALIZER = "org.apache.superDooper.common.serialization.StringSerializer";
+    private static final String DEFAULT_VALUE_SERIALIZER =
+            "org.apache.superDooper.common.serialization.StringSerializer";
+    private static final String DEFAULT_KEY_DESERIALIZER =
+            "org.apache.superDooper.common.serialization.StringDeserializer";
+    private static final String DEFAULT_VALUE_DESERIALIZER =
+            "org.apache.superDooper.common.serialization.StringDeserializer";
+
+    // Parameter property map tokens
+    private static final String PROPERTY_BOOTSTRAP_SERVERS = "bootstrap.servers";
+    private static final String PROPERTY_ACKS = "acks";
+    private static final String PROPERTY_RETRIES = "retries";
+    private static final String PROPERTY_BATCH_SIZE = "batch.size";
+    private static final String PROPERTY_LINGER_TIME = "linger.ms";
+    private static final String PROPERTY_BUFFER_MEMORY = "buffer.memory";
+    private static final String PROPERTY_GROUP_ID = "group.id";
+    private static final String PROPERTY_ENABLE_AUTO_COMMIT = "enable.auto.commit";
+    private static final String PROPERTY_AUTO_COMMIT_TIME = "auto.commit.interval.ms";
+    private static final String PROPERTY_SESSION_TIMEOUT = "session.timeout.ms";
+    private static final String PROPERTY_KEY_SERIALIZER = "key.serializer";
+    private static final String PROPERTY_VALUE_SERIALIZER = "value.serializer";
+    private static final String PROPERTY_KEY_DESERIALIZER = "key.deserializer";
+    private static final String PROPERTY_VALUE_DESERIALIZER = "value.deserializer";
+
+    // superDooper carrier parameters
+    private final String bootstrapServers = DEFAULT_BOOTSTRAP_SERVERS;
+    private final String acks = DEFAULT_ACKS;
+    private final int retries = DEFAULT_RETRIES;
+    private final int batchSize = DEFAULT_BATCH_SIZE;
+    private final int lingerTime = DEFAULT_LINGER_TIME;
+    private final long bufferMemory = DEFAULT_BUFFER_MEMORY;
+    private final String groupId = DEFAULT_GROUP_ID;
+    private final boolean enableAutoCommit = DEFAULT_ENABLE_AUTO_COMMIT;
+    private final int autoCommitTime = DEFAULT_AUTO_COMMIT_TIME;
+    private final int sessionTimeout = DEFAULT_SESSION_TIMEOUT;
+    private final String producerTopic = DEFAULT_PRODUCER_TOPIC;
+    private final int consumerPollTime = DEFAULT_CONSUMER_POLL_TIME;
+    private final String[] consumerTopicList = DEFAULT_CONSUMER_TOPIC_LIST;
+    private final String keySerializer = DEFAULT_KEY_SERIALIZER;
+    private final String valueSerializer = DEFAULT_VALUE_SERIALIZER;
+    private final String keyDeserializer = DEFAULT_KEY_DESERIALIZER;
+    private final String valueDeserializer = DEFAULT_VALUE_DESERIALIZER;
+
+    /**
+     * Constructor to create a file carrier technology parameters instance and register the instance
+     * with the parameter service.
+     */
+    public SuperDooperCarrierTechnologyParameters() {
+        super(SuperDooperCarrierTechnologyParameters.class.getCanonicalName());
+        ParameterService.registerParameters(SuperDooperCarrierTechnologyParameters.class, this);
+
+        // Set the carrier technology properties for the FILE carrier technology
+        this.setLabel("SUPER_DOOPER");
+        this.setEventProducerPluginClass(
+                "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperEventProducer");
+        this.setEventConsumerPluginClass(
+                "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperEventSubscriber");
+    }
+
+    /**
+     * Gets the superDooper producer properties.
+     *
+     * @return the superDooper producer properties
+     */
+    public Properties getSuperDooperProducerProperties() {
+        final Properties superDooperProperties = new Properties();
+
+        superDooperProperties.put(PROPERTY_BOOTSTRAP_SERVERS, bootstrapServers);
+        superDooperProperties.put(PROPERTY_ACKS, acks);
+        superDooperProperties.put(PROPERTY_RETRIES, retries);
+        superDooperProperties.put(PROPERTY_BATCH_SIZE, batchSize);
+        superDooperProperties.put(PROPERTY_LINGER_TIME, lingerTime);
+        superDooperProperties.put(PROPERTY_BUFFER_MEMORY, bufferMemory);
+        superDooperProperties.put(PROPERTY_KEY_SERIALIZER, keySerializer);
+        superDooperProperties.put(PROPERTY_VALUE_SERIALIZER, valueSerializer);
+
+        return superDooperProperties;
+    }
+
+    /**
+     * Gets the superDooper consumer properties.
+     *
+     * @return the superDooper consumer properties
+     */
+    public Properties getSuperDooperConsumerProperties() {
+        final Properties superDooperProperties = new Properties();
+
+        superDooperProperties.put(PROPERTY_BOOTSTRAP_SERVERS, bootstrapServers);
+        superDooperProperties.put(PROPERTY_GROUP_ID, groupId);
+        superDooperProperties.put(PROPERTY_ENABLE_AUTO_COMMIT, enableAutoCommit);
+        superDooperProperties.put(PROPERTY_AUTO_COMMIT_TIME, autoCommitTime);
+        superDooperProperties.put(PROPERTY_SESSION_TIMEOUT, sessionTimeout);
+        superDooperProperties.put(PROPERTY_KEY_DESERIALIZER, keyDeserializer);
+        superDooperProperties.put(PROPERTY_VALUE_DESERIALIZER, valueDeserializer);
+
+        return superDooperProperties;
+    }
+
+    /**
+     * Gets the bootstrap servers.
+     *
+     * @return the bootstrap servers
+     */
+    public String getBootstrapServers() {
+        return bootstrapServers;
+    }
+
+    /**
+     * Gets the acks.
+     *
+     * @return the acks
+     */
+    public String getAcks() {
+        return acks;
+    }
+
+    /**
+     * Gets the retries.
+     *
+     * @return the retries
+     */
+    public int getRetries() {
+        return retries;
+    }
+
+    /**
+     * Gets the batch size.
+     *
+     * @return the batch size
+     */
+    public int getBatchSize() {
+        return batchSize;
+    }
+
+    /**
+     * Gets the linger time.
+     *
+     * @return the linger time
+     */
+    public int getLingerTime() {
+        return lingerTime;
+    }
+
+    /**
+     * Gets the buffer memory.
+     *
+     * @return the buffer memory
+     */
+    public long getBufferMemory() {
+        return bufferMemory;
+    }
+
+    /**
+     * Gets the group id.
+     *
+     * @return the group id
+     */
+    public String getGroupId() {
+        return groupId;
+    }
+
+    /**
+     * Checks if is enable auto commit.
+     *
+     * @return true, if checks if is enable auto commit
+     */
+    public boolean isEnableAutoCommit() {
+        return enableAutoCommit;
+    }
+
+    /**
+     * Gets the auto commit time.
+     *
+     * @return the auto commit time
+     */
+    public int getAutoCommitTime() {
+        return autoCommitTime;
+    }
+
+    /**
+     * Gets the session timeout.
+     *
+     * @return the session timeout
+     */
+    public int getSessionTimeout() {
+        return sessionTimeout;
+    }
+
+    /**
+     * Gets the producer topic.
+     *
+     * @return the producer topic
+     */
+    public String getProducerTopic() {
+        return producerTopic;
+    }
+
+    /**
+     * Gets the consumer poll time.
+     *
+     * @return the consumer poll time
+     */
+    public long getConsumerPollTime() {
+        return consumerPollTime;
+    }
+
+    /**
+     * Gets the consumer topic list.
+     *
+     * @return the consumer topic list
+     */
+    public Collection<String> getConsumerTopicList() {
+        return Arrays.asList(consumerTopicList);
+    }
+
+    /**
+     * Gets the key serializer.
+     *
+     * @return the key serializer
+     */
+    public String getKeySerializer() {
+        return keySerializer;
+    }
+
+    /**
+     * Gets the value serializer.
+     *
+     * @return the value serializer
+     */
+    public String getValueSerializer() {
+        return valueSerializer;
+    }
+
+    /**
+     * Gets the key deserializer.
+     *
+     * @return the key deserializer
+     */
+    public String getKeyDeserializer() {
+        return keyDeserializer;
+    }
+
+    /**
+     * Gets the value deserializer.
+     *
+     * @return the value deserializer
+     */
+    public String getValueDeserializer() {
+        return valueDeserializer;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.apps.uservice.parameters.ApexParameterValidator#validate()
+     */
+    @Override
+    public String validate() {
+        final StringBuilder errorMessageBuilder = new StringBuilder();
+
+        errorMessageBuilder.append(super.validate());
+
+        if (bootstrapServers == null || bootstrapServers.trim().length() == 0) {
+            errorMessageBuilder
+                    .append("  bootstrapServers not specified, must be specified as a string of form host:port\n");
+        }
+
+        if (acks == null || acks.trim().length() == 0) {
+            errorMessageBuilder.append("  acks not specified, must be specified as a string with values [0|1|all]\n");
+        }
+
+        if (retries < 0) {
+            errorMessageBuilder.append("  retries [" + retries + "] invalid, must be specified as retries >= 0\n");
+        }
+
+        if (batchSize < 0) {
+            errorMessageBuilder
+                    .append("  batchSize [" + batchSize + "] invalid, must be specified as batchSize >= 0\n");
+        }
+
+        if (lingerTime < 0) {
+            errorMessageBuilder
+                    .append("  lingerTime [" + lingerTime + "] invalid, must be specified as lingerTime >= 0\n");
+        }
+
+        if (bufferMemory < 0) {
+            errorMessageBuilder
+                    .append("  bufferMemory [" + bufferMemory + "] invalid, must be specified as bufferMemory >= 0\n");
+        }
+
+        if (groupId == null || groupId.trim().length() == 0) {
+            errorMessageBuilder.append("  groupId not specified, must be specified as a string\n");
+        }
+
+        if (autoCommitTime < 0) {
+            errorMessageBuilder.append(
+                    "  autoCommitTime [" + autoCommitTime + "] invalid, must be specified as autoCommitTime >= 0\n");
+        }
+
+        if (sessionTimeout < 0) {
+            errorMessageBuilder.append(
+                    "  sessionTimeout [" + sessionTimeout + "] invalid, must be specified as sessionTimeout >= 0\n");
+        }
+
+        if (producerTopic == null || producerTopic.trim().length() == 0) {
+            errorMessageBuilder.append("  producerTopic not specified, must be specified as a string\n");
+        }
+
+        if (consumerPollTime < 0) {
+            errorMessageBuilder.append("  consumerPollTime [" + consumerPollTime
+                    + "] invalid, must be specified as consumerPollTime >= 0\n");
+        }
+
+        if (consumerTopicList == null || consumerTopicList.length == 0) {
+            errorMessageBuilder.append("  consumerTopicList not specified, must be specified as a list of strings\n");
+        }
+
+        for (final String consumerTopic : consumerTopicList) {
+            if (consumerTopic == null || consumerTopic.trim().length() == 0) {
+                errorMessageBuilder.append("  invalid consumer topic \"" + consumerTopic
+                        + "\" specified on consumerTopicList, consumer topics must be specified as strings\n");
+            }
+        }
+
+        if (keySerializer == null || keySerializer.trim().length() == 0) {
+            errorMessageBuilder.append("  keySerializer not specified, must be specified as a string\n");
+        }
+
+        if (valueSerializer == null || valueSerializer.trim().length() == 0) {
+            errorMessageBuilder.append("  valueSerializer not specified, must be specified as a string\n");
+        }
+
+        if (keyDeserializer == null || keyDeserializer.trim().length() == 0) {
+            errorMessageBuilder.append("  keyDeserializer not specified, must be specified as a string\n");
+        }
+
+        if (valueDeserializer == null || valueDeserializer.trim().length() == 0) {
+            errorMessageBuilder.append("  valueDeserializer not specified, must be specified as a string\n");
+        }
+
+        return errorMessageBuilder.toString();
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperDistributorParameters.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperDistributorParameters.java
new file mode 100644 (file)
index 0000000..6d7c6ff
--- /dev/null
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.parameters.dummyclasses;
+
+import org.onap.policy.apex.context.parameters.DistributorParameters;
+import org.onap.policy.apex.model.basicmodel.service.ParameterService;
+
+/**
+ * Distributor parameters for the Super Dooper Distributor
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @version
+ */
+public class SuperDooperDistributorParameters extends DistributorParameters {
+    // Constants for SuperDooper configuration file locations
+    public static final String DEFAULT_SUPER_DOOPER_DISTRIBUTION_CONFIG_FILE = "superDooper/superDooper.xml";
+    public static final String DEFAULT_SUPER_DOOPER_DISTRIBUTION_JGROUPS_FILE =
+            "superDooper/jgroups-superDooper-apex.xml";
+    public static final boolean DEFAULT_SUPER_DOOPER_JAVA_NET_PREFER_IPV4_STACK = true;
+    public static final String DEFAULT_INFINSPAN_JGROUPS_BIND_ADDRESS = "localhost";
+
+    // SuperDooper configuration file names
+    private String configFile = DEFAULT_SUPER_DOOPER_DISTRIBUTION_CONFIG_FILE;
+    private String jgroupsFile = DEFAULT_SUPER_DOOPER_DISTRIBUTION_JGROUPS_FILE;
+    private boolean preferIPv4Stack = DEFAULT_SUPER_DOOPER_JAVA_NET_PREFER_IPV4_STACK;
+    private String jGroupsBindAddress = DEFAULT_INFINSPAN_JGROUPS_BIND_ADDRESS;
+
+    public SuperDooperDistributorParameters() {
+        super(SuperDooperDistributorParameters.class.getCanonicalName());
+        ParameterService.registerParameters(SuperDooperDistributorParameters.class, this);
+        ParameterService.registerParameters(DistributorParameters.class, this);
+    }
+
+    public String getConfigFile() {
+        return configFile;
+    }
+
+    public void setConfigFile(final String configFile) {
+        this.configFile = configFile;
+    }
+
+    public String getJgroupsFile() {
+        return jgroupsFile;
+    }
+
+    public void setJgroupsFile(final String jgroupsFile) {
+        this.jgroupsFile = jgroupsFile;
+    }
+
+    public boolean preferIPv4Stack() {
+        return preferIPv4Stack;
+    }
+
+    public void setPreferIPv4Stack(final boolean preferIPv4Stack) {
+        this.preferIPv4Stack = preferIPv4Stack;
+    }
+
+    public String getjGroupsBindAddress() {
+        return jGroupsBindAddress;
+    }
+
+    public void setjGroupsBindAddress(final String jGroupsBindAddress) {
+        this.jGroupsBindAddress = jGroupsBindAddress;
+    }
+
+    @Override
+    public String toString() {
+        return "SuperDooperDistributorParameters [configFile=" + configFile + ", jgroupsFile=" + jgroupsFile
+                + ", preferIPv4Stack=" + preferIPv4Stack + ", jGroupsBindAddress=" + jGroupsBindAddress + "]";
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperEventProducer.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperEventProducer.java
new file mode 100644 (file)
index 0000000..e405107
--- /dev/null
@@ -0,0 +1,106 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.parameters.dummyclasses;
+
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.engine.event.ApexEventProducer;
+import org.onap.policy.apex.service.engine.event.PeeredReference;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * @author John Keeney (john.keeney@ericsson.com)
+ */
+public class SuperDooperEventProducer implements ApexEventProducer {
+
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(SuperDooperEventProducer.class);
+
+    private String name;
+
+    public SuperDooperEventProducer() {}
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.ericsson.apex.service.engine.event.ApexEventProducer#init(java.lang.String,
+     * com.ericsson.apex.service.parameters.producer.ProducerParameters)
+     */
+    @Override
+    public void init(final String name, final EventHandlerParameters producerParameters) throws ApexEventException {
+        this.name = name;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.ericsson.apex.service.engine.event.ApexEventProducer#getName()
+     */
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * com.ericsson.apex.service.engine.event.ApexEventProducer#getPeeredReference(com.ericsson.apex
+     * .service.parameters.eventhandler.EventHandlerPeeredMode)
+     */
+    @Override
+    public PeeredReference getPeeredReference(final EventHandlerPeeredMode peeredMode) {
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * com.ericsson.apex.service.engine.event.ApexEventProducer#setPeeredReference(com.ericsson.apex
+     * .service.parameters.eventhandler.EventHandlerPeeredMode,
+     * com.ericsson.apex.service.engine.event.PeeredReference)
+     */
+    @Override
+    public void setPeeredReference(final EventHandlerPeeredMode peeredMode, final PeeredReference peeredReference) {}
+
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.ericsson.apex.service.engine.event.ApexEventProducer#sendEvent(long,
+     * java.lang.String, java.lang.Object)
+     */
+    @Override
+    public void sendEvent(final long executionId, final String eventName, final Object event) {
+        LOGGER.info("Sending Event: " + this.getClass().getCanonicalName() + ":" + this.name + " ... event ("
+                + eventName + ") : " + event);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.ericsson.apex.service.engine.event.ApexEventProducer#stop()
+     */
+    @Override
+    public void stop() {}
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperEventSubscriber.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperEventSubscriber.java
new file mode 100644 (file)
index 0000000..c791d31
--- /dev/null
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.parameters.dummyclasses;
+
+import org.onap.policy.apex.service.engine.event.ApexEventConsumer;
+import org.onap.policy.apex.service.engine.event.ApexEventException;
+import org.onap.policy.apex.service.engine.event.ApexEventReceiver;
+import org.onap.policy.apex.service.engine.event.PeeredReference;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
+import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+public class SuperDooperEventSubscriber implements ApexEventConsumer {
+
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(SuperDooperEventSubscriber.class);
+
+    private String name;
+
+    public SuperDooperEventSubscriber() {}
+
+    @Override
+    public void init(final String name, final EventHandlerParameters consumerParameters,
+            final ApexEventReceiver apexEventReceiver) throws ApexEventException {
+        this.name = name;
+        LOGGER.info("Initialising Apex Consumer: " + this.getClass().getCanonicalName() + ":" + this.name);
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#getPeeredReference(org.onap.
+     * policy.apex .service.parameters.eventhandler.EventHandlerPeeredMode)
+     */
+    @Override
+    public PeeredReference getPeeredReference(final EventHandlerPeeredMode peeredMode) {
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.onap.policy.apex.service.engine.event.ApexEventConsumer#setPeeredReference(org.onap.
+     * policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode,
+     * org.onap.policy.apex.service.engine.event.PeeredReference)
+     */
+    @Override
+    public void setPeeredReference(final EventHandlerPeeredMode peeredMode, final PeeredReference peeredReference) {}
+
+    @Override
+    public void start() {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void stop() {}
+
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperExecutorParameters.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperDooperExecutorParameters.java
new file mode 100644 (file)
index 0000000..3af7729
--- /dev/null
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.parameters.dummyclasses;
+
+import org.onap.policy.apex.core.engine.ExecutorParameters;
+
+/**
+ * Default Executor parameters for MVEL
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @version
+ */
+public class SuperDooperExecutorParameters extends ExecutorParameters {
+    public SuperDooperExecutorParameters() {
+        this.setTaskExecutorPluginClass(
+                "org.onap.policy.apex.service.engine.parameters.dummyclasses.DummyTaskExecutor");
+        this.setTaskSelectionExecutorPluginClass(
+                "org.onap.policy.apex.service.engine.parameters.dummyclasses.DummyTaskSelectExecutor");
+        this.setStateFinalizerExecutorPluginClass(
+                "org.onap.policy.apex.service.engine.parameters.dummyclasses.DummyStateFinalizerExecutor");
+    }
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperTokenDelimitedEventConverter.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperTokenDelimitedEventConverter.java
new file mode 100644 (file)
index 0000000..e807f7f
--- /dev/null
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.parameters.dummyclasses;
+
+import java.util.List;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.service.engine.event.ApexEvent;
+import org.onap.policy.apex.service.engine.event.ApexEventProtocolConverter;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolParameters;
+
+public final class SuperTokenDelimitedEventConverter implements ApexEventProtocolConverter {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.onap.policy.apex.service.engine.event.ApexEventConverter#toApexEvent(java.lang.String,
+     * java.lang.Object)
+     */
+    @Override
+    public List<ApexEvent> toApexEvent(final String eventName, final Object eventOfOtherType) throws ApexException {
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.onap.policy.apex.service.engine.event.ApexEventConverter#fromApexEvent(org.onap.policy.
+     * apex.service.engine.event.ApexEvent)
+     */
+    @Override
+    public String fromApexEvent(final ApexEvent apexEvent) throws ApexException {
+        return null;
+    }
+
+    @Override
+    public void init(final EventProtocolParameters parameters) {}
+}
diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperTokenDelimitedEventProtocolParameters.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/SuperTokenDelimitedEventProtocolParameters.java
new file mode 100644 (file)
index 0000000..99f938e
--- /dev/null
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2016-2018 Ericsson. 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.service.engine.parameters.dummyclasses;
+
+import org.onap.policy.apex.model.basicmodel.service.ParameterService;
+import org.onap.policy.apex.service.engine.event.impl.jsonprotocolplugin.JSONEventProtocolParameters;
+import org.onap.policy.apex.service.parameters.eventprotocol.EventProtocolTextTokenDelimitedParameters;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class SuperTokenDelimitedEventProtocolParameters extends EventProtocolTextTokenDelimitedParameters {
+    /** The label of this carrier technology. */
+    public static final String SUPER_TOKEN_EVENT_PROTOCOL_LABEL = "SUPER_TOK_DEL";
+
+    // Constants for text delimiter tokeb
+    private static final String SUPER_TOKEN_DELIMITER = "SuperToken";
+
+    /**
+     * Constructor to create a JSON event protocol parameter instance and register the instance with
+     * the parameter service.
+     */
+    public SuperTokenDelimitedEventProtocolParameters() {
+        super(JSONEventProtocolParameters.class.getCanonicalName());
+        ParameterService.registerParameters(SuperTokenDelimitedEventProtocolParameters.class, this);
+
+        // Set the event protocol properties for the JSON carrier technology
+        this.setLabel(SUPER_TOKEN_EVENT_PROTOCOL_LABEL);
+
+        // Set the starting and ending delimiters for text blocks of JSON events
+        this.setDelimiterToken(SUPER_TOKEN_DELIMITER);
+
+        // Set the event protocol plugin class
+        this.setEventProtocolPluginClass(SuperTokenDelimitedEventConverter.class.getCanonicalName());
+    }
+}
diff --git a/services/services-engine/src/test/resources/logback-test.xml b/services/services-engine/src/test/resources/logback-test.xml
new file mode 100644 (file)
index 0000000..bb9d0c7
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============LICENSE_START=======================================================
+   Copyright (C) 2016-2018 Ericsson. 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.
+  
+  SPDX-License-Identifier: Apache-2.0
+  ============LICENSE_END=========================================================
+-->
+
+<configuration>
+
+    <contextName>Apex</contextName>
+    <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
+    <property name="LOG_DIR" value="${java.io.tmpdir}/apex_logging/" />
+
+       <!-- USE FOR STD OUT ONLY -->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <Pattern>%d %contextName [%t] %level %logger{36} - %msg%n</Pattern>
+        </encoder>
+    </appender>
+
+    <root level="info">
+        <appender-ref ref="STDOUT" />
+    </root>
+
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${LOG_DIR}/apex.log</file>
+        <encoder>
+            <pattern>%d %-5relative [procId=${processId}] [%thread] %-5level
+                %logger{26} - %msg %n %ex{full}</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="org.onap.policy.apex.service.engine.event" level="info" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+</configuration>
diff --git a/services/services-engine/src/test/resources/main/DummyModelFile.json b/services/services-engine/src/test/resources/main/DummyModelFile.json
new file mode 100644 (file)
index 0000000..b6cf5bd
--- /dev/null
@@ -0,0 +1,3 @@
+{
+       "name": "value"
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/badParams.json b/services/services-engine/src/test/resources/parameters/badParams.json
new file mode 100644 (file)
index 0000000..c3b96c7
--- /dev/null
@@ -0,0 +1,31 @@
+{
+    "engineServiceParameters": {
+        "name": "hello there",
+        "version": "PA1",
+        "id": -45,
+        "instanceCount": -345,
+        "deploymentPort": 65536,
+        "policyModelFileName": "/some/file/name.xml"
+    },
+    "eventOutputParameters": {
+        "FirstProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "TheFileConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/blankParams.json b/services/services-engine/src/test/resources/parameters/blankParams.json
new file mode 100644 (file)
index 0000000..d874ae9
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "engineServiceParameters": {
+        
+    },
+    "eventInputParameters": {
+        
+    },
+    "eventOutputParameters": {
+        
+    }
+}
diff --git a/services/services-engine/src/test/resources/parameters/empty.json b/services/services-engine/src/test/resources/parameters/empty.json
new file mode 100644 (file)
index 0000000..9e26dfe
--- /dev/null
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/factoryGoodParams.json b/services/services-engine/src/test/resources/parameters/factoryGoodParams.json
new file mode 100644 (file)
index 0000000..54b58ce
--- /dev/null
@@ -0,0 +1,64 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "FirstProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        },
+        "MyOtherProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "TheFileConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        },
+        "MySuperDooperConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/goodParams.json b/services/services-engine/src/test/resources/parameters/goodParams.json
new file mode 100644 (file)
index 0000000..c470f3e
--- /dev/null
@@ -0,0 +1,64 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "FirstProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        },
+        "MyOtherProducer": {
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            }
+        }
+    },
+    "eventInputParameters": {
+        "TheFileConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        },
+        "MySuperDooperConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/noParams.json b/services/services-engine/src/test/resources/parameters/noParams.json
new file mode 100644 (file)
index 0000000..7a73a41
--- /dev/null
@@ -0,0 +1,2 @@
+{
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/prodConsBadCTParClass.json b/services/services-engine/src/test/resources/parameters/prodConsBadCTParClass.json
new file mode 100644 (file)
index 0000000..2179469
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "aProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "aConsumer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.FILECarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/prodConsBadEPParClass.json b/services/services-engine/src/test/resources/parameters/prodConsBadEPParClass.json
new file mode 100644 (file)
index 0000000..0900d5b
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "aProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "aConsumer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.event.impl.jsonprotocolplugin.JSONEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/prodConsBadFileName.json b/services/services-engine/src/test/resources/parameters/prodConsBadFileName.json
new file mode 100644 (file)
index 0000000..2dc5065
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "aProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": null
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "aConsumer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/prodConsMismatchCTParClass.json b/services/services-engine/src/test/resources/parameters/prodConsMismatchCTParClass.json
new file mode 100644 (file)
index 0000000..e8d1a96
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "aProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "aConsumer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_LOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/prodConsMismatchEPParClass.json b/services/services-engine/src/test/resources/parameters/prodConsMismatchEPParClass.json
new file mode 100644 (file)
index 0000000..89e905c
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "aProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "aConsumer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_BEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/prodConsNoCT.json b/services/services-engine/src/test/resources/parameters/prodConsNoCT.json
new file mode 100644 (file)
index 0000000..7bf3024
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "aProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "aConsumer": {
+            "carrierParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.FILECarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/prodConsNoCTParClass.json b/services/services-engine/src/test/resources/parameters/prodConsNoCTParClass.json
new file mode 100644 (file)
index 0000000..9c8723a
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "aProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "aConsumer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/prodConsNoEP.json b/services/services-engine/src/test/resources/parameters/prodConsNoEP.json
new file mode 100644 (file)
index 0000000..122680d
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "aProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "aConsumer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameterClassName": "org.onap.policy.apex.service.engine.event.impl.filecarrierplugin.FILECarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/prodConsNoEPParClass.json b/services/services-engine/src/test/resources/parameters/prodConsNoEPParClass.json
new file mode 100644 (file)
index 0000000..8aea0ea
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "aProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "aConsumer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/prodConsOKFileName.json b/services/services-engine/src/test/resources/parameters/prodConsOKFileName.json
new file mode 100644 (file)
index 0000000..b242404
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "aProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "aConsumer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/prodConsWrongTypeCTParClass.json b/services/services-engine/src/test/resources/parameters/prodConsWrongTypeCTParClass.json
new file mode 100644 (file)
index 0000000..6bfab6a
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "aProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "aConsumer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/prodConsWrongTypeEPParClass.json b/services/services-engine/src/test/resources/parameters/prodConsWrongTypeEPParClass.json
new file mode 100644 (file)
index 0000000..d72139d
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "aProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "aConsumer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceContextBadClassDistParams.json b/services/services-engine/src/test/resources/parameters/serviceContextBadClassDistParams.json
new file mode 100644 (file)
index 0000000..6468e10
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "contextParameters": {
+                "parameterClassName": "org.onap.policy.apex.context.parameters.ContextParameters",
+                "distributorParameters": {
+                    "parameterClassName": "org.onap.policy.apex.context.parameters.ContextParameters"
+                }
+            },
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceContextBadClassLockParams.json b/services/services-engine/src/test/resources/parameters/serviceContextBadClassLockParams.json
new file mode 100644 (file)
index 0000000..57a3802
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "contextParameters": {
+                "parameterClassName": "org.onap.policy.apex.context.parameters.ContextParameters",
+                "lockManagerParameters": {
+                    "parameterClassName": "org.onap.policy.apex.context.parameters.ContextParameters"
+                }
+            },
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceContextBadClassParams.json b/services/services-engine/src/test/resources/parameters/serviceContextBadClassParams.json
new file mode 100644 (file)
index 0000000..a292030
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "contextParameters": {
+                "parameterClassName": "java.lang.Integer"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceContextBadClassPersistParams.json b/services/services-engine/src/test/resources/parameters/serviceContextBadClassPersistParams.json
new file mode 100644 (file)
index 0000000..598c20b
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "contextParameters": {
+                "parameterClassName": "org.onap.policy.apex.context.parameters.ContextParameters",
+                "persistorParameters": {
+                    "parameterClassName": "org.onap.policy.apex.context.parameters.ContextParameters"
+                }
+            },
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceContextBadParams.json b/services/services-engine/src/test/resources/parameters/serviceContextBadParams.json
new file mode 100644 (file)
index 0000000..d850ba2
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "contextParameters": {
+                "parameterClassName": "hello"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceContextBadPluginClassParams.json b/services/services-engine/src/test/resources/parameters/serviceContextBadPluginClassParams.json
new file mode 100644 (file)
index 0000000..beb0490
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "contextParameters": {
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceContextBadPluginNameParams.json b/services/services-engine/src/test/resources/parameters/serviceContextBadPluginNameParams.json
new file mode 100644 (file)
index 0000000..d152809
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "contextParameters": {
+                "parameterClassNamelooby": ""
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceContextNoParams.json b/services/services-engine/src/test/resources/parameters/serviceContextNoParams.json
new file mode 100644 (file)
index 0000000..2d6cb4d
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "contextParameters": {
+                
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceContextOKDefaultParams.json b/services/services-engine/src/test/resources/parameters/serviceContextOKDefaultParams.json
new file mode 100644 (file)
index 0000000..56294a3
--- /dev/null
@@ -0,0 +1,45 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "contextParameters": {
+                "parameterClassName": "org.onap.policy.apex.context.parameters.ContextParameters"
+            },
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "FirstProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "MySuperDooperConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceContextOKDistParams.json b/services/services-engine/src/test/resources/parameters/serviceContextOKDistParams.json
new file mode 100644 (file)
index 0000000..1aa2abb
--- /dev/null
@@ -0,0 +1,48 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "contextParameters": {
+                "parameterClassName": "org.onap.policy.apex.context.parameters.ContextParameters",
+                "contextParameters": {
+                    "parameterClassName": "org.onap.policy.apex.context.parameters.DistributorParameters"
+                }
+            },
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "FirstProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "MySuperDooperConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceContextOKFlushParams.json b/services/services-engine/src/test/resources/parameters/serviceContextOKFlushParams.json
new file mode 100644 (file)
index 0000000..7d9eb6f
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "contextParameters": {
+                "parameterClassName": "org.onap.policy.apex.context.parameters.ContextParameters",
+                "persistorParameters": {
+                    "parameterClassName": "org.onap.policy.apex.context.parameters.PersistorParameters",
+                    "flushPeriod": 123456
+                }
+            },
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "FirstProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "MySuperDooperConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceContextOKFullParams.json b/services/services-engine/src/test/resources/parameters/serviceContextOKFullParams.json
new file mode 100644 (file)
index 0000000..2299105
--- /dev/null
@@ -0,0 +1,59 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "contextParameters": {
+                "parameterClassName": "org.onap.policy.apex.context.parameters.ContextParameters",
+                "distributorParameters": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperDistributorParameters",
+                    "configFile": "my/lovely/configFile.xml",
+                    "jgroupsFile": "holy/stone.xml",
+                    "preferIPv4Stack": false,
+                    "jGroupsBindAddress": "fatherted"
+                },
+                "lockManagerParameters": {
+                    "parameterClassName": "org.onap.policy.apex.context.parameters.LockManagerParameters"
+                },
+                "persistorParameters": {
+                    "parameterClassName": "org.onap.policy.apex.context.parameters.PersistorParameters",
+                    "flushPeriod": 123456
+                }
+            },
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "FirstProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "MySuperDooperConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceExecutorBadParams.json b/services/services-engine/src/test/resources/parameters/serviceExecutorBadParams.json
new file mode 100644 (file)
index 0000000..839694a
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                },
+                "ZOOBY": "hello"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceExecutorBadPluginNameParams.json b/services/services-engine/src/test/resources/parameters/serviceExecutorBadPluginNameParams.json
new file mode 100644 (file)
index 0000000..5a28d89
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                },
+                "ZOOBY": {
+                    "parameterClassNamelooby": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                },
+                "LOOBY": {
+                    "parameterClassNamelooby": ""
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceExecutorBadPluginValueBlankParams.json b/services/services-engine/src/test/resources/parameters/serviceExecutorBadPluginValueBlankParams.json
new file mode 100644 (file)
index 0000000..c70fa4c
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                },
+                "ZOOBY": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                },
+                "LOOBY": {
+                    "parameterClassName": "   "
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceExecutorBadPluginValueObjectParams.json b/services/services-engine/src/test/resources/parameters/serviceExecutorBadPluginValueObjectParams.json
new file mode 100644 (file)
index 0000000..200d8f1
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                },
+                "ZOOBY": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                },
+                "LOOBY": {
+                    "parameterClassName": {
+                        
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceExecutorBadPluginValueParams.json b/services/services-engine/src/test/resources/parameters/serviceExecutorBadPluginValueParams.json
new file mode 100644 (file)
index 0000000..b96a274
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                },
+                "ZOOBY": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                },
+                "LOOBY": {
+                    "parameterClassName": "helloworld"
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceExecutorEmptyParams.json b/services/services-engine/src/test/resources/parameters/serviceExecutorEmptyParams.json
new file mode 100644 (file)
index 0000000..f07eaff
--- /dev/null
@@ -0,0 +1,20 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                },
+                "ZOOBY": {
+                    
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceExecutorNoExecutorParams.json b/services/services-engine/src/test/resources/parameters/serviceExecutorNoExecutorParams.json
new file mode 100644 (file)
index 0000000..44d643c
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "someParameter": "someValue"
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/serviceExecutorNoParams.json b/services/services-engine/src/test/resources/parameters/serviceExecutorNoParams.json
new file mode 100644 (file)
index 0000000..751ac21
--- /dev/null
@@ -0,0 +1,40 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "FirstProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "MySuperDooperConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/superDooperParams.json b/services/services-engine/src/test/resources/parameters/superDooperParams.json
new file mode 100644 (file)
index 0000000..75820eb
--- /dev/null
@@ -0,0 +1,55 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 345,
+        "deploymentPort": 65522
+    },
+    "eventOutputParameters": {
+        "FirstProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters",
+                "parameters": {
+                    "bootstrapServers": "somehost:12345",
+                    "acks": 0,
+                    "retries": 25,
+                    "batchSize": 98765,
+                    "lingerTime": 21,
+                    "bufferMemory": 50505050,
+                    "groupId": "first-group-id",
+                    "enableAutoCommit": false,
+                    "autoCommitTime": 441,
+                    "sessionTimeout": 987,
+                    "producerTopic": "producer-out",
+                    "consumerPollTime": 101,
+                    "consumerTopicList": [
+                        "consumer-out-0",
+                        "consumer-out-1",
+                        "consumer-out-2"
+                    ],
+                    "keySerializer": "some.key.serailizer",
+                    "valueSerializer": "some.value.serailizer",
+                    "keyDeserializer": "some.key.deserailizer",
+                    "valueDeserializer": "some.value.deserailizer"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    },
+    "eventInputParameters": {
+        "MySuperDooperConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        }
+    }
+}
diff --git a/services/services-engine/src/test/resources/parameters/syncBadParamsBadPeers.json b/services/services-engine/src/test/resources/parameters/syncBadParamsBadPeers.json
new file mode 100644 (file)
index 0000000..6393d48
--- /dev/null
@@ -0,0 +1,72 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "SyncProducer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer1"
+        },
+        "SyncProducer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer0"
+        }
+    },
+    "eventInputParameters": {
+        "SyncConsumer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncConsumer1"
+        },
+        "SyncConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncConsumer0"
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/syncBadParamsBadTimeout.json b/services/services-engine/src/test/resources/parameters/syncBadParamsBadTimeout.json
new file mode 100644 (file)
index 0000000..a6de63f
--- /dev/null
@@ -0,0 +1,65 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "FirstProducer": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        },
+        "MyOtherProducer": {
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "synchronousTimeout": 12345
+        }
+    },
+    "eventInputParameters": {
+        "TheFileConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            }
+        },
+        "MySuperDooperConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/syncBadParamsInvalidTimeout.json b/services/services-engine/src/test/resources/parameters/syncBadParamsInvalidTimeout.json
new file mode 100644 (file)
index 0000000..ac24c82
--- /dev/null
@@ -0,0 +1,76 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "SyncProducer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousTimeout": -10,
+            "synchronousPeer": "SyncConsumer0"
+        },
+        "SyncProducer1": {
+            "synchronousMode": true,
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousTimeout": -3,
+            "synchronousPeer": "SyncConsumer1"
+        }
+    },
+    "eventInputParameters": {
+        "SyncConsumer0": {
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer0",
+            "synchronousTimeout": -1,
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            }
+        },
+        "SyncConsumer1": {
+            "synchronousPeer": "SyncProducer1",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "synchronousMode": true,
+            "synchronousTimeout": -99999999
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/syncBadParamsNoSyncWithPeer.json b/services/services-engine/src/test/resources/parameters/syncBadParamsNoSyncWithPeer.json
new file mode 100644 (file)
index 0000000..9884091
--- /dev/null
@@ -0,0 +1,71 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "SyncProducer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousPeer": "SyncConsumer0"
+        },
+        "SyncProducer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncConsumer1"
+        }
+    },
+    "eventInputParameters": {
+        "SyncConsumer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer0"
+        },
+        "SyncConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer1"
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/syncBadParamsNotSyncWithPeer.json b/services/services-engine/src/test/resources/parameters/syncBadParamsNotSyncWithPeer.json
new file mode 100644 (file)
index 0000000..477bf86
--- /dev/null
@@ -0,0 +1,72 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "SyncProducer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": false,
+            "synchronousPeer": "SyncConsumer0"
+        },
+        "SyncProducer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncConsumer1"
+        }
+    },
+    "eventInputParameters": {
+        "SyncConsumer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer0"
+        },
+        "SyncConsumer1": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer1"
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/syncBadParamsUnpairedTimeout.json b/services/services-engine/src/test/resources/parameters/syncBadParamsUnpairedTimeout.json
new file mode 100644 (file)
index 0000000..93c998b
--- /dev/null
@@ -0,0 +1,76 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "SyncProducer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousTimeout": 10,
+            "synchronousPeer": "SyncConsumer0"
+        },
+        "SyncProducer1": {
+            "synchronousMode": true,
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousTimeout": 3,
+            "synchronousPeer": "SyncConsumer1"
+        }
+    },
+    "eventInputParameters": {
+        "SyncConsumer0": {
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer0",
+            "synchronousTimeout": 1,
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            }
+        },
+        "SyncConsumer1": {
+            "synchronousPeer": "SyncProducer1",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "synchronousMode": true,
+            "synchronousTimeout": 99999999
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/syncGoodParams.json b/services/services-engine/src/test/resources/parameters/syncGoodParams.json
new file mode 100644 (file)
index 0000000..b2980aa
--- /dev/null
@@ -0,0 +1,72 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "SyncProducer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncConsumer0"
+        },
+        "SyncProducer1": {
+            "synchronousMode": true,
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousPeer": "SyncConsumer1"
+        }
+    },
+    "eventInputParameters": {
+        "SyncConsumer0": {
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer0",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            }
+        },
+        "SyncConsumer1": {
+            "synchronousPeer": "SyncProducer1",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "synchronousMode": true
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/syncGoodParamsBothTimeout.json b/services/services-engine/src/test/resources/parameters/syncGoodParamsBothTimeout.json
new file mode 100644 (file)
index 0000000..6862695
--- /dev/null
@@ -0,0 +1,76 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "SyncProducer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "synchronousTimeout": 12345,
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncConsumer0"
+        },
+        "SyncProducer1": {
+            "synchronousTimeout": 1,
+            "synchronousMode": true,
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousPeer": "SyncConsumer1"
+        }
+    },
+    "eventInputParameters": {
+        "SyncConsumer0": {
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousTimeout": 12345,
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer0",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            }
+        },
+        "SyncConsumer1": {
+            "synchronousPeer": "SyncProducer1",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "synchronousTimeout": 1,
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "synchronousMode": true
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/syncGoodParamsConsumerTimeout.json b/services/services-engine/src/test/resources/parameters/syncGoodParamsConsumerTimeout.json
new file mode 100644 (file)
index 0000000..d849040
--- /dev/null
@@ -0,0 +1,74 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "SyncProducer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncConsumer0"
+        },
+        "SyncProducer1": {
+            "synchronousMode": true,
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousPeer": "SyncConsumer1"
+        }
+    },
+    "eventInputParameters": {
+        "SyncConsumer0": {
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousTimeout": 12345,
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer0",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            }
+        },
+        "SyncConsumer1": {
+            "synchronousPeer": "SyncProducer1",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "synchronousTimeout": 1,
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "synchronousMode": true
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/syncGoodParamsProducerTimeout.json b/services/services-engine/src/test/resources/parameters/syncGoodParamsProducerTimeout.json
new file mode 100644 (file)
index 0000000..b248259
--- /dev/null
@@ -0,0 +1,74 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "SyncProducer0": {
+            "synchronousTimeout": 12345,
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncConsumer0"
+        },
+        "SyncProducer1": {
+            "synchronousMode": true,
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousPeer": "SyncConsumer1",
+            "synchronousTimeout": 1
+        }
+    },
+    "eventInputParameters": {
+        "SyncConsumer0": {
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer0",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            }
+        },
+        "SyncConsumer1": {
+            "synchronousPeer": "SyncProducer1",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "synchronousMode": true
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/syncMismatchedPeers.json b/services/services-engine/src/test/resources/parameters/syncMismatchedPeers.json
new file mode 100644 (file)
index 0000000..9e5399d
--- /dev/null
@@ -0,0 +1,72 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "SyncProducer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncConsumer1"
+        },
+        "SyncProducer1": {
+            "synchronousMode": true,
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousPeer": "SyncConsumer0"
+        }
+    },
+    "eventInputParameters": {
+        "SyncConsumer0": {
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer0",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            }
+        },
+        "SyncConsumer1": {
+            "synchronousPeer": "SyncProducer1",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "synchronousMode": true
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/syncUnusedConsumerPeers.json b/services/services-engine/src/test/resources/parameters/syncUnusedConsumerPeers.json
new file mode 100644 (file)
index 0000000..71337f3
--- /dev/null
@@ -0,0 +1,72 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "SyncProducer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncConsumer0"
+        },
+        "SyncProducer1": {
+            "synchronousMode": true,
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousPeer": "SyncConsumer0"
+        }
+    },
+    "eventInputParameters": {
+        "SyncConsumer0": {
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer0",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            }
+        },
+        "SyncConsumer1": {
+            "synchronousPeer": "SyncProducer1",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "synchronousMode": true
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/parameters/syncUnusedProducerPeers.json b/services/services-engine/src/test/resources/parameters/syncUnusedProducerPeers.json
new file mode 100644 (file)
index 0000000..4fe58ba
--- /dev/null
@@ -0,0 +1,72 @@
+{
+    "engineServiceParameters": {
+        "name": "MyApexEngine",
+        "version": "0.0.1",
+        "id": 45,
+        "instanceCount": 19,
+        "deploymentPort": 65522,
+        "policyModelFileName": "src/test/resources/policymodels/SamplePolicyModelMVEL.json",
+        "engineParameters": {
+            "executorParameters": {
+                "MVEL": {
+                    "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperExecutorParameters"
+                }
+            }
+        }
+    },
+    "eventOutputParameters": {
+        "SyncProducer0": {
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncConsumer0"
+        },
+        "SyncProducer1": {
+            "synchronousMode": true,
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/aaa.json"
+                }
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousPeer": "SyncConsumer1"
+        }
+    },
+    "eventInputParameters": {
+        "SyncConsumer0": {
+            "eventProtocolParameters": {
+                "eventProtocol": "JSON"
+            },
+            "synchronousMode": true,
+            "synchronousPeer": "SyncProducer1",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "FILE",
+                "parameters": {
+                    "fileName": "/tmp/bbb.json"
+                }
+            }
+        },
+        "SyncConsumer1": {
+            "synchronousPeer": "SyncProducer1",
+            "carrierTechnologyParameters": {
+                "carrierTechnology": "SUPER_DOOPER",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperDooperCarrierTechnologyParameters"
+            },
+            "eventProtocolParameters": {
+                "eventProtocol": "SUPER_TOK_DEL",
+                "parameterClassName": "org.onap.policy.apex.service.engine.parameters.dummyclasses.SuperTokenDelimitedEventProtocolParameters"
+            },
+            "synchronousMode": true
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/services-engine/src/test/resources/policymodels/SamplePolicyModelMVEL.json b/services/services-engine/src/test/resources/policymodels/SamplePolicyModelMVEL.json
new file mode 100644 (file)
index 0000000..95ea511
--- /dev/null
@@ -0,0 +1,7372 @@
+{
+    "apexPolicyModel": {
+        "key": {
+            "name": "SamplePolicyModelMVEL",
+            "version": "0.0.1"
+        },
+        "keyInformation": {
+            "key": {
+                "name": "KeyInformation",
+                "version": "0.0.1"
+            },
+            "keyInfoMap": {
+                "entry": [
+                    {
+                        "key": {
+                            "name": "Context",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Context",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "ca36bfd8-6042-3633-8c85-89c66507c3bf",
+                            "description": "Generated description for concept referred to by key \"Context:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0000",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0000",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "465a81cc-885f-3a4d-bc4e-1508da92b236",
+                            "description": "Generated description for concept referred to by key \"Event0000:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0001",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0001",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "36b2d570-fff7-3a4b-bab2-6bf492f5129a",
+                            "description": "Generated description for concept referred to by key \"Event0001:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0002",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0002",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "ff6160a7-fb5e-379c-a6d2-2cd28053eacf",
+                            "description": "Generated description for concept referred to by key \"Event0002:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0003",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0003",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "5899e216-2abf-3781-abc4-2c257b92721e",
+                            "description": "Generated description for concept referred to by key \"Event0003:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0004",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0004",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "7c2692a7-4587-3d09-abf9-d96b339a316f",
+                            "description": "Generated description for concept referred to by key \"Event0004:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0100",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0100",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "b696048c-c0b0-34c1-8dbe-32ab6c8bc0c7",
+                            "description": "Generated description for concept referred to by key \"Event0100:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0101",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0101",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "edbfa868-2ab2-30fd-8078-4c7f67ca6122",
+                            "description": "Generated description for concept referred to by key \"Event0101:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0102",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0102",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "6b6ad2ff-ef63-3f7b-aabb-fba44f8de9d4",
+                            "description": "Generated description for concept referred to by key \"Event0102:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0103",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0103",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "c2550912-10d9-3000-8826-377288cd6cb1",
+                            "description": "Generated description for concept referred to by key \"Event0103:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0104",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0104",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "f6d75b71-c8a7-3337-a121-88d68c389f5a",
+                            "description": "Generated description for concept referred to by key \"Event0104:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Events",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Events",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "0215644c-4531-375c-8335-d558b4de8c03",
+                            "description": "Generated description for concept referred to by key \"Events:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "ExternalContextAlbum",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "ExternalContextAlbum",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "976a79e7-5c80-3c03-9503-da3f41fec395",
+                            "description": "Generated description for concept referred to by key \"ExternalContextAlbum:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "GlobalContextAlbum",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "GlobalContextAlbum",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "c95e9e5f-d2c7-3ac7-a205-ea3574530cb7",
+                            "description": "Generated description for concept referred to by key \"GlobalContextAlbum:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "KeyInformation",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "KeyInformation",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "1ff2f905-685c-3caf-95bc-0bbc90345888",
+                            "description": "Generated description for concept referred to by key \"KeyInformation:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Policies",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Policies",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "f54c3b2b-be76-31c4-adfc-87c494c06808",
+                            "description": "Generated description for concept referred to by key \"Policies:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Policy0",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Policy0",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "3410e939-30ca-32c4-a2d8-c30b6fee6eec",
+                            "description": "Generated description for concept referred to by key \"Policy0:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Policy0ContextAlbum",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Policy0ContextAlbum",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "e27564c4-3cbf-3db2-9bf3-83ae80a2f907",
+                            "description": "Generated description for concept referred to by key \"Policy0ContextAlbum:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Policy1",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Policy1",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "d0b2b585-f344-33b8-af9e-250e7f4cfbce",
+                            "description": "Generated description for concept referred to by key \"Policy1:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Policy1ContextAlbum",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Policy1ContextAlbum",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "815d74ae-6fc0-3221-87b9-2bb1dfdfa7f0",
+                            "description": "Generated description for concept referred to by key \"Policy1ContextAlbum:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "SamplePolicyModelMVEL",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "SamplePolicyModelMVEL",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "a4cc4860-0bbc-389c-b270-e1bf7daffbe2",
+                            "description": "Generated description for concept referred to by key \"SamplePolicyModelMVEL:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Act0",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Act0",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "0589ff20-adcc-3ce5-95fe-8d7978ed54ed",
+                            "description": "Generated description for concept referred to by key \"Task_Act0:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Act1",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Act1",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "095b126d-ca8b-32c9-ad52-d744e817a79c",
+                            "description": "Generated description for concept referred to by key \"Task_Act1:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Act2",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Act2",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "3d786b4c-d9ee-3367-ab71-c67271a4ea2f",
+                            "description": "Generated description for concept referred to by key \"Task_Act2:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Act3",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Act3",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "9231753e-20c5-3436-982f-9100340cc570",
+                            "description": "Generated description for concept referred to by key \"Task_Act3:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Decide0",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Decide0",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "502383d3-483f-3a56-a426-2f0406674c8d",
+                            "description": "Generated description for concept referred to by key \"Task_Decide0:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Decide1",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Decide1",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "16598106-41c8-3b5a-99c6-5fcf6d1a5ddf",
+                            "description": "Generated description for concept referred to by key \"Task_Decide1:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Decide2",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Decide2",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "ad3a89f5-e369-3c66-b22c-669f7b3653b8",
+                            "description": "Generated description for concept referred to by key \"Task_Decide2:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Decide3",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Decide3",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "56815939-1164-3867-9ed1-0a27ff8aafb3",
+                            "description": "Generated description for concept referred to by key \"Task_Decide3:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Establish0",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Establish0",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "0db0c566-ecd7-3e27-9865-4b82c893abdb",
+                            "description": "Generated description for concept referred to by key \"Task_Establish0:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Establish1",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Establish1",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "6944a4c1-6201-317c-8d7e-eaa7f2ee0ea0",
+                            "description": "Generated description for concept referred to by key \"Task_Establish1:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Establish2",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Establish2",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "0f766ea9-11cd-3e7d-a8c8-28c8dee6a85a",
+                            "description": "Generated description for concept referred to by key \"Task_Establish2:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Establish3",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Establish3",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "c3237a38-cc6d-3418-b1e1-0dc8b4bdcc66",
+                            "description": "Generated description for concept referred to by key \"Task_Establish3:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Match0",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Match0",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "051bcfd5-cf73-3c89-8ee7-ea6e005ec059",
+                            "description": "Generated description for concept referred to by key \"Task_Match0:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Match1",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Match1",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "3754fe19-98f2-34a1-9f45-db31052208d8",
+                            "description": "Generated description for concept referred to by key \"Task_Match1:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Match2",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Match2",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "8c200709-a180-3c8b-916f-275ff49ce194",
+                            "description": "Generated description for concept referred to by key \"Task_Match2:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Match3",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Match3",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "a1a879c6-4510-33b0-bbd0-ad6256189a37",
+                            "description": "Generated description for concept referred to by key \"Task_Match3:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Tasks",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Tasks",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "a7fab96b-ce1c-37ce-bbb2-556b6db524a5",
+                            "description": "Generated description for concept referred to by key \"Tasks:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestCase",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestCase",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "0a652886-c88d-3f8c-8994-ae9161e7c963",
+                            "description": "Generated description for concept referred to by key \"TestCase:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem000",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem000",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "8efba9fa-371e-33df-a7d6-88b0284e7fd0",
+                            "description": "Generated description for concept referred to by key \"TestContextItem000:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem001",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem001",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "3740077c-a2b3-356b-81dc-5ded2118a951",
+                            "description": "Generated description for concept referred to by key \"TestContextItem001:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem002",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem002",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "b5c7df95-9af5-322f-9ea8-eb440a2bf926",
+                            "description": "Generated description for concept referred to by key \"TestContextItem002:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem003",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem003",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "b36f0aa5-0fb9-3e2c-8fa2-fddb7fd05f4b",
+                            "description": "Generated description for concept referred to by key \"TestContextItem003:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem004",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem004",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "093cda11-eaeb-3a46-a5b6-d5e30c00935b",
+                            "description": "Generated description for concept referred to by key \"TestContextItem004:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem005",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem005",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "569a758d-ba40-37c0-aebb-7ad138df25ac",
+                            "description": "Generated description for concept referred to by key \"TestContextItem005:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem006",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem006",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "252818d9-b61f-3962-a905-8865fb00fb04",
+                            "description": "Generated description for concept referred to by key \"TestContextItem006:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem007",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem007",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "fe1a5f7c-c083-377b-a797-752b01fc6c73",
+                            "description": "Generated description for concept referred to by key \"TestContextItem007:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem008",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem008",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "aa87d007-d07e-3f67-8c6d-0ebc3d85479d",
+                            "description": "Generated description for concept referred to by key \"TestContextItem008:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem009",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem009",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "126e7a3a-11b6-3f88-9397-c21d8819f859",
+                            "description": "Generated description for concept referred to by key \"TestContextItem009:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem00A",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem00A",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "0e0e3dec-e03d-3379-a87b-1ecd4aa3d8cc",
+                            "description": "Generated description for concept referred to by key \"TestContextItem00A:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem00B",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem00B",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "dbdc98df-3ff4-360c-b8d3-a7a836ac3de6",
+                            "description": "Generated description for concept referred to by key \"TestContextItem00B:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem00C",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem00C",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "32a2f355-77f3-3b25-ace6-7a9c5763a5ad",
+                            "description": "Generated description for concept referred to by key \"TestContextItem00C:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestDatatypes",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestDatatypes",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "3f95472c-973e-30e2-95f1-bf00cbef909a",
+                            "description": "Generated description for concept referred to by key \"TestDatatypes:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestExternalContextItem",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestExternalContextItem",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "610dbbd4-9149-3b3c-9af4-819056f0e169",
+                            "description": "Generated description for concept referred to by key \"TestExternalContextItem:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestGlobalContextItem",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestGlobalContextItem",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "07fa8f68-55f1-3fd0-81c1-749a379753a7",
+                            "description": "Generated description for concept referred to by key \"TestGlobalContextItem:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestPolicyContextItem",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestPolicyContextItem",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "d9c93cd1-539e-35c5-aaec-bb711ceb1251",
+                            "description": "Generated description for concept referred to by key \"TestPolicyContextItem:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestSlogan",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestSlogan",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "683fe492-7eae-3ac7-9924-bb7850208d05",
+                            "description": "Generated description for concept referred to by key \"TestSlogan:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestTemperature",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestTemperature",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "bba25b6f-e3cd-3060-9022-4ef3a79f8eb0",
+                            "description": "Generated description for concept referred to by key \"TestTemperature:0.0.1\""
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestTimestamp",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestTimestamp",
+                                "version": "0.0.1"
+                            },
+                            "UUID": "97b73937-c344-33c0-924c-4d26b6449564",
+                            "description": "Generated description for concept referred to by key \"TestTimestamp:0.0.1\""
+                        }
+                    }
+                ]
+            }
+        },
+        "policies": {
+            "key": {
+                "name": "Policies",
+                "version": "0.0.1"
+            },
+            "policyMap": {
+                "entry": [
+                    {
+                        "key": {
+                            "name": "Policy0",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "policyKey": {
+                                "name": "Policy0",
+                                "version": "0.0.1"
+                            },
+                            "template": "MEDA",
+                            "state": {
+                                "entry": [
+                                    {
+                                        "key": "Act",
+                                        "value": {
+                                            "stateKey": {
+                                                "parentKeyName": "Policy0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Act"
+                                            },
+                                            "trigger": {
+                                                "name": "Event0003",
+                                                "version": "0.0.1"
+                                            },
+                                            "stateOutputs": {
+                                                "entry": [
+                                                    {
+                                                        "key": "Act_NULL",
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Act_NULL"
+                                                            },
+                                                            "outgoingEvent": {
+                                                                "name": "Event0004",
+                                                                "version": "0.0.1"
+                                                            },
+                                                            "nextState": {
+                                                                "parentKeyName": "NULL",
+                                                                "parentKeyVersion": "0.0.0",
+                                                                "parentLocalName": "NULL",
+                                                                "localName": "NULL"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            },
+                                            "contextAlbumReference": [
+                                                {
+                                                    "name": "GlobalContextAlbum",
+                                                    "version": "0.0.1"
+                                                }
+                                            ],
+                                            "taskSelectionLogic": {
+                                                "key": "TaskSelectionLigic",
+                                                "logicFlavour": "MVEL",
+                                                "logic": "logger.debug(subject.id + \":\" + subject.stateName);\nsubject.defaultTaskKey.copyTo(selectedTask);\nreturn true;"
+                                            },
+                                            "stateFinalizerLogicMap": {
+                                                "entry": []
+                                            },
+                                            "defaultTask": {
+                                                "name": "Task_Act1",
+                                                "version": "0.0.1"
+                                            },
+                                            "taskReferences": {
+                                                "entry": [
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Act0",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Task_Act0_DIRECT_Act_NULL"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Act_NULL"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Act1",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Task_Act1_DIRECT_Act_NULL"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Act_NULL"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Act2",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Task_Act2_DIRECT_Act_NULL"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Act_NULL"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Act3",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Task_Act3_DIRECT_Act_NULL"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Act_NULL"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "key": "Decide",
+                                        "value": {
+                                            "stateKey": {
+                                                "parentKeyName": "Policy0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Decide"
+                                            },
+                                            "trigger": {
+                                                "name": "Event0002",
+                                                "version": "0.0.1"
+                                            },
+                                            "stateOutputs": {
+                                                "entry": [
+                                                    {
+                                                        "key": "Decide_Act",
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Decide_Act"
+                                                            },
+                                                            "outgoingEvent": {
+                                                                "name": "Event0003",
+                                                                "version": "0.0.1"
+                                                            },
+                                                            "nextState": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "NULL",
+                                                                "localName": "Act"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            },
+                                            "contextAlbumReference": [
+                                                {
+                                                    "name": "ExternalContextAlbum",
+                                                    "version": "0.0.1"
+                                                },
+                                                {
+                                                    "name": "GlobalContextAlbum",
+                                                    "version": "0.0.1"
+                                                },
+                                                {
+                                                    "name": "Policy0ContextAlbum",
+                                                    "version": "0.0.1"
+                                                }
+                                            ],
+                                            "taskSelectionLogic": {
+                                                "key": "TaskSelectionLigic",
+                                                "logicFlavour": "MVEL",
+                                                "logic": "logger.debug(subject.id + \":\" + subject.stateName);\nsubject.defaultTaskKey.copyTo(selectedTask);\nreturn true;"
+                                            },
+                                            "stateFinalizerLogicMap": {
+                                                "entry": []
+                                            },
+                                            "defaultTask": {
+                                                "name": "Task_Decide3",
+                                                "version": "0.0.1"
+                                            },
+                                            "taskReferences": {
+                                                "entry": [
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Decide0",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Task_Decide0_DIRECT_Decide_Act"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Decide_Act"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Decide1",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Task_Decide1_DIRECT_Decide_Act"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Decide_Act"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Decide2",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Task_Decide2_DIRECT_Decide_Act"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Decide_Act"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Decide3",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Task_Decide3_DIRECT_Decide_Act"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Decide_Act"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "key": "Establish",
+                                        "value": {
+                                            "stateKey": {
+                                                "parentKeyName": "Policy0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Establish"
+                                            },
+                                            "trigger": {
+                                                "name": "Event0001",
+                                                "version": "0.0.1"
+                                            },
+                                            "stateOutputs": {
+                                                "entry": [
+                                                    {
+                                                        "key": "Establish_Decide",
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Establish_Decide"
+                                                            },
+                                                            "outgoingEvent": {
+                                                                "name": "Event0002",
+                                                                "version": "0.0.1"
+                                                            },
+                                                            "nextState": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "NULL",
+                                                                "localName": "Decide"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            },
+                                            "contextAlbumReference": [
+                                                {
+                                                    "name": "ExternalContextAlbum",
+                                                    "version": "0.0.1"
+                                                },
+                                                {
+                                                    "name": "GlobalContextAlbum",
+                                                    "version": "0.0.1"
+                                                },
+                                                {
+                                                    "name": "Policy1ContextAlbum",
+                                                    "version": "0.0.1"
+                                                }
+                                            ],
+                                            "taskSelectionLogic": {
+                                                "key": "TaskSelectionLigic",
+                                                "logicFlavour": "MVEL",
+                                                "logic": "logger.debug(subject.id + \":\" + subject.stateName);\nsubject.defaultTaskKey.copyTo(selectedTask);\nreturn true;"
+                                            },
+                                            "stateFinalizerLogicMap": {
+                                                "entry": []
+                                            },
+                                            "defaultTask": {
+                                                "name": "Task_Establish2",
+                                                "version": "0.0.1"
+                                            },
+                                            "taskReferences": {
+                                                "entry": [
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Establish0",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Task_Establish0_DIRECT_Establish_Decide"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Establish_Decide"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Establish1",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Task_Establish1_DIRECT_Establish_Decide"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Establish_Decide"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Establish2",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Task_Establish2_DIRECT_Establish_Decide"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Establish_Decide"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Establish3",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Task_Establish3_DIRECT_Establish_Decide"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Establish_Decide"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "key": "Match",
+                                        "value": {
+                                            "stateKey": {
+                                                "parentKeyName": "Policy0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Match"
+                                            },
+                                            "trigger": {
+                                                "name": "Event0000",
+                                                "version": "0.0.1"
+                                            },
+                                            "stateOutputs": {
+                                                "entry": [
+                                                    {
+                                                        "key": "Match_Establish",
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Match_Establish"
+                                                            },
+                                                            "outgoingEvent": {
+                                                                "name": "Event0001",
+                                                                "version": "0.0.1"
+                                                            },
+                                                            "nextState": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "NULL",
+                                                                "localName": "Establish"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            },
+                                            "contextAlbumReference": [
+                                                {
+                                                    "name": "GlobalContextAlbum",
+                                                    "version": "0.0.1"
+                                                },
+                                                {
+                                                    "name": "Policy0ContextAlbum",
+                                                    "version": "0.0.1"
+                                                }
+                                            ],
+                                            "taskSelectionLogic": {
+                                                "key": "TaskSelectionLigic",
+                                                "logicFlavour": "MVEL",
+                                                "logic": "logger.debug(subject.id + \":\" + subject.stateName);\nsubject.defaultTaskKey.copyTo(selectedTask);\nreturn true;"
+                                            },
+                                            "stateFinalizerLogicMap": {
+                                                "entry": []
+                                            },
+                                            "defaultTask": {
+                                                "name": "Task_Match0",
+                                                "version": "0.0.1"
+                                            },
+                                            "taskReferences": {
+                                                "entry": [
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Match0",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Task_Match0_DIRECT_Match_Establish"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Match_Establish"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Match1",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Task_Match1_DIRECT_Match_Establish"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Match_Establish"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Match2",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Task_Match2_DIRECT_Match_Establish"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Match_Establish"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Match3",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Task_Match3_DIRECT_Match_Establish"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy0",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Match_Establish"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            }
+                                        }
+                                    }
+                                ]
+                            },
+                            "firstState": "Match"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Policy1",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "policyKey": {
+                                "name": "Policy1",
+                                "version": "0.0.1"
+                            },
+                            "template": "MEDA",
+                            "state": {
+                                "entry": [
+                                    {
+                                        "key": "Act",
+                                        "value": {
+                                            "stateKey": {
+                                                "parentKeyName": "Policy1",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Act"
+                                            },
+                                            "trigger": {
+                                                "name": "Event0103",
+                                                "version": "0.0.1"
+                                            },
+                                            "stateOutputs": {
+                                                "entry": [
+                                                    {
+                                                        "key": "Act_NULL",
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Act_NULL"
+                                                            },
+                                                            "outgoingEvent": {
+                                                                "name": "Event0104",
+                                                                "version": "0.0.1"
+                                                            },
+                                                            "nextState": {
+                                                                "parentKeyName": "NULL",
+                                                                "parentKeyVersion": "0.0.0",
+                                                                "parentLocalName": "NULL",
+                                                                "localName": "NULL"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            },
+                                            "contextAlbumReference": [
+                                                {
+                                                    "name": "GlobalContextAlbum",
+                                                    "version": "0.0.1"
+                                                }
+                                            ],
+                                            "taskSelectionLogic": {
+                                                "key": "TaskSelectionLigic",
+                                                "logicFlavour": "MVEL",
+                                                "logic": "logger.debug(subject.id + \":\" + subject.stateName);\nsubject.defaultTaskKey.copyTo(selectedTask);\nreturn true;"
+                                            },
+                                            "stateFinalizerLogicMap": {
+                                                "entry": []
+                                            },
+                                            "defaultTask": {
+                                                "name": "Task_Act0",
+                                                "version": "0.0.1"
+                                            },
+                                            "taskReferences": {
+                                                "entry": [
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Act0",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Task_Act0_DIRECT_Act_NULL"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Act_NULL"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Act1",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Task_Act1_DIRECT_Act_NULL"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Act_NULL"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Act2",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Task_Act2_DIRECT_Act_NULL"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Act_NULL"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Act3",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Task_Act3_DIRECT_Act_NULL"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Act",
+                                                                "localName": "Act_NULL"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "key": "Decide",
+                                        "value": {
+                                            "stateKey": {
+                                                "parentKeyName": "Policy1",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Decide"
+                                            },
+                                            "trigger": {
+                                                "name": "Event0102",
+                                                "version": "0.0.1"
+                                            },
+                                            "stateOutputs": {
+                                                "entry": [
+                                                    {
+                                                        "key": "Decide_Act",
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Decide_Act"
+                                                            },
+                                                            "outgoingEvent": {
+                                                                "name": "Event0103",
+                                                                "version": "0.0.1"
+                                                            },
+                                                            "nextState": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "NULL",
+                                                                "localName": "Act"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            },
+                                            "contextAlbumReference": [
+                                                {
+                                                    "name": "ExternalContextAlbum",
+                                                    "version": "0.0.1"
+                                                },
+                                                {
+                                                    "name": "GlobalContextAlbum",
+                                                    "version": "0.0.1"
+                                                },
+                                                {
+                                                    "name": "Policy1ContextAlbum",
+                                                    "version": "0.0.1"
+                                                }
+                                            ],
+                                            "taskSelectionLogic": {
+                                                "key": "TaskSelectionLigic",
+                                                "logicFlavour": "MVEL",
+                                                "logic": "logger.debug(subject.id + \":\" + subject.stateName);\nsubject.defaultTaskKey.copyTo(selectedTask);\nreturn true;"
+                                            },
+                                            "stateFinalizerLogicMap": {
+                                                "entry": []
+                                            },
+                                            "defaultTask": {
+                                                "name": "Task_Decide3",
+                                                "version": "0.0.1"
+                                            },
+                                            "taskReferences": {
+                                                "entry": [
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Decide0",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Task_Decide0_DIRECT_Decide_Act"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Decide_Act"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Decide1",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Task_Decide1_DIRECT_Decide_Act"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Decide_Act"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Decide2",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Task_Decide2_DIRECT_Decide_Act"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Decide_Act"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Decide3",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Task_Decide3_DIRECT_Decide_Act"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Decide",
+                                                                "localName": "Decide_Act"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "key": "Establish",
+                                        "value": {
+                                            "stateKey": {
+                                                "parentKeyName": "Policy1",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Establish"
+                                            },
+                                            "trigger": {
+                                                "name": "Event0101",
+                                                "version": "0.0.1"
+                                            },
+                                            "stateOutputs": {
+                                                "entry": [
+                                                    {
+                                                        "key": "Establish_Decide",
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Establish_Decide"
+                                                            },
+                                                            "outgoingEvent": {
+                                                                "name": "Event0102",
+                                                                "version": "0.0.1"
+                                                            },
+                                                            "nextState": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "NULL",
+                                                                "localName": "Decide"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            },
+                                            "contextAlbumReference": [
+                                                {
+                                                    "name": "ExternalContextAlbum",
+                                                    "version": "0.0.1"
+                                                },
+                                                {
+                                                    "name": "GlobalContextAlbum",
+                                                    "version": "0.0.1"
+                                                },
+                                                {
+                                                    "name": "Policy1ContextAlbum",
+                                                    "version": "0.0.1"
+                                                }
+                                            ],
+                                            "taskSelectionLogic": {
+                                                "key": "TaskSelectionLigic",
+                                                "logicFlavour": "MVEL",
+                                                "logic": "logger.debug(subject.id + \":\" + subject.stateName);\nsubject.defaultTaskKey.copyTo(selectedTask);\nreturn true;"
+                                            },
+                                            "stateFinalizerLogicMap": {
+                                                "entry": []
+                                            },
+                                            "defaultTask": {
+                                                "name": "Task_Establish1",
+                                                "version": "0.0.1"
+                                            },
+                                            "taskReferences": {
+                                                "entry": [
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Establish0",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Task_Establish0_DIRECT_Establish_Decide"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Establish_Decide"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Establish1",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Task_Establish1_DIRECT_Establish_Decide"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Establish_Decide"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Establish2",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Task_Establish2_DIRECT_Establish_Decide"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Establish_Decide"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Establish3",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Task_Establish3_DIRECT_Establish_Decide"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Establish",
+                                                                "localName": "Establish_Decide"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            }
+                                        }
+                                    },
+                                    {
+                                        "key": "Match",
+                                        "value": {
+                                            "stateKey": {
+                                                "parentKeyName": "Policy1",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Match"
+                                            },
+                                            "trigger": {
+                                                "name": "Event0100",
+                                                "version": "0.0.1"
+                                            },
+                                            "stateOutputs": {
+                                                "entry": [
+                                                    {
+                                                        "key": "Match_Establish",
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Match_Establish"
+                                                            },
+                                                            "outgoingEvent": {
+                                                                "name": "Event0101",
+                                                                "version": "0.0.1"
+                                                            },
+                                                            "nextState": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "NULL",
+                                                                "localName": "Establish"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            },
+                                            "contextAlbumReference": [
+                                                {
+                                                    "name": "ExternalContextAlbum",
+                                                    "version": "0.0.1"
+                                                },
+                                                {
+                                                    "name": "GlobalContextAlbum",
+                                                    "version": "0.0.1"
+                                                },
+                                                {
+                                                    "name": "Policy1ContextAlbum",
+                                                    "version": "0.0.1"
+                                                }
+                                            ],
+                                            "taskSelectionLogic": {
+                                                "key": "TaskSelectionLigic",
+                                                "logicFlavour": "MVEL",
+                                                "logic": "logger.debug(subject.id + \":\" + subject.stateName);\nsubject.defaultTaskKey.copyTo(selectedTask);\nreturn true;"
+                                            },
+                                            "stateFinalizerLogicMap": {
+                                                "entry": []
+                                            },
+                                            "defaultTask": {
+                                                "name": "Task_Match3",
+                                                "version": "0.0.1"
+                                            },
+                                            "taskReferences": {
+                                                "entry": [
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Match0",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Task_Match0_DIRECT_Match_Establish"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Match_Establish"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Match1",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Task_Match1_DIRECT_Match_Establish"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Match_Establish"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Match2",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Task_Match2_DIRECT_Match_Establish"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Match_Establish"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "key": {
+                                                            "name": "Task_Match3",
+                                                            "version": "0.0.1"
+                                                        },
+                                                        "value": {
+                                                            "key": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Task_Match3_DIRECT_Match_Establish"
+                                                            },
+                                                            "outputType": "DIRECT",
+                                                            "output": {
+                                                                "parentKeyName": "Policy1",
+                                                                "parentKeyVersion": "0.0.1",
+                                                                "parentLocalName": "Match",
+                                                                "localName": "Match_Establish"
+                                                            }
+                                                        }
+                                                    }
+                                                ]
+                                            }
+                                        }
+                                    }
+                                ]
+                            },
+                            "firstState": "Match"
+                        }
+                    }
+                ]
+            }
+        },
+        "tasks": {
+            "key": {
+                "name": "Tasks",
+                "version": "0.0.1"
+            },
+            "taskMap": {
+                "entry": [
+                    {
+                        "key": {
+                            "name": "Task_Act0",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Act0",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestActCaseSelected",
+                                        "value": {
+                                            "key": "TestActCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestActStateTime",
+                                        "value": {
+                                            "key": "TestActStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Act0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    },
+                                    {
+                                        "key": "Parameter1",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Act0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter1"
+                                            },
+                                            "defaultValue": "DefaultValue1"
+                                        }
+                                    },
+                                    {
+                                        "key": "Parameter2",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Act0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter2"
+                                            },
+                                            "defaultValue": "DefaultValue2"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "ExternalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy0ContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy1ContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestActCaseSelected\"] = (byte)2;\ntimeNow = new Date();\noutFields[\"TestActStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Act1",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Act1",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestActCaseSelected",
+                                        "value": {
+                                            "key": "TestActCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestActStateTime",
+                                        "value": {
+                                            "key": "TestActStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Act1",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    },
+                                    {
+                                        "key": "Parameter1",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Act1",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter1"
+                                            },
+                                            "defaultValue": "DefaultValue1"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy0ContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestActCaseSelected\"] = (byte)3;\ntimeNow = new Date();\noutFields[\"TestActStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Act2",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Act2",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestActCaseSelected",
+                                        "value": {
+                                            "key": "TestActCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestActStateTime",
+                                        "value": {
+                                            "key": "TestActStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Act2",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy1ContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestActCaseSelected\"] = (byte)0;\ntimeNow = new Date();\noutFields[\"TestActStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Act3",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Act3",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestActCaseSelected",
+                                        "value": {
+                                            "key": "TestActCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestActStateTime",
+                                        "value": {
+                                            "key": "TestActStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Act3",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "ExternalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestActCaseSelected\"] = (byte)1;\ntimeNow = new Date();\noutFields[\"TestActStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Decide0",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Decide0",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Decide0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    },
+                                    {
+                                        "key": "Parameter1",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Decide0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter1"
+                                            },
+                                            "defaultValue": "DefaultValue1"
+                                        }
+                                    },
+                                    {
+                                        "key": "Parameter2",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Decide0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter2"
+                                            },
+                                            "defaultValue": "DefaultValue2"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "ExternalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy0ContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy1ContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestDecideCaseSelected\"] = (byte)2;\ntimeNow = new Date();\noutFields[\"TestDecideStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Decide1",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Decide1",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Decide1",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    },
+                                    {
+                                        "key": "Parameter1",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Decide1",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter1"
+                                            },
+                                            "defaultValue": "DefaultValue1"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy0ContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestDecideCaseSelected\"] = (byte)3;\ntimeNow = new Date();\noutFields[\"TestDecideStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Decide2",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Decide2",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Decide2",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy1ContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestDecideCaseSelected\"] = (byte)0;\ntimeNow = new Date();\noutFields[\"TestDecideStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Decide3",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Decide3",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Decide3",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "ExternalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestDecideCaseSelected\"] = (byte)1;\ntimeNow = new Date();\noutFields[\"TestDecideStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Establish0",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Establish0",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Establish0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    },
+                                    {
+                                        "key": "Parameter1",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Establish0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter1"
+                                            },
+                                            "defaultValue": "DefaultValue1"
+                                        }
+                                    },
+                                    {
+                                        "key": "Parameter2",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Establish0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter2"
+                                            },
+                                            "defaultValue": "DefaultValue2"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "ExternalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy0ContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy1ContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestEstablishCaseSelected\"] = (byte)2;\ntimeNow = new Date();\noutFields[\"TestEstablishStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Establish1",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Establish1",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Establish1",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    },
+                                    {
+                                        "key": "Parameter1",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Establish1",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter1"
+                                            },
+                                            "defaultValue": "DefaultValue1"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy0ContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestEstablishCaseSelected\"] = (byte)3;\ntimeNow = new Date();\noutFields[\"TestEstablishStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Establish2",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Establish2",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Establish2",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy1ContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestEstablishCaseSelected\"] = (byte)0;\ntimeNow = new Date();\noutFields[\"TestEstablishStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Establish3",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Establish3",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Establish3",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "ExternalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestEstablishCaseSelected\"] = (byte)1;\ntimeNow = new Date();\noutFields[\"TestEstablishStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Match0",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Match0",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Match0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    },
+                                    {
+                                        "key": "Parameter1",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Match0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter1"
+                                            },
+                                            "defaultValue": "DefaultValue1"
+                                        }
+                                    },
+                                    {
+                                        "key": "Parameter2",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Match0",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter2"
+                                            },
+                                            "defaultValue": "DefaultValue2"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "ExternalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy0ContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy1ContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestMatchCaseSelected\"] = (byte)2;\ntimeNow = new Date();\noutFields[\"TestMatchStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Match1",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Match1",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Match1",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    },
+                                    {
+                                        "key": "Parameter1",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Match1",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter1"
+                                            },
+                                            "defaultValue": "DefaultValue1"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy0ContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestMatchCaseSelected\"] = (byte)3;\ntimeNow = new Date();\noutFields[\"TestMatchStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Match2",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Match2",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Match2",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "Policy1ContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestMatchCaseSelected\"] = (byte)0;\ntimeNow = new Date();\noutFields[\"TestMatchStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Task_Match3",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Task_Match3",
+                                "version": "0.0.1"
+                            },
+                            "inputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "outputFields": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            },
+                            "taskParameters": {
+                                "entry": [
+                                    {
+                                        "key": "Parameter0",
+                                        "value": {
+                                            "key": {
+                                                "parentKeyName": "Task_Match3",
+                                                "parentKeyVersion": "0.0.1",
+                                                "parentLocalName": "NULL",
+                                                "localName": "Parameter0"
+                                            },
+                                            "defaultValue": "DefaultValue0"
+                                        }
+                                    }
+                                ]
+                            },
+                            "contextAlbumReference": [
+                                {
+                                    "name": "ExternalContextAlbum",
+                                    "version": "0.0.1"
+                                },
+                                {
+                                    "name": "GlobalContextAlbum",
+                                    "version": "0.0.1"
+                                }
+                            ],
+                            "taskLogic": {
+                                "key": "_TaskLogic",
+                                "logicFlavour": "MVEL",
+                                "logic": "import java.util.Date;\nlogger.debug(subject.id);\ngc = getContextAlbum(\"GlobalContextAlbum\");\nlogger.debug(gc);\nlogger.debug(inFields);\noutFields[\"TestMatchCaseSelected\"] = (byte)1;\ntimeNow = new Date();\noutFields[\"TestMatchStateTime\"] = timeNow.getTime();\nlogger.debug(outFields);\nreturn true;"
+                            }
+                        }
+                    }
+                ]
+            }
+        },
+        "events": {
+            "key": {
+                "name": "Events",
+                "version": "0.0.1"
+            },
+            "eventMap": {
+                "entry": [
+                    {
+                        "key": {
+                            "name": "Event0000",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0000",
+                                "version": "0.0.1"
+                            },
+                            "nameSpace": "org.onap.policy.apex.sample.events",
+                            "source": "Outside",
+                            "target": "Match",
+                            "parameter": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0001",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0001",
+                                "version": "0.0.1"
+                            },
+                            "nameSpace": "org.onap.policy.apex.sample.events",
+                            "source": "Match",
+                            "target": "Establish",
+                            "parameter": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0002",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0002",
+                                "version": "0.0.1"
+                            },
+                            "nameSpace": "org.onap.policy.apex.sample.events",
+                            "source": "Establish",
+                            "target": "Decide",
+                            "parameter": {
+                                "entry": [
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0003",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0003",
+                                "version": "0.0.1"
+                            },
+                            "nameSpace": "org.onap.policy.apex.sample.events",
+                            "source": "Decide",
+                            "target": "Act",
+                            "parameter": {
+                                "entry": [
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0004",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0004",
+                                "version": "0.0.1"
+                            },
+                            "nameSpace": "org.onap.policy.apex.sample.events",
+                            "source": "Act",
+                            "target": "Outside",
+                            "parameter": {
+                                "entry": [
+                                    {
+                                        "key": "TestActCaseSelected",
+                                        "value": {
+                                            "key": "TestActCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestActStateTime",
+                                        "value": {
+                                            "key": "TestActStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0100",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0100",
+                                "version": "0.0.1"
+                            },
+                            "nameSpace": "org.onap.policy.apex.sample.events",
+                            "source": "Outside",
+                            "target": "Match",
+                            "parameter": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0101",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0101",
+                                "version": "0.0.1"
+                            },
+                            "nameSpace": "org.onap.policy.apex.sample.events",
+                            "source": "Match",
+                            "target": "Establish",
+                            "parameter": {
+                                "entry": [
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0102",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0102",
+                                "version": "0.0.1"
+                            },
+                            "nameSpace": "org.onap.policy.apex.sample.events",
+                            "source": "Establish",
+                            "target": "Decide",
+                            "parameter": {
+                                "entry": [
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0103",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0103",
+                                "version": "0.0.1"
+                            },
+                            "nameSpace": "org.onap.policy.apex.sample.events",
+                            "source": "Decide",
+                            "target": "Act",
+                            "parameter": {
+                                "entry": [
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Event0104",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Event0104",
+                                "version": "0.0.1"
+                            },
+                            "nameSpace": "org.onap.policy.apex.sample.events",
+                            "source": "Act",
+                            "target": "Outside",
+                            "parameter": {
+                                "entry": [
+                                    {
+                                        "key": "TestActCaseSelected",
+                                        "value": {
+                                            "key": "TestActCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestActStateTime",
+                                        "value": {
+                                            "key": "TestActStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideCaseSelected",
+                                        "value": {
+                                            "key": "TestDecideCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestDecideStateTime",
+                                        "value": {
+                                            "key": "TestDecideStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishCaseSelected",
+                                        "value": {
+                                            "key": "TestEstablishCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestEstablishStateTime",
+                                        "value": {
+                                            "key": "TestEstablishStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCase",
+                                        "value": {
+                                            "key": "TestMatchCase",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchCaseSelected",
+                                        "value": {
+                                            "key": "TestMatchCaseSelected",
+                                            "fieldSchemaKey": {
+                                                "name": "TestCase",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestMatchStateTime",
+                                        "value": {
+                                            "key": "TestMatchStateTime",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestSlogan",
+                                        "value": {
+                                            "key": "TestSlogan",
+                                            "fieldSchemaKey": {
+                                                "name": "TestSlogan",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTemperature",
+                                        "value": {
+                                            "key": "TestTemperature",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTemperature",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    },
+                                    {
+                                        "key": "TestTimestamp",
+                                        "value": {
+                                            "key": "TestTimestamp",
+                                            "fieldSchemaKey": {
+                                                "name": "TestTimestamp",
+                                                "version": "0.0.1"
+                                            },
+                                            "optional": false
+                                        }
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                ]
+            }
+        },
+        "albums": {
+            "key": {
+                "name": "Context",
+                "version": "0.0.1"
+            },
+            "albums": {
+                "entry": [
+                    {
+                        "key": {
+                            "name": "ExternalContextAlbum",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "ExternalContextAlbum",
+                                "version": "0.0.1"
+                            },
+                            "scope": "EXTERNAL",
+                            "isWritable": false,
+                            "itemSchema": {
+                                "name": "TestExternalContextItem",
+                                "version": "0.0.1"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "GlobalContextAlbum",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "GlobalContextAlbum",
+                                "version": "0.0.1"
+                            },
+                            "scope": "GLOBAL",
+                            "isWritable": true,
+                            "itemSchema": {
+                                "name": "TestGlobalContextItem",
+                                "version": "0.0.1"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Policy0ContextAlbum",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Policy0ContextAlbum",
+                                "version": "0.0.1"
+                            },
+                            "scope": "APPLICATION",
+                            "isWritable": true,
+                            "itemSchema": {
+                                "name": "TestPolicyContextItem",
+                                "version": "0.0.1"
+                            }
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "Policy1ContextAlbum",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "Policy1ContextAlbum",
+                                "version": "0.0.1"
+                            },
+                            "scope": "APPLICATION",
+                            "isWritable": true,
+                            "itemSchema": {
+                                "name": "TestPolicyContextItem",
+                                "version": "0.0.1"
+                            }
+                        }
+                    }
+                ]
+            }
+        },
+        "schemas": {
+            "key": {
+                "name": "TestDatatypes",
+                "version": "0.0.1"
+            },
+            "schemas": {
+                "entry": [
+                    {
+                        "key": {
+                            "name": "TestCase",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestCase",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "java.lang.Byte"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem000",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem000",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem000"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem001",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem001",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem001"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem002",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem002",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem002"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem003",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem003",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem003"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem004",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem004",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem004"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem005",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem005",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem005"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem006",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem006",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem006"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem007",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem007",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem007"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem008",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem008",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem008"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem009",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem009",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem009"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem00A",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem00A",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem00A"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem00B",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem00B",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem00B"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestContextItem00C",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestContextItem00C",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestContextItem00C"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestExternalContextItem",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestExternalContextItem",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestExternalContextItem"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestGlobalContextItem",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestGlobalContextItem",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestGlobalContextItem"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestPolicyContextItem",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestPolicyContextItem",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "org.onap.policy.apex.context.test.concepts.TestPolicyContextItem"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestSlogan",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestSlogan",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "java.lang.String"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestTemperature",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestTemperature",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "java.lang.Double"
+                        }
+                    },
+                    {
+                        "key": {
+                            "name": "TestTimestamp",
+                            "version": "0.0.1"
+                        },
+                        "value": {
+                            "key": {
+                                "name": "TestTimestamp",
+                                "version": "0.0.1"
+                            },
+                            "schemaFlavour": "Java",
+                            "schemaDefinition": "java.lang.Long"
+                        }
+                    }
+                ]
+            }
+        }
+    }
+}