Adding apex plugins/plugins-context modules 83/50383/1
authorwaqas.ikram <waqas.ikram@ericsson.com>
Tue, 5 Jun 2018 15:18:01 +0000 (16:18 +0100)
committerwaqas.ikram <waqas.ikram@ericsson.com>
Tue, 5 Jun 2018 15:18:47 +0000 (16:18 +0100)
Change-Id: I36fc295ffbd22661bf8bd091bfb20ebf6dcc7f5e
Issue-ID: POLICY-862
Signed-off-by: waqas.ikram <waqas.ikram@ericsson.com>
113 files changed:
plugins/plugins-context/context-distribution/context-distribution-hazelcast/pom.xml [new file with mode: 0644]
plugins/plugins-context/context-distribution/context-distribution-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/distribution/hazelcast/HazelcastContextDistributor.java [new file with mode: 0644]
plugins/plugins-context/context-distribution/context-distribution-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/distribution/hazelcast/package-info.java [new file with mode: 0644]
plugins/plugins-context/context-distribution/context-distribution-hazelcast/src/main/resources/hazelcast/hazelcast.xml.sample [new file with mode: 0644]
plugins/plugins-context/context-distribution/context-distribution-infinispan/pom.xml [new file with mode: 0644]
plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/java/org/onap/policy/apex/plugins/context/distribution/infinispan/InfinispanContextDistributor.java [new file with mode: 0644]
plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/java/org/onap/policy/apex/plugins/context/distribution/infinispan/InfinispanDistributorParameters.java [new file with mode: 0644]
plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/java/org/onap/policy/apex/plugins/context/distribution/infinispan/InfinispanManager.java [new file with mode: 0644]
plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/java/org/onap/policy/apex/plugins/context/distribution/infinispan/package-info.java [new file with mode: 0644]
plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/resources/infinispan/infinispan.xml.sample [new file with mode: 0644]
plugins/plugins-context/context-distribution/pom.xml [new file with mode: 0644]
plugins/plugins-context/context-locking/context-locking-curator/pom.xml [new file with mode: 0644]
plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/CuratorLockFacade.java [new file with mode: 0644]
plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/CuratorLockManager.java [new file with mode: 0644]
plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/CuratorLockManagerParameters.java [new file with mode: 0644]
plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/CuratorReentrantReadWriteLock.java [new file with mode: 0644]
plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/package-info.java [new file with mode: 0644]
plugins/plugins-context/context-locking/context-locking-hazelcast/pom.xml [new file with mode: 0644]
plugins/plugins-context/context-locking/context-locking-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/locking/hazelcast/HazelcastLock.java [new file with mode: 0644]
plugins/plugins-context/context-locking/context-locking-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/locking/hazelcast/HazelcastLockManager.java [new file with mode: 0644]
plugins/plugins-context/context-locking/context-locking-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/locking/hazelcast/package-info.java [new file with mode: 0644]
plugins/plugins-context/context-locking/pom.xml [new file with mode: 0644]
plugins/plugins-context/context-metrics/pom.xml [new file with mode: 0644]
plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/ConcurrentContextMetrics.java [new file with mode: 0644]
plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/ConcurrentContextMetricsJVM.java [new file with mode: 0644]
plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/ConcurrentContextMetricsJVMThread.java [new file with mode: 0644]
plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/ConcurrentContextMetricsThread.java [new file with mode: 0644]
plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/package-info.java [new file with mode: 0644]
plugins/plugins-context/context-metrics/src/test/java/org/onap/policy/apex/plugins/context/metrics/TestMetrics.java [new file with mode: 0644]
plugins/plugins-context/context-metrics/src/test/resources/hazelcast/hazelcast.xml [new file with mode: 0644]
plugins/plugins-context/context-metrics/src/test/resources/infinispan/infinispan.xml [new file with mode: 0644]
plugins/plugins-context/context-persistence/pom.xml [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/pom.xml [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroArrayObjectMapper.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroBytesObjectMapper.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroDirectObjectMapper.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroEnumObjectMapper.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroNullableMapper.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapper.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapperFactory.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroRecordObjectMapper.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelper.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelperParameters.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaKeyTranslationUtilities.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroStringObjectMapper.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/package-info.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaAAI.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaArray.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaEnum.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaFixed.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaHelperBadSchemas.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaHelperMarshal.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaHelperUnmarshal.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaMap.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaRecord.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaUnion.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestHealthCheckSchema.java [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/AAIInventoryResponseItemType.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/ArrayExampleAddress.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/ArrayExampleLong.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/EnumSchema.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/FixedSchema.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/HealthCheckBodyType.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/MapExampleAddress.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/MapExampleAddressInvalidFields.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/MapExampleLong.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/RecordExample.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/RecordExampleInvalidFields.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/RecordExampleVPN.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/RecordExampleVPNReuse.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/UnionExample.avsc [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/AAIResponse4Policy.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/AAIResponse4VNF.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/AAIResponseExample.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/ArrayExampleAddressFull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/ArrayExampleAddressNull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/ArrayExampleLongFull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/ArrayExampleLongNull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/EnumExampleBad0.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/EnumExampleBad1.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/EnumExampleHearts.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/EnumExampleNull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/FixedExampleBad0.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/FixedExampleBad1.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/FixedExampleGood.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/FixedExampleNull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/HealthCheckEvent.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleAddressFull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleAddressInvalidFields.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleAddressNull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleLongFull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleLongNull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/RecordExampleFull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/RecordExampleInvalidFields.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/RecordExampleNull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/RecordExampleVPNFull.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/UnionExampleAllFields.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/UnionExampleNullField.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/UnionExampleOptionalField.json [new file with mode: 0644]
plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/logback-test.xml [new file with mode: 0644]
plugins/plugins-context/context-schema/pom.xml [new file with mode: 0644]
plugins/plugins-context/plugins-context-test/pom.xml [new file with mode: 0644]
plugins/plugins-context/plugins-context-test/src/main/java/org/onap/policy/apex/plugins/context/test/HazelcastContextInjection.java [new file with mode: 0644]
plugins/plugins-context/plugins-context-test/src/main/java/org/onap/policy/apex/plugins/context/test/package-info.java [new file with mode: 0644]
plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/distribution/TestContextAlbumUpdate.java [new file with mode: 0644]
plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/distribution/TestContextInstantiation.java [new file with mode: 0644]
plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/distribution/TestContextUpdate.java [new file with mode: 0644]
plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/distribution/TestSequentialContextInstantiation.java [new file with mode: 0644]
plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/locking/CuratorManagerTest.java [new file with mode: 0644]
plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/locking/TestConcurrentContext.java [new file with mode: 0644]
plugins/plugins-context/pom.xml [new file with mode: 0644]
plugins/pom.xml [new file with mode: 0644]
pom.xml

diff --git a/plugins/plugins-context/context-distribution/context-distribution-hazelcast/pom.xml b/plugins/plugins-context/context-distribution/context-distribution-hazelcast/pom.xml
new file mode 100644 (file)
index 0000000..ce80a7a
--- /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.plugins.plugins-context.context-distribution</groupId>
+        <artifactId>context-distribution</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>context-distribution-hazelcast</artifactId>
+    <name>${project.artifactId}</name>
+    <description>[${project.parent.artifactId}] Plugin for distribution using Hazelcast</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.hazelcast</groupId>
+            <artifactId>hazelcast</artifactId>
+            <version>${version.hazelcast}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/plugins/plugins-context/context-distribution/context-distribution-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/distribution/hazelcast/HazelcastContextDistributor.java b/plugins/plugins-context/context-distribution/context-distribution-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/distribution/hazelcast/HazelcastContextDistributor.java
new file mode 100644 (file)
index 0000000..2b17b17
--- /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.plugins.context.distribution.hazelcast;
+
+import java.util.Map;
+
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.context.impl.distribution.AbstractDistributor;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import com.hazelcast.core.Hazelcast;
+import com.hazelcast.core.HazelcastInstance;
+
+/**
+ * This context distributor distributes context across threads in multiple JVMs on multiple hosts.
+ * It uses hazelcast to distribute maps.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class HazelcastContextDistributor extends AbstractDistributor {
+    // Logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(HazelcastContextDistributor.class);
+
+    // The hazelcast instance for distributing context for this JVM
+    private static HazelcastInstance hazelcastInstance = null;
+
+    /**
+     * Create an instance of a Hazelcast Context Distributor.
+     *
+     * @throws ContextException On errors creating the context distributor
+     */
+    public HazelcastContextDistributor() throws ContextException {
+        super();
+        LOGGER.entry("HazelcastContextDistributor()");
+
+        LOGGER.exit("HazelcastContextDistributor()");
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.context.impl.distribution.AbstractContextDistributor#init(org.onap.
+     * policy.apex.model.basicmodel.concepts.AxArtifactKey)
+     */
+    @Override
+    public void init(final AxArtifactKey key) throws ContextException {
+        LOGGER.entry("init(" + key + ")");
+
+        super.init(key);
+
+        // Create the hazelcast instance if it does not already exist
+        if (hazelcastInstance == null) {
+            hazelcastInstance = Hazelcast.newHazelcastInstance();
+        }
+
+        LOGGER.exit("init(" + key + ")");
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.core.context.impl.distribution.AbstractContextDistributor#
+     * getContextAlbumMap(org.onap.policy.apex.core.model.concepts.AxArtifactKey)
+     */
+    @Override
+    public Map<String, Object> getContextAlbumMap(final AxArtifactKey contextAlbumKey) {
+        // Get the map from Hazelcast
+        LOGGER.info("HazelcastContextDistributor: create album: " + contextAlbumKey.getID());
+        return hazelcastInstance.getMap(contextAlbumKey.getID());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.core.context.impl.distribution.AbstractContextDistributor#shutdown()
+     */
+    @Override
+    public void shutdown() {
+        // Shut down the hazelcast instance
+        if (hazelcastInstance != null) {
+            hazelcastInstance.shutdown();
+        }
+        hazelcastInstance = null;
+    }
+}
diff --git a/plugins/plugins-context/context-distribution/context-distribution-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/distribution/hazelcast/package-info.java b/plugins/plugins-context/context-distribution/context-distribution-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/distribution/hazelcast/package-info.java
new file mode 100644 (file)
index 0000000..027aeec
--- /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 <a href="http://hazelcast.org/">Hazelcast</a> context distributor for distribution
+ * of Apex context across JVMs.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.plugins.context.distribution.hazelcast;
diff --git a/plugins/plugins-context/context-distribution/context-distribution-hazelcast/src/main/resources/hazelcast/hazelcast.xml.sample b/plugins/plugins-context/context-distribution/context-distribution-hazelcast/src/main/resources/hazelcast/hazelcast.xml.sample
new file mode 100644 (file)
index 0000000..5f6c1b0
--- /dev/null
@@ -0,0 +1,55 @@
+<?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=========================================================
+-->
+
+<hazelcast xmlns="http://www.hazelcast.com/schema/config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <group>
+        <name>ApexHazelcastGroup</name>
+        <password>ApexHazelcastGroupPassword</password>
+    </group>
+    <network>
+        <port auto-increment="true">5706</port>
+        <join>
+            <multicast enabled="false">
+                <multicast-group>224.2.2.10</multicast-group>
+                <multicast-port>54327</multicast-port>
+            </multicast>
+            <tcp-ip enabled="true">
+                <members>127.0.0.1</members>
+            </tcp-ip>
+        </join>
+        <interfaces enabled="false">
+            <!-- This value will allow hazelcast to run locally from the IDE -->
+            <interface>127.0.0.*</interface>
+        </interfaces>
+    </network>
+    <properties>
+        <property name="hazelcast.icmp.enabled">true</property>
+        <property name="hazelcast.logging.type">slf4j</property>
+        <!-- disable the hazelcast shutdown hook - prefer to control the shutdown 
+            in code -->
+        <property name="hazelcast.shutdownhook.enabled">false</property>
+        <property name="hazelcast.graceful.shutdown.max.wait">60</property>
+    </properties>
+    <executor-service>
+        <pool-size>16</pool-size>
+    </executor-service>
+</hazelcast>
diff --git a/plugins/plugins-context/context-distribution/context-distribution-infinispan/pom.xml b/plugins/plugins-context/context-distribution/context-distribution-infinispan/pom.xml
new file mode 100644 (file)
index 0000000..7592edd
--- /dev/null
@@ -0,0 +1,47 @@
+<!--
+  ============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.plugins.plugins-context.context-distribution</groupId>
+        <artifactId>context-distribution</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>context-distribution-infinispan</artifactId>
+    <name>${project.artifactId}</name>
+    <description>[${project.parent.artifactId}] Plugin for distribution using Infinispan</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.infinispan</groupId>
+            <artifactId>infinispan-core</artifactId>
+            <version>9.2.2.Final</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.jboss.slf4j</groupId>
+                    <artifactId>slf4j-jboss-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/java/org/onap/policy/apex/plugins/context/distribution/infinispan/InfinispanContextDistributor.java b/plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/java/org/onap/policy/apex/plugins/context/distribution/infinispan/InfinispanContextDistributor.java
new file mode 100644 (file)
index 0000000..9361d0b
--- /dev/null
@@ -0,0 +1,115 @@
+/*-
+ * ============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.plugins.context.distribution.infinispan;
+
+import java.util.Map;
+
+import org.infinispan.Cache;
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.context.impl.distribution.AbstractDistributor;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.service.ParameterService;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This context distributor distributes context across threads in multiple JVMs on multiple hosts.
+ * It uses Infinispan to distribute maps.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class InfinispanContextDistributor extends AbstractDistributor {
+    // Logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(InfinispanContextDistributor.class);
+
+    // The infinispan manager for distributing context for this JVM
+    private static InfinispanManager infinispanManager = null;
+
+    /**
+     * Create an instance of an Infinispan Context Distributor.
+     *
+     * @throws ContextException On errors creating the context distributor
+     */
+    public InfinispanContextDistributor() throws ContextException {
+        LOGGER.entry("InfinispanContextDistributor()");
+
+        LOGGER.exit("InfinispanContextDistributor()");
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * com.ericsson.apex.context.impl.distribution.AbstractContextDistributor#init(com.ericsson.apex
+     * .model.basicmodel.concepts.AxArtifactKey)
+     */
+    @Override
+    public void init(final AxArtifactKey key) throws ContextException {
+        LOGGER.entry("init(" + key + ")");
+
+        super.init(key);
+
+        // Create the infinispan manager if it does not already exist
+        if (infinispanManager == null) {
+            // Get the parameters from the parameter service
+            final InfinispanDistributorParameters parameters =
+                    ParameterService.getParameters(InfinispanDistributorParameters.class);
+
+            LOGGER.debug("initiating Infinispan with the parameters: " + parameters);
+
+            // Create the manager
+            infinispanManager = new InfinispanManager(parameters);
+        }
+
+        LOGGER.exit("init(" + key + ")");
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.apex.core.context.impl.distribution.AbstractContextDistributor#
+     * getContextAlbumMap(com.ericsson.apex.core.model.concepts.AxArtifactKey)
+     */
+    @Override
+    public Map<String, Object> getContextAlbumMap(final AxArtifactKey contextAlbumKey) {
+        LOGGER.info("InfinispanContextDistributor: create album: " + contextAlbumKey.getID());
+
+        // Get the Cache from Infinispan
+        final Cache<String, Object> infinispanCache =
+                infinispanManager.getCacheManager().getCache(contextAlbumKey.getID().replace(':', '_'));
+
+        return infinispanCache;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.ericsson.apex.core.context.impl.distribution.AbstractContextDistributor#shutdown()
+     */
+    @Override
+    public void shutdown() {
+        // Shut down the infinispan manager
+        if (infinispanManager != null) {
+            infinispanManager.shutdown();
+        }
+        infinispanManager = null;
+    }
+}
diff --git a/plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/java/org/onap/policy/apex/plugins/context/distribution/infinispan/InfinispanDistributorParameters.java b/plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/java/org/onap/policy/apex/plugins/context/distribution/infinispan/InfinispanDistributorParameters.java
new file mode 100644 (file)
index 0000000..d739552
--- /dev/null
@@ -0,0 +1,144 @@
+/*-
+ * ============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.plugins.context.distribution.infinispan;
+
+import org.onap.policy.apex.context.parameters.DistributorParameters;
+import org.onap.policy.apex.model.basicmodel.service.ParameterService;
+
+/**
+ * Distributor parameters for the Infinspan Distributor.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class InfinispanDistributorParameters extends DistributorParameters {
+    // @formatter:off
+
+    /** The default Infinispan configuration file location. */
+    public static final String  DEFAULT_INFINISPAN_DISTRIBUTION_CONFIG_FILE = "/infinispan/infinispan.xml";
+
+    /** The default Infinispan jgroups configuration file location. */
+    public static final String  DEFAULT_INFINISPAN_DISTRIBUTION_JGROUPS_FILE = null;
+
+    /** The default Infinispan IP stack is IPV4. */
+    public static final boolean DEFAULT_INFINISPAN_JAVA_NET_PREFER_IPV4_STACK = true;
+
+    /** The default Infinispan bind address is localhost. */
+    public static final String  DEFAULT_INFINSPAN_JGROUPS_BIND_ADDRESS = "localhost";
+
+    // Infinspan configuration file names
+    private String configFile         = DEFAULT_INFINISPAN_DISTRIBUTION_CONFIG_FILE;
+    private String jgroupsFile        = DEFAULT_INFINISPAN_DISTRIBUTION_JGROUPS_FILE;
+    private boolean preferIPv4Stack   = DEFAULT_INFINISPAN_JAVA_NET_PREFER_IPV4_STACK;
+    private String jGroupsBindAddress = DEFAULT_INFINSPAN_JGROUPS_BIND_ADDRESS;
+    // @formatter:on
+
+    /**
+     * The Constructor.
+     */
+    public InfinispanDistributorParameters() {
+        super(InfinispanDistributorParameters.class.getCanonicalName());
+        ParameterService.registerParameters(InfinispanDistributorParameters.class, this);
+        ParameterService.registerParameters(DistributorParameters.class, this);
+    }
+
+    /**
+     * Gets the config file.
+     *
+     * @return the config file
+     */
+    public String getConfigFile() {
+        return configFile;
+    }
+
+    /**
+     * Sets the config file.
+     *
+     * @param configFile the config file
+     */
+    public void setConfigFile(final String configFile) {
+        this.configFile = configFile;
+    }
+
+    /**
+     * Gets the jgroups file.
+     *
+     * @return the jgroups file
+     */
+    public String getJgroupsFile() {
+        return jgroupsFile;
+    }
+
+    /**
+     * Sets the jgroups file.
+     *
+     * @param jgroupsFile the jgroups file
+     */
+    public void setJgroupsFile(final String jgroupsFile) {
+        this.jgroupsFile = jgroupsFile;
+    }
+
+    /**
+     * Prefer I pv 4 stack.
+     *
+     * @return true, if prefer I pv 4 stack
+     */
+    public boolean preferIPv4Stack() {
+        return preferIPv4Stack;
+    }
+
+    /**
+     * Sets the prefer I pv 4 stack.
+     *
+     * @param preferIPv4Stack the prefer I pv 4 stack
+     */
+    public void setPreferIPv4Stack(final boolean preferIPv4Stack) {
+        this.preferIPv4Stack = preferIPv4Stack;
+    }
+
+    /**
+     * Getj groups bind address.
+     *
+     * @return the j groups bind address
+     */
+    public String getjGroupsBindAddress() {
+        return jGroupsBindAddress;
+    }
+
+    /**
+     * Setj groups bind address.
+     *
+     * @param jGroupsBindAddress the j groups bind address
+     */
+    public void setjGroupsBindAddress(final String jGroupsBindAddress) {
+        this.jGroupsBindAddress = jGroupsBindAddress;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.ericsson.apex.context.parameters.DistributorParameters#toString()
+     */
+    @Override
+    public String toString() {
+        return "InfinispanDistributorParameters [configFile=" + configFile + ", jgroupsFile=" + jgroupsFile
+                + ", preferIPv4Stack=" + preferIPv4Stack + ", jGroupsBindAddress=" + jGroupsBindAddress + "]";
+    }
+}
diff --git a/plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/java/org/onap/policy/apex/plugins/context/distribution/infinispan/InfinispanManager.java b/plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/java/org/onap/policy/apex/plugins/context/distribution/infinispan/InfinispanManager.java
new file mode 100644 (file)
index 0000000..803d99a
--- /dev/null
@@ -0,0 +1,196 @@
+/*-
+ * ============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.plugins.context.distribution.infinispan;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.model.utilities.ResourceUtils;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The Class InfinispanManager holds the Infinispan cache manager for a JVM.
+ */
+public class InfinispanManager {
+    // Logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(InfinispanManager.class);
+
+    // The Infinispan Cache Manager
+    private EmbeddedCacheManager cacheManager;
+
+    /**
+     * Constructor, set up an Infinispan cache manager.
+     *
+     * @param infinispanDistributorParameters the infinispan distributor parameters
+     * @throws ContextException On errors connecting to Infinispan
+     */
+    public InfinispanManager(final InfinispanDistributorParameters infinispanDistributorParameters)
+            throws ContextException {
+        LOGGER.entry("Creating Infinispan Manager: " + infinispanDistributorParameters);
+
+        setSystemProperties(infinispanDistributorParameters);
+
+        // First, try and open a local input stream for Infinispan configuration
+        InputStream infinispanConfigStream =
+                getLocalInfinispanConfigurationStream(infinispanDistributorParameters.getConfigFile());
+
+        // Check if a local file was found, if not then go to the class path
+        if (infinispanConfigStream == null) {
+            // If a local file is not specified, then check for an infinispan configuration file on
+            // the class path
+            infinispanConfigStream =
+                    getClasspathInfinispanConfigurationStream(infinispanDistributorParameters.getConfigFile());
+        }
+
+        // Check if we found configuration for Infinispan
+        if (infinispanConfigStream == null) {
+            final String errorMessage =
+                    "failed to start infinispan cache manager, no infinispan configuration found on local file system or in classpath, "
+                            + "try setting Infinspan \"configFile\" parameter";
+            LOGGER.error(errorMessage);
+            throw new ContextException(errorMessage);
+        }
+
+        try {
+            LOGGER.debug("starting infinispan cache manager using specified configuration . . .");
+            cacheManager = new DefaultCacheManager(infinispanConfigStream);
+            LOGGER.debug("started infinispan cache manager using specified configuration");
+        } catch (final Exception e) {
+            LOGGER.error("failed to start infinispan cache manager using specified configuration", e);
+            throw new ContextException("failed to start infinispan cache manager using specified configuration", e);
+        }
+
+        // Start the cache manager
+        cacheManager.start();
+
+        Runtime.getRuntime().addShutdownHook(new InfinspanManagerShutdownHook());
+
+        LOGGER.exit("Created Infinispan Manager: " + infinispanDistributorParameters);
+    }
+
+    /**
+     * Shutdown the manager.
+     */
+    public void shutdown() {
+        if (cacheManager == null) {
+            return;
+        }
+
+        cacheManager.stop();
+        cacheManager = null;
+    }
+
+    /**
+     * Get the cache manager.
+     *
+     * @return the infinispan cache manager
+     */
+    public EmbeddedCacheManager getCacheManager() {
+        return cacheManager;
+    }
+
+    /**
+     * Set system properties used by Infinispan.
+     *
+     * @param infinispanDistributorParameters The parameter values to set are passed as properties
+     */
+    private void setSystemProperties(final InfinispanDistributorParameters infinispanDistributorParameters) {
+        System.setProperty("java.net.preferIPv4Stack",
+                Boolean.toString(infinispanDistributorParameters.preferIPv4Stack()));
+        System.setProperty("jgroups.bind_addr", infinispanDistributorParameters.getjGroupsBindAddress());
+    }
+
+    /**
+     * Get an Infinispan configuration stream from the local file system.
+     *
+     * @param infinispanConfigFileName The file name to open
+     * @return The file opened as a stream
+     * @throws ContextException If the local file could not be found or is invalid
+     */
+    private InputStream getLocalInfinispanConfigurationStream(final String infinispanConfigFileName)
+            throws ContextException {
+        LOGGER.debug("checking infinispan configuration file exists at \"" + infinispanConfigFileName + "\". . .");
+
+        // Check if the file exists
+        final File infinispanConfigFile = new File(infinispanConfigFileName);
+        if (!infinispanConfigFile.exists()) {
+            return null;
+        }
+
+        // Check the file
+        if (!infinispanConfigFile.isFile() || !infinispanConfigFile.canRead()) {
+            LOGGER.error("infinispan configuration file at \"" + infinispanConfigFileName
+                    + "\" does not exist or is invalid");
+            throw new ContextException("infinispan configuration file at \"" + infinispanConfigFileName
+                    + "\" does not exist or is invalid");
+        }
+
+        try {
+            final InputStream infinispanConfigStream = new FileInputStream(infinispanConfigFile);
+            LOGGER.debug("infinispan configuration file exists at \"" + infinispanConfigFileName + "\"");
+            return infinispanConfigStream;
+        } catch (final Exception e) {
+            LOGGER.error("infinispan configuration file at \"" + infinispanConfigFileName
+                    + "\" does not exist or is invalid", e);
+            throw new ContextException("infinispan configuration file at \"" + infinispanConfigFileName
+                    + "\" does not exist or is invalid", e);
+        }
+    }
+
+    /**
+     * Get an Infinispan configuration stream from the class path.
+     *
+     * @param apexInfinispanConfigFile the apex infinispan config file
+     * @return The file opened as a stream
+     */
+    private InputStream getClasspathInfinispanConfigurationStream(final String apexInfinispanConfigFile) {
+        LOGGER.debug(
+                "checking infinispan configuration file exists at resource \"" + apexInfinispanConfigFile + "\". . .");
+        final InputStream infinispanConfigStream = ResourceUtils.getResourceAsStream(apexInfinispanConfigFile);
+
+        if (infinispanConfigStream != null) {
+            LOGGER.debug("infinispan configuration file exists at resource \"" + apexInfinispanConfigFile + "\"");
+        } else {
+            LOGGER.debug("infinispan configuration file at resource \"" + apexInfinispanConfigFile + "\" not found");
+        }
+        return infinispanConfigStream;
+    }
+
+    /**
+     * Private class to implement the shutdown hook for this infinispan manager.
+     */
+    public class InfinspanManagerShutdownHook extends Thread {
+        /*
+         * (non-Javadoc)
+         *
+         * @see java.lang.Thread#run()
+         */
+        @Override
+        public void run() {
+            shutdown();
+        }
+    }
+}
diff --git a/plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/java/org/onap/policy/apex/plugins/context/distribution/infinispan/package-info.java b/plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/java/org/onap/policy/apex/plugins/context/distribution/infinispan/package-info.java
new file mode 100644 (file)
index 0000000..b9ceeb6
--- /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 <a href="http://infinispan.org/">Infinispan</a> context distributor for
+ * distribution of APEX context across JVMs.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.plugins.context.distribution.infinispan;
diff --git a/plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/resources/infinispan/infinispan.xml.sample b/plugins/plugins-context/context-distribution/context-distribution-infinispan/src/main/resources/infinispan/infinispan.xml.sample
new file mode 100644 (file)
index 0000000..302eac9
--- /dev/null
@@ -0,0 +1,40 @@
+<?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=========================================================
+-->
+
+<infinispan xmlns="urn:infinispan:config:8.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:infinispan:config:8.0 http://infinispan.org/schemas/infinispan-config-8.0.xsd">
+       <jgroups>
+               <stack-file name="tcpStack" path="default-configs/default-jgroups-tcp.xml" />
+       </jgroups>
+
+       <cache-container name="ApexCacheContainer" default-cache="TestContext_0.0.1">
+               <transport cluster="apexCluster" stack="tcpStack" />
+               <jmx />
+               <replicated-cache name="LargeContextMap_0.0.1" mode="SYNC" statistics="true">
+                       <state-transfer enabled="true" />
+               </replicated-cache>
+               <replicated-cache name="LongSameTypeContextMap_0.0.1" mode="SYNC" statistics="true">
+                       <state-transfer enabled="true" />
+               </replicated-cache>
+               <replicated-cache name="TestContext_0.0.1" mode="SYNC">
+                       <state-transfer enabled="true" />
+               </replicated-cache>
+       </cache-container>
+</infinispan>
diff --git a/plugins/plugins-context/context-distribution/pom.xml b/plugins/plugins-context/context-distribution/pom.xml
new file mode 100644 (file)
index 0000000..94e7691
--- /dev/null
@@ -0,0 +1,41 @@
+<!--
+  ============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.plugins.plugins-context</groupId>
+        <artifactId>plugins-context</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-distribution</groupId>
+    <artifactId>context-distribution</artifactId>
+    <packaging>pom</packaging>
+
+    <name>${project.artifactId}</name>
+    <description>Plugins for 3pps that distribute context</description>
+
+    <modules>
+        <module>context-distribution-hazelcast</module>
+        <module>context-distribution-infinispan</module>
+    </modules>
+</project>
\ No newline at end of file
diff --git a/plugins/plugins-context/context-locking/context-locking-curator/pom.xml b/plugins/plugins-context/context-locking/context-locking-curator/pom.xml
new file mode 100644 (file)
index 0000000..d5d50e1
--- /dev/null
@@ -0,0 +1,45 @@
+<!--
+  ============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.plugins.plugins-context.context-locking</groupId>
+        <artifactId>context-locking</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>context-locking-curator</artifactId>
+    <name>${project.artifactId}</name>
+    <description>[${project.parent.artifactId}] Plugin for locking using Curator</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-framework</artifactId>
+            <version>4.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-recipes</artifactId>
+            <version>4.0.0</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/CuratorLockFacade.java b/plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/CuratorLockFacade.java
new file mode 100644 (file)
index 0000000..9282550
--- /dev/null
@@ -0,0 +1,137 @@
+/*-
+ * ============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.plugins.context.locking.curator;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+
+import org.apache.curator.framework.recipes.locks.InterProcessMutex;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This class provides a facade over the {@link Lock} interface for Curator locks.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class CuratorLockFacade implements Lock {
+    // Logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(CuratorLockFacade.class);
+
+    // The Lock ID
+    private final String lockId;
+
+    // The mutex used for Curator locking
+    private final InterProcessMutex lockMutex;
+
+    /**
+     * Create the lock Facade.
+     *
+     * @param lockMutex The lock mutex behind the facade
+     * @param lockId The ID of the lock
+     */
+    public CuratorLockFacade(final InterProcessMutex lockMutex, final String lockId) {
+        this.lockId = lockId;
+        this.lockMutex = lockMutex;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.concurrent.locks.Lock#lock()
+     */
+    @Override
+    public void lock() {
+        try {
+            lockMutex.acquire();
+        } catch (final Exception e) {
+            LOGGER.warn("failed to acquire lock for \"" + lockId, e);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.concurrent.locks.Lock#lockInterruptibly()
+     */
+    @Override
+    public void lockInterruptibly() throws InterruptedException {
+        LOGGER.warn("lockInterruptibly() not supported for \"" + lockId);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.concurrent.locks.Lock#tryLock()
+     */
+    @Override
+    public boolean tryLock() {
+        try {
+            lockMutex.acquire();
+            return true;
+        } catch (final Exception e) {
+            LOGGER.warn("failed to acquire lock for \"" + lockId, e);
+            return false;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.concurrent.locks.Lock#tryLock(long, java.util.concurrent.TimeUnit)
+     */
+    @Override
+    public boolean tryLock(final long time, final TimeUnit unit) throws InterruptedException {
+        try {
+            lockMutex.acquire(time, unit);
+            return true;
+        } catch (final Exception e) {
+            LOGGER.warn("failed to acquire lock for \"" + lockId, e);
+            return false;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.concurrent.locks.Lock#unlock()
+     */
+    @Override
+    public void unlock() {
+        try {
+            lockMutex.release();
+        } catch (final Exception e) {
+            LOGGER.warn("failed to release lock for \"" + lockId, e);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.concurrent.locks.Lock#newCondition()
+     */
+    @Override
+    public Condition newCondition() {
+        LOGGER.warn("newCondition() not supported for \"" + lockId);
+        return null;
+    }
+}
diff --git a/plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/CuratorLockManager.java b/plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/CuratorLockManager.java
new file mode 100644 (file)
index 0000000..d0cc842
--- /dev/null
@@ -0,0 +1,185 @@
+/*-
+ * ============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.plugins.context.locking.curator;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReadWriteLock;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.state.ConnectionState;
+import org.apache.curator.framework.state.ConnectionStateListener;
+import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.apache.curator.utils.CloseableUtils;
+import org.apache.zookeeper.CreateMode;
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.context.impl.locking.AbstractLockManager;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.service.ParameterService;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The Class CuratorLockManager manages the Curator interface towards Zookeeper for administering
+ * the Apex Context Album instance locks..
+ */
+public class CuratorLockManager extends AbstractLockManager {
+    // Logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(CuratorLockManager.class);
+
+    // The Curator framework used for locking
+    private CuratorFramework curatorFramework;
+
+    // The address of the Zookeeper server
+    private String curatorZookeeperAddress;
+
+    /**
+     * Constructor, set up a lock manager that uses Curator locking.
+     *
+     * @throws ContextException On errors connecting to Curator
+     */
+    public CuratorLockManager() throws ContextException {
+        LOGGER.entry("CuratorLockManager(): setting up the Curator lock manager . . .");
+
+        LOGGER.exit("CuratorLockManager(): Curator lock manager set up");
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.context.impl.locking.AbstractLockManager#init(org.onap.policy.apex.
+     * model. basicmodel.concepts.AxArtifactKey)
+     */
+    @Override
+    public void init(final AxArtifactKey key) throws ContextException {
+        LOGGER.entry("init(" + key + ")");
+
+        super.init(key);
+
+        // Get the lock manager parameters
+        final CuratorLockManagerParameters lockParameters =
+                ParameterService.getParameters(CuratorLockManagerParameters.class);
+
+        // Check if the curator address has been set
+        curatorZookeeperAddress = lockParameters.getZookeeperAddress();
+        if (curatorZookeeperAddress == null || curatorZookeeperAddress.trim().length() == 0) {
+            LOGGER.warn(
+                    "could not set up Curator locking, check if the curator Zookeeper address parameter is set correctly");
+            throw new ContextException(
+                    "could not set up Curator locking, check if the curator Zookeeper address parameter is set correctly");
+        }
+
+        // Set up the curator framework we'll use
+        curatorFramework = CuratorFrameworkFactory.builder().connectString(curatorZookeeperAddress)
+                .retryPolicy(new ExponentialBackoffRetry(lockParameters.getZookeeperConnectSleepTime(),
+                        lockParameters.getZookeeperContextRetries()))
+                .build();
+
+        // Listen for changes on the Curator connection
+        curatorFramework.getConnectionStateListenable().addListener(new CuratorManagerConnectionStateListener());
+
+        // Start the framework and specify Ephemeral nodes
+        curatorFramework.start();
+
+        // Wait for the connection to be made
+        try {
+            curatorFramework.blockUntilConnected(
+                    lockParameters.getZookeeperConnectSleepTime() * lockParameters.getZookeeperContextRetries(),
+                    TimeUnit.MILLISECONDS);
+        } catch (final InterruptedException e) {
+            LOGGER.warn("could not connect to Zookeeper server at \"" + curatorZookeeperAddress
+                    + "\", wait for connection timed out");
+            throw new ContextException("could not connect to Zookeeper server at \"" + curatorZookeeperAddress
+                    + "\", wait for connection timed out");
+        }
+
+        if (!curatorFramework.getZookeeperClient().isConnected()) {
+            LOGGER.warn("could not connect to Zookeeper server at \"" + curatorZookeeperAddress
+                    + "\", see error log for details");
+            throw new ContextException("could not connect to Zookeeper server at \"" + curatorZookeeperAddress
+                    + "\", see error log for details");
+        }
+
+        // We'll use Ephemeral nodes for locks on the Zookeeper server
+        curatorFramework.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL);
+
+        LOGGER.exit("init(" + key + "," + lockParameters + ")");
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.core.context.impl.locking.AbstractLockManager#getReentrantReadWriteLock(
+     * java.lang.String)
+     */
+    @Override
+    public ReadWriteLock getReentrantReadWriteLock(final String lockId) throws ContextException {
+        // Check if the framework is active
+        if (curatorFramework != null && curatorFramework.getZookeeperClient().isConnected()) {
+            return new CuratorReentrantReadWriteLock(curatorFramework, "/" + lockId);
+        } else {
+            throw new ContextException("creation of lock using Zookeeper server at \"" + curatorZookeeperAddress
+                    + "\", failed, see error log for details");
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.core.context.LockManager#shutdown()
+     */
+    @Override
+    public void shutdown() {
+        if (curatorFramework == null) {
+            return;
+        }
+        CloseableUtils.closeQuietly(curatorFramework);
+        curatorFramework = null;
+    }
+
+    /**
+     * This class is a callback class for state changes on the curator to Zookeeper connection.
+     */
+    private class CuratorManagerConnectionStateListener implements ConnectionStateListener {
+
+        /*
+         * (non-Javadoc)
+         *
+         * @see org.apache.curator.framework.state.ConnectionStateListener#stateChanged(org.apache.
+         * curator.framework.CuratorFramework, org.apache.curator.framework.state.ConnectionState)
+         */
+        @Override
+        public void stateChanged(final CuratorFramework incomngCuratorFramework, final ConnectionState newState) {
+            // Is the state changed for this curator framework?
+            if (!incomngCuratorFramework.equals(curatorFramework)) {
+                return;
+            }
+
+            LOGGER.info("curator state of client \"" + curatorFramework + "\" connected to \"" + curatorZookeeperAddress
+                    + "\" changed to " + newState);
+
+            if (newState != ConnectionState.CONNECTED) {
+                shutdown();
+            }
+        }
+    }
+}
diff --git a/plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/CuratorLockManagerParameters.java b/plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/CuratorLockManagerParameters.java
new file mode 100644 (file)
index 0000000..9e8d5d2
--- /dev/null
@@ -0,0 +1,120 @@
+/*-
+ * ============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.plugins.context.locking.curator;
+
+import org.onap.policy.apex.context.parameters.LockManagerParameters;
+import org.onap.policy.apex.model.basicmodel.service.ParameterService;
+
+/**
+ * Bean class for Curator locking parameters.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class CuratorLockManagerParameters extends LockManagerParameters {
+    // @formatter:off
+    /** The default address used to connect to the Zookeeper server. */
+    public static final String DEFAULT_ZOOKEEPER_ADDRESS            = "localhost:2181";
+
+    /** The default sleep time to use when connecting to the Zookeeper server. */
+    public static final int DEFAULT_ZOOKEEPER_CONNECT_SLEEP_TIME = 1000;
+
+    /** The default number of times to retry failed connections to the Zookeeper server. */
+    public static final int DEFAULT_ZOOKEEPER_CONNECT_RETRIES = 3;
+
+    // Curator parameters
+    private String zookeeperAddress       = DEFAULT_ZOOKEEPER_ADDRESS;
+    private int zookeeperConnectSleepTime = DEFAULT_ZOOKEEPER_CONNECT_SLEEP_TIME;
+    private int zookeeperContextRetries   = DEFAULT_ZOOKEEPER_CONNECT_RETRIES;
+    // @formatter:on
+
+    /**
+     * The Constructor.
+     */
+    public CuratorLockManagerParameters() {
+        super(CuratorLockManagerParameters.class.getCanonicalName());
+        ParameterService.registerParameters(CuratorLockManagerParameters.class, this);
+    }
+
+    /**
+     * Gets the zookeeper address.
+     *
+     * @return the zookeeper address
+     */
+    public String getZookeeperAddress() {
+        return zookeeperAddress;
+    }
+
+    /**
+     * Sets the zookeeper address.
+     *
+     * @param zookeeperAddress the zookeeper address
+     */
+    public void setZookeeperAddress(final String zookeeperAddress) {
+        this.zookeeperAddress = zookeeperAddress;
+    }
+
+    /**
+     * Gets the zookeeper connect sleep time.
+     *
+     * @return the zookeeper connect sleep time
+     */
+    public int getZookeeperConnectSleepTime() {
+        return zookeeperConnectSleepTime;
+    }
+
+    /**
+     * Sets the zookeeper connect sleep time.
+     *
+     * @param zookeeperConnectSleepTime the zookeeper connect sleep time
+     */
+    public void setZookeeperConnectSleepTime(final int zookeeperConnectSleepTime) {
+        this.zookeeperConnectSleepTime = zookeeperConnectSleepTime;
+    }
+
+    /**
+     * Gets the zookeeper context retries.
+     *
+     * @return the zookeeper context retries
+     */
+    public int getZookeeperContextRetries() {
+        return zookeeperContextRetries;
+    }
+
+    /**
+     * Sets the zookeeper context retries.
+     *
+     * @param zookeeperContextRetries the zookeeper context retries
+     */
+    public void setZookeeperContextRetries(final int zookeeperContextRetries) {
+        this.zookeeperContextRetries = zookeeperContextRetries;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.context.parameters.LockManagerParameters#toString()
+     */
+    @Override
+    public String toString() {
+        return "CuratorLockManagerParameters [zookeeperAddress=" + zookeeperAddress + ", zookeeperConnectSleepTime="
+                + zookeeperConnectSleepTime + ", zookeeperContextRetries=" + zookeeperContextRetries + "]";
+    }
+}
diff --git a/plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/CuratorReentrantReadWriteLock.java b/plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/CuratorReentrantReadWriteLock.java
new file mode 100644 (file)
index 0000000..22bf5e5
--- /dev/null
@@ -0,0 +1,90 @@
+/*-
+ * ============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.plugins.context.locking.curator;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;
+
+/**
+ * This class maps a Curator {@link InterProcessReadWriteLock} to a Java {@link ReadWriteLock}.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class CuratorReentrantReadWriteLock implements ReadWriteLock {
+    // The Lock ID
+    private final String lockID;
+
+    // The Curator lock
+    private final InterProcessReadWriteLock curatorReadWriteLock;
+
+    // The Curator Lock facades for read and write locks
+    private final CuratorLockFacade readLockFacade;
+    private final CuratorLockFacade writeLockFacade;
+
+    /**
+     * Create a Curator lock.
+     *
+     * @param curatorFramework the Curator framework to use to create the lock
+     * @param lockId The unique ID of the lock.
+     */
+    public CuratorReentrantReadWriteLock(final CuratorFramework curatorFramework, final String lockId) {
+        lockID = lockId;
+
+        // Create the Curator lock
+        curatorReadWriteLock = new InterProcessReadWriteLock(curatorFramework, lockId);
+
+        // Create the lock facades
+        readLockFacade = new CuratorLockFacade(curatorReadWriteLock.readLock(), lockId);
+        writeLockFacade = new CuratorLockFacade(curatorReadWriteLock.writeLock(), lockId);
+    }
+
+    /**
+     * Get the lock Id of the lock.
+     *
+     * @return the lock ID
+     */
+    public String getLockID() {
+        return lockID;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.concurrent.locks.ReadWriteLock#readLock()
+     */
+    @Override
+    public Lock readLock() {
+        return readLockFacade;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.concurrent.locks.ReadWriteLock#writeLock()
+     */
+    @Override
+    public Lock writeLock() {
+        return writeLockFacade;
+    }
+}
diff --git a/plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/package-info.java b/plugins/plugins-context/context-locking/context-locking-curator/src/main/java/org/onap/policy/apex/plugins/context/locking/curator/package-info.java
new file mode 100644 (file)
index 0000000..d867c39
--- /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 locking on context items in APEX context albums using
+ * <a href="http://curator.apache.org/">Curator</a> centralized locking.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.plugins.context.locking.curator;
diff --git a/plugins/plugins-context/context-locking/context-locking-hazelcast/pom.xml b/plugins/plugins-context/context-locking/context-locking-hazelcast/pom.xml
new file mode 100644 (file)
index 0000000..3e581ec
--- /dev/null
@@ -0,0 +1,59 @@
+<!--
+  ============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.plugins.plugins-context.context-locking</groupId>
+        <artifactId>context-locking</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>context-locking-hazelcast</artifactId>
+    <name>${project.artifactId}</name>
+    <description>[${project.parent.artifactId}] Plugin for locking using Hazelcast</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.hazelcast</groupId>
+            <artifactId>hazelcast</artifactId>
+            <version>${version.hazelcast}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.core</groupId>
+            <artifactId>core-infrastructure</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-distribution</groupId>
+            <artifactId>context-distribution-hazelcast</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-distribution</groupId>
+            <artifactId>context-distribution-infinispan</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/plugins/plugins-context/context-locking/context-locking-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/locking/hazelcast/HazelcastLock.java b/plugins/plugins-context/context-locking/context-locking-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/locking/hazelcast/HazelcastLock.java
new file mode 100644 (file)
index 0000000..73678ad
--- /dev/null
@@ -0,0 +1,84 @@
+/*-
+ * ============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.plugins.context.locking.hazelcast;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+
+import com.hazelcast.core.HazelcastInstance;
+import com.hazelcast.core.ILock;
+
+/**
+ * This class maps a Hazelcast {@link ILock} to a Java {@link ReadWriteLock}.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class HazelcastLock implements ReadWriteLock {
+    // The Lock ID
+    private final String lockID;
+
+    // The hazelcast lock
+    private final ILock readLock;
+    private final ILock writeLock;
+
+    /**
+     * Create a Hazelcast lock.
+     *
+     * @param hazelcastInstance the hazelcast instance to use to create the lock
+     * @param lockId The unique ID of the lock.
+     */
+    public HazelcastLock(final HazelcastInstance hazelcastInstance, final String lockId) {
+        lockID = lockId;
+
+        // Create the Hazelcast read and write locks
+        readLock = hazelcastInstance.getLock(lockId + "_READ");
+        writeLock = hazelcastInstance.getLock(lockId + "_WRITE");
+    }
+
+    /**
+     * Get the lock Id of the lock.
+     *
+     * @return the lock ID
+     */
+    public String getLockID() {
+        return lockID;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.concurrent.locks.ReadWriteLock#readLock()
+     */
+    @Override
+    public Lock readLock() {
+        return readLock;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.util.concurrent.locks.ReadWriteLock#writeLock()
+     */
+    @Override
+    public Lock writeLock() {
+        return writeLock;
+    }
+}
diff --git a/plugins/plugins-context/context-locking/context-locking-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/locking/hazelcast/HazelcastLockManager.java b/plugins/plugins-context/context-locking/context-locking-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/locking/hazelcast/HazelcastLockManager.java
new file mode 100644 (file)
index 0000000..34258bf
--- /dev/null
@@ -0,0 +1,104 @@
+/*-
+ * ============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.plugins.context.locking.hazelcast;
+
+import java.util.concurrent.locks.ReadWriteLock;
+
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.context.impl.locking.AbstractLockManager;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import com.hazelcast.core.Hazelcast;
+import com.hazelcast.core.HazelcastInstance;
+
+/**
+ * The Class HazelcastLockManager manages Hazelcast locks for locks on items in Apex context albums.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class HazelcastLockManager extends AbstractLockManager {
+    // Logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(HazelcastLockManager.class);
+
+    private HazelcastInstance hazelcastInstance;
+
+    /**
+     * Constructor, set up a lock manager that uses Hazelcast locking.
+     *
+     * @throws ContextException On errors connecting to the Hazelcast cluster
+     */
+    public HazelcastLockManager() throws ContextException {
+        LOGGER.entry("HazelcastLockManager(): setting up the Hazelcast lock manager . . .");
+
+        LOGGER.exit("HazelcastLockManager(): Hazelcast lock manager set up");
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.context.impl.locking.AbstractLockManager#init(org.onap.policy.apex.
+     * model. basicmodel.concepts.AxArtifactKey)
+     */
+    @Override
+    public void init(final AxArtifactKey key) throws ContextException {
+        LOGGER.entry("init(" + key + ")");
+
+        super.init(key);
+
+        // Set up the Hazelcast instance for lock handling
+        hazelcastInstance = Hazelcast.newHazelcastInstance();
+
+        LOGGER.exit("init(" + key + ")");
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.core.context.impl.locking.AbstractLockManager#getReentrantReadWriteLock(
+     * java.lang.String)
+     */
+    @Override
+    public ReadWriteLock getReentrantReadWriteLock(final String lockId) throws ContextException {
+        // Check if the framework is active
+        if (hazelcastInstance != null && hazelcastInstance.getLifecycleService().isRunning()) {
+            return new HazelcastLock(hazelcastInstance, lockId);
+        } else {
+            throw new ContextException("creation of hazelcast lock failed, see error log for details");
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.core.context.LockManager#shutdown()
+     */
+    @Override
+    public void shutdown() {
+        if (hazelcastInstance == null) {
+            return;
+        }
+        hazelcastInstance.shutdown();
+        hazelcastInstance = null;
+    }
+}
diff --git a/plugins/plugins-context/context-locking/context-locking-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/locking/hazelcast/package-info.java b/plugins/plugins-context/context-locking/context-locking-hazelcast/src/main/java/org/onap/policy/apex/plugins/context/locking/hazelcast/package-info.java
new file mode 100644 (file)
index 0000000..8d35556
--- /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 locking on context items in APEX context albums using
+ * <a href="http://hazelcast.org/">Hazelcast</a> distributed locking.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.plugins.context.locking.hazelcast;
diff --git a/plugins/plugins-context/context-locking/pom.xml b/plugins/plugins-context/context-locking/pom.xml
new file mode 100644 (file)
index 0000000..a25eb92
--- /dev/null
@@ -0,0 +1,39 @@
+<!--
+  ============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.plugins.plugins-context</groupId>
+        <artifactId>plugins-context</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-locking</groupId>
+    <artifactId>context-locking</artifactId>
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+
+    <description>Plugins for 3pps that lock context</description>
+    <modules>
+        <module>context-locking-curator</module>
+        <module>context-locking-hazelcast</module>
+    </modules>
+</project>
\ No newline at end of file
diff --git a/plugins/plugins-context/context-metrics/pom.xml b/plugins/plugins-context/context-metrics/pom.xml
new file mode 100644 (file)
index 0000000..1e5800c
--- /dev/null
@@ -0,0 +1,72 @@
+<!--
+  ============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.plugins.plugins-context</groupId>
+        <artifactId>plugins-context</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>context-metrics</artifactId>
+    <name>${project.artifactId}</name>
+    <description>[${project.parent.artifactId}] module to calculate metrics using various plugins</description>
+
+
+    <dependencies>
+        <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.context</groupId>
+            <artifactId>context-test</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-distribution</groupId>
+            <artifactId>context-distribution-hazelcast</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-distribution</groupId>
+            <artifactId>context-distribution-infinispan</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-locking</groupId>
+            <artifactId>context-locking-curator</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-locking</groupId>
+            <artifactId>context-locking-hazelcast</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-test</artifactId>
+            <version>3.2.0</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/ConcurrentContextMetrics.java b/plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/ConcurrentContextMetrics.java
new file mode 100644 (file)
index 0000000..de719c9
--- /dev/null
@@ -0,0 +1,525 @@
+/*-
+ * ============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.plugins.context.metrics;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.onap.policy.apex.context.ContextAlbum;
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.context.Distributor;
+import org.onap.policy.apex.context.impl.distribution.DistributorFactory;
+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.test.concepts.TestContextItem003;
+import org.onap.policy.apex.context.test.factory.TestContextAlbumFactory;
+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.contextmodel.concepts.AxContextModel;
+import org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanDistributorParameters;
+import org.onap.policy.apex.plugins.context.locking.curator.CuratorLockManagerParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The Class concurrentContextMetrics tests concurrent use of context.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ConcurrentContextMetrics {
+    private static final int NUM_ARGS = 8;
+    private static final int ARG_LABEL = 0;
+    private static final int ARG_JVM_COUNT = 1;
+    private static final int ARG_THREAD_COUNT = 2;
+    private static final int ARG_ITERATIONS = 3;
+    private static final int ARG_ARRAY_SIZE = 4;
+    private static final int ARG_LOCK_TYPE = 5;
+    private static final int ARG_ZOOKEEPER_ADDRESS = 6;
+    private static final int ARG_INTERACTIVE = 7;
+
+    private static final int TIME_10_MS = 10;
+
+    // Logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ConcurrentContextMetrics.class);
+
+    // Test parameters
+    private String testLabel = null;
+    private int jvmCount = -1;
+    private int threadCount = -1;
+    private int threadLoops = -1;
+    private int longArraySize = -1;
+    private int lockType = -1;
+    private String zookeeperAddress = null;
+    private long total = -1;
+    private boolean interactive = false;
+
+    // The context distributor and map used by each test
+    private Distributor contextDistributor = null;
+    private ContextAlbum lTypeAlbum = null;
+
+    private final DateFormat dateFormat = new SimpleDateFormat("yyyy,MM,dd,HH,mm,ss,S");
+
+    /**
+     * The main method.
+     *
+     * @param args the args
+     * @throws ApexModelException the apex model exception
+     * @throws IOException the IO exception
+     * @throws ApexException the apex exception
+     */
+    public static void main(final String[] args) throws ApexModelException, IOException, ApexException {
+        if (args.length != NUM_ARGS) {
+            System.err.println(
+                    "usage: ConcurrentContextMetrics testLabel jvmCount threadCount threadLoops longArraySize lockType zookeeperAddress interactive");
+            return;
+        }
+        // @formatter:off
+        final ConcurrentContextMetrics concurrentContextMetrics = new ConcurrentContextMetrics(
+                args[ARG_LABEL],
+                Integer.valueOf(args[ARG_JVM_COUNT]),
+                Integer.valueOf(args[ARG_THREAD_COUNT]),
+                Integer.valueOf(args[ARG_ITERATIONS]),
+                Integer.valueOf(args[ARG_ARRAY_SIZE]),
+                Integer.valueOf(args[ARG_LOCK_TYPE]),
+                args[ARG_ZOOKEEPER_ADDRESS],
+                Boolean.valueOf(args[ARG_INTERACTIVE]));
+        // @formatter:on
+
+        concurrentContextMetrics.concurrentContextMetricsJVMLocal();
+        concurrentContextMetrics.concurrentContextMetricsCurator();
+        concurrentContextMetrics.concurrentContextMetricsHazelcast();
+        concurrentContextMetrics.concurrentContextMetricsHazelcastMultiJVMHazelcastLock();
+        concurrentContextMetrics.concurrentContextMetricsInfinispanMultiJVMHazelcastlock();
+        concurrentContextMetrics.concurrentContextMetricsInfinispanMultiJVMCuratorLock();
+        concurrentContextMetrics.concurrentContextMetricsHazelcastMultiJVMCuratorLock();
+    }
+
+    /**
+     * The Constructor.
+     *
+     * @param testLabel the test label
+     * @param jvmCount the jvm count
+     * @param threadCount the thread count
+     * @param threadLoops the thread loops
+     * @param longArraySize the long array size
+     * @param lockType the lock type
+     * @param zookeeperAddress the zookeeper address
+     * @param interactive the interactive
+     */
+    // CHECKSTYLE:OFF: checkstyle:parameterNumber
+    public ConcurrentContextMetrics(final String testLabel, final int jvmCount, final int threadCount,
+            final int threadLoops, final int longArraySize, final int lockType, final String zookeeperAddress,
+            final boolean interactive) {
+        // CHECKSTYLE:ON: checkstyle:parameterNumber
+        super();
+        this.testLabel = testLabel;
+        this.jvmCount = jvmCount;
+        this.threadCount = threadCount;
+        this.threadLoops = threadLoops;
+        this.longArraySize = longArraySize;
+        this.lockType = lockType;
+        this.zookeeperAddress = zookeeperAddress;
+        this.interactive = interactive;
+    }
+
+    /**
+     * Concurrent context metrics JVM local.
+     *
+     * @throws ApexModelException the apex model exception
+     * @throws IOException the IO exception
+     * @throws ApexException the apex exception
+     */
+    private void concurrentContextMetricsJVMLocal() throws ApexModelException, IOException, ApexException {
+        if (jvmCount != 1) {
+            return;
+        }
+
+        LOGGER.debug("Running concurrentContextMetricsJVMLocalVarSet metrics . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters()
+                .setPluginClass(DistributorParameters.DEFAULT_DISTRIBUTOR_PLUGIN_CLASS);
+        contextParameters.getLockManagerParameters()
+                .setPluginClass(LockManagerParameters.DEFAULT_LOCK_MANAGER_PLUGIN_CLASS);
+        runConcurrentContextMetrics("JVMLocal");
+
+        LOGGER.debug("Ran concurrentContextMetricsJVMLocalVarSet metrics");
+    }
+
+    /**
+     * Concurrent context metrics hazelcast.
+     *
+     * @throws ApexModelException the apex model exception
+     * @throws IOException the IO exception
+     * @throws ApexException the apex exception
+     */
+    private void concurrentContextMetricsHazelcast() throws ApexModelException, IOException, ApexException {
+        if (jvmCount != 1) {
+            return;
+        }
+
+        LOGGER.debug("Running concurrentContextMetricsHazelcast metrics . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters()
+                .setPluginClass(DistributorParameters.DEFAULT_DISTRIBUTOR_PLUGIN_CLASS);
+        contextParameters.getLockManagerParameters()
+                .setPluginClass("org.onap.policy.apex.plugins.context.locking.hazelcast.HazelcastLockManager");
+        runConcurrentContextMetrics("Hazelcast");
+
+        LOGGER.debug("Ran concurrentContextMetricsHazelcast metrics");
+    }
+
+    /**
+     * Concurrent context metrics curator.
+     *
+     * @throws ApexModelException the apex model exception
+     * @throws IOException the IO exception
+     * @throws ApexException the apex exception
+     */
+    private void concurrentContextMetricsCurator() throws ApexModelException, IOException, ApexException {
+        if (jvmCount != 1) {
+            return;
+        }
+
+        LOGGER.debug("Running concurrentContextMetricsCurator metrics . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters()
+                .setPluginClass(DistributorParameters.DEFAULT_DISTRIBUTOR_PLUGIN_CLASS);
+
+        final CuratorLockManagerParameters curatorParameters = new CuratorLockManagerParameters();
+        curatorParameters.setPluginClass("org.onap.policy.apex.plugins.context.locking.curator.CuratorLockManager");
+        contextParameters.setLockManagerParameters(curatorParameters);
+        curatorParameters.setZookeeperAddress(zookeeperAddress);
+
+        runConcurrentContextMetrics("Curator");
+
+        LOGGER.debug("Ran concurrentContextMetricsCurator metrics");
+    }
+
+    /**
+     * Concurrent context metrics hazelcast multi JVM hazelcast lock.
+     *
+     * @throws ApexModelException the apex model exception
+     * @throws IOException the IO exception
+     * @throws ApexException the apex exception
+     */
+    private void concurrentContextMetricsHazelcastMultiJVMHazelcastLock()
+            throws ApexModelException, IOException, ApexException {
+        LOGGER.debug("Running concurrentContextMetricsHazelcastMultiJVMHazelcastLock metrics . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.hazelcast.HazelcastContextDistributor");
+        contextParameters.getLockManagerParameters()
+                .setPluginClass("org.onap.policy.apex.plugins.context.locking.hazelcast.HazelcastLockManager");
+        runConcurrentContextMetrics("HazelcastMultiJVMHazelcastLock");
+
+        LOGGER.debug("Ran concurrentContextMetricsHazelcastMultiJVMHazelcastLock metrics");
+    }
+
+    /**
+     * Concurrent context metrics infinispan multi JVM hazelcastlock.
+     *
+     * @throws ApexModelException the apex model exception
+     * @throws IOException the IO exception
+     * @throws ApexException the apex exception
+     */
+    private void concurrentContextMetricsInfinispanMultiJVMHazelcastlock()
+            throws ApexModelException, IOException, ApexException {
+        LOGGER.debug("Running concurrentContextMetricsInfinispanMultiJVMHazelcastlock metrics . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanContextDistributor");
+        contextParameters.getLockManagerParameters()
+                .setPluginClass("org.onap.policy.apex.plugins.context.locking.hazelcast.HazelcastLockManager");
+
+        final InfinispanDistributorParameters infinispanParameters = new InfinispanDistributorParameters();
+        contextParameters.setDistributorParameters(infinispanParameters);
+
+        runConcurrentContextMetrics("InfinispanMultiJVMHazelcastlock");
+
+        LOGGER.debug("Ran concurrentContextMetricsInfinispanMultiJVMHazelcastlock metrics");
+    }
+
+    /**
+     * Concurrent context metrics infinispan multi JVM curator lock.
+     *
+     * @throws ApexModelException the apex model exception
+     * @throws IOException the IO exception
+     * @throws ApexException the apex exception
+     */
+    private void concurrentContextMetricsInfinispanMultiJVMCuratorLock()
+            throws ApexModelException, IOException, ApexException {
+        LOGGER.debug("Running concurrentContextMetricsInfinispanMultiJVMCuratorLock metrics . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanContextDistributor");
+
+        final CuratorLockManagerParameters curatorParameters = new CuratorLockManagerParameters();
+        curatorParameters.setPluginClass("org.onap.policy.apex.plugins.context.locking.curator.CuratorLockManager");
+        contextParameters.setLockManagerParameters(curatorParameters);
+        curatorParameters.setZookeeperAddress(zookeeperAddress);
+
+        final InfinispanDistributorParameters infinispanParameters = new InfinispanDistributorParameters();
+        contextParameters.setDistributorParameters(infinispanParameters);
+
+        runConcurrentContextMetrics("InfinispanMultiJVMCuratorLock");
+
+        LOGGER.debug("Ran concurrentContextMetricsInfinispanMultiJVMCuratorLock metrics");
+    }
+
+    /**
+     * Concurrent context metrics hazelcast multi JVM curator lock.
+     *
+     * @throws ApexModelException the apex model exception
+     * @throws IOException the IO exception
+     * @throws ApexException the apex exception
+     */
+    private void concurrentContextMetricsHazelcastMultiJVMCuratorLock()
+            throws ApexModelException, IOException, ApexException {
+        LOGGER.debug("Running concurrentContextMetricsHazelcastMultiJVMCuratorLock metrics . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.hazelcast.HazelcastContextDistributor");
+
+        final CuratorLockManagerParameters curatorParameters = new CuratorLockManagerParameters();
+        curatorParameters.setPluginClass("org.onap.policy.apex.plugins.context.locking.curator.CuratorLockManager");
+        contextParameters.setLockManagerParameters(curatorParameters);
+        curatorParameters.setZookeeperAddress(zookeeperAddress);
+
+        runConcurrentContextMetrics("HazelcastMultiJVMCuratorLock");
+
+        LOGGER.debug("Ran concurrentContextMetricsHazelcastMultiJVMCuratorLock metrics");
+    }
+
+    /**
+     * Run concurrent context metrics.
+     *
+     * @param testName the test name
+     * @throws ApexModelException the apex model exception
+     * @throws IOException the IO exception
+     * @throws ApexException the apex exception
+     */
+    private void runConcurrentContextMetrics(final String testName)
+            throws ApexModelException, IOException, ApexException {
+        total = -1;
+        outMetricLine(testName, "Init");
+
+        try {
+            setupContext();
+        } catch (final Exception e) {
+            e.printStackTrace();
+            throw e;
+        }
+
+        outMetricLine(testName, "Start");
+
+        Thread[] threadArray;
+
+        // Check if we have a single JVM or multiple JVMs
+        int runningThreadCount = -1;
+        if (jvmCount == 1) {
+            threadArray = new Thread[threadCount];
+
+            // Run everything in this JVM
+            for (int t = 0; t < threadCount; t++) {
+                threadArray[t] =
+                        new Thread(new ConcurrentContextMetricsThread(0, t, threadLoops, longArraySize, lockType));
+                threadArray[t].setName(testLabel + "_" + testName + ":concurrentContextMetricsThread_0_" + t);
+                threadArray[t].start();
+            }
+
+            outMetricLine(testName, "Running");
+            runningThreadCount = threadCount;
+        } else {
+            threadArray = new Thread[jvmCount];
+
+            final ConcurrentContextMetricsJVMThread[] jvmArray = new ConcurrentContextMetricsJVMThread[jvmCount];
+            // Spawn JVMs to run the tests
+            for (int j = 0; j < jvmCount; j++) {
+                jvmArray[j] = new ConcurrentContextMetricsJVMThread(testLabel + "_" + testName, j, threadCount,
+                        threadLoops, longArraySize, lockType);
+                threadArray[j] = new Thread(jvmArray[j]);
+                threadArray[j].setName(testLabel + "_" + testName + ":concurrentContextMetricsJVMThread_" + j);
+                threadArray[j].start();
+            }
+
+            boolean allReadyToGo;
+            do {
+                ThreadUtilities.sleep(TIME_10_MS);
+                allReadyToGo = true;
+                for (int j = 0; j < jvmCount; j++) {
+                    if (!jvmArray[j].isReadyToGo()) {
+                        allReadyToGo = false;
+                        break;
+                    }
+                }
+            } while (!allReadyToGo);
+
+            outMetricLine(testName, "Ready");
+            if (interactive) {
+                System.in.read();
+            }
+            outMetricLine(testName, "Running");
+
+            for (int j = 0; j < jvmCount; j++) {
+                jvmArray[j].offYouGo();
+            }
+
+            boolean allFinished;
+            do {
+                ThreadUtilities.sleep(TIME_10_MS);
+                allFinished = true;
+                for (int j = 0; j < jvmCount; j++) {
+                    if (!jvmArray[j].isAllFinished()) {
+                        allFinished = false;
+                        break;
+                    }
+                }
+            } while (!allFinished);
+
+            outMetricLine(testName, "Completed");
+
+            verifyContext(testName);
+
+            for (int j = 0; j < jvmCount; j++) {
+                jvmArray[j].finishItOut();
+            }
+
+            runningThreadCount = jvmCount;
+        }
+
+        boolean allFinished;
+        do {
+            ThreadUtilities.sleep(TIME_10_MS);
+            allFinished = true;
+            for (int i = 0; i < runningThreadCount; i++) {
+                if (threadArray[i].isAlive()) {
+                    allFinished = false;
+                    break;
+                }
+            }
+        } while (!allFinished);
+
+        if (jvmCount == 1) {
+            outMetricLine(testName, "Completed");
+            verifyContext(testName);
+        }
+
+        clearContext(testName);
+    }
+
+    /**
+     * Setup context.
+     *
+     * @throws ContextException the context exception
+     */
+    private void setupContext() throws ContextException {
+        final AxArtifactKey distributorKey = new AxArtifactKey("ApexDistributor", "0.0.1");
+        contextDistributor = new DistributorFactory().getDistributor(distributorKey);
+
+        final AxArtifactKey[] usedArtifactStackArray = {new AxArtifactKey("testC-top", "0.0.1"),
+                new AxArtifactKey("testC-next", "0.0.1"), new AxArtifactKey("testC-bot", "0.0.1")};
+
+        final AxContextModel albumsModel = TestContextAlbumFactory.createMultiAlbumsContextModel();
+        contextDistributor.registerModel(albumsModel);
+
+        lTypeAlbum = contextDistributor.createContextAlbum(new AxArtifactKey("LTypeContextAlbum", "0.0.1"));
+        assert (lTypeAlbum != null);
+        lTypeAlbum.setUserArtifactStack(usedArtifactStackArray);
+
+        for (int i = 0; i < longArraySize; i++) {
+            final String longKey = Integer.toString(i);
+            final TestContextItem003 longItem = new TestContextItem003();
+            longItem.setLongValue(0);
+            lTypeAlbum.put(longKey, longItem);
+        }
+    }
+
+    /**
+     * Verify context.
+     *
+     * @param testName the test name
+     * @throws ContextException the context exception
+     */
+    private void verifyContext(final String testName) throws ContextException {
+        total = 0;
+
+        try {
+            for (int i = 0; i < longArraySize; i++) {
+                total += ((TestContextItem003) lTypeAlbum.get(Integer.toString(i))).getLongValue();
+            }
+
+            outMetricLine(testName, "Totaled");
+        } catch (final Exception e) {
+            e.printStackTrace();
+        }
+
+        if (lockType == 2) {
+            if (total == jvmCount * threadCount * threadLoops) {
+                outMetricLine(testName, "VerifiedOK");
+            } else {
+                outMetricLine(testName, "VerifiedFail");
+            }
+        } else {
+            if (total == 0) {
+                outMetricLine(testName, "VerifiedOK");
+            } else {
+                outMetricLine(testName, "VerifiedFail");
+            }
+        }
+    }
+
+    /**
+     * Clear context.
+     *
+     * @param testName the test name
+     * @throws ContextException the context exception
+     */
+    private void clearContext(final String testName) throws ContextException {
+        contextDistributor.clear();
+        contextDistributor = null;
+
+        outMetricLine(testName, "Cleared");
+    }
+
+    /**
+     * Out metric line.
+     *
+     * @param testName the test name
+     * @param testPhase the test phase
+     */
+    public void outMetricLine(final String testName, final String testPhase) {
+        System.out.println("ContextMetrics," + dateFormat.format(new Date()) + "," + System.currentTimeMillis() + ","
+                + testLabel + "," + testName + "," + testPhase + "," + jvmCount + "," + threadCount + "," + threadLoops
+                + "," + longArraySize + "," + lockType + "," + total);
+    }
+}
diff --git a/plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/ConcurrentContextMetricsJVM.java b/plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/ConcurrentContextMetricsJVM.java
new file mode 100644 (file)
index 0000000..ed81e39
--- /dev/null
@@ -0,0 +1,212 @@
+/*-
+ * ============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.plugins.context.metrics;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+
+import org.onap.policy.apex.context.ContextAlbum;
+import org.onap.policy.apex.context.Distributor;
+import org.onap.policy.apex.context.impl.distribution.DistributorFactory;
+import org.onap.policy.apex.context.test.factory.TestContextAlbumFactory;
+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.service.AbstractParameters;
+import org.onap.policy.apex.model.basicmodel.service.ParameterService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextModel;
+import org.onap.policy.apex.model.utilities.Assertions;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+
+/**
+ * The Class ConcurrentContextMetricsJVM rins in its own JVM to test concurrent context updates and
+ * lockings across JVMs.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public final class ConcurrentContextMetricsJVM {
+    // Logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ConcurrentContextMetricsJVM.class);
+
+    private static final int NUM_ARGS = 6;
+    private static final int ARG_JVM_NO = 1;
+    private static final int ARG_THREAD_COUNT = 2;
+    private static final int ARG_ITERATIONS = 3;
+    private static final int ARG_ARRAY_SIZE = 4;
+    private static final int ARG_LOCK_TYPE = 5;
+
+    private static final int WAIT_10_MS = 10;
+
+    /**
+     * The Constructor for this class.
+     *
+     * @param testType the test type
+     * @param jvmNo the jvm no
+     * @param threadCount the thread count
+     * @param threadLoops the thread loops
+     * @param longArraySize the long array size
+     * @param lockType the lock type
+     * @throws ApexException the apex exception
+     * @throws IOException the IO exception
+     */
+    private ConcurrentContextMetricsJVM(final String testType, final int jvmNo, final int threadCount,
+            final int threadLoops, final int longArraySize, final int lockType) throws ApexException, IOException {
+        LOGGER.debug("starting JVMs and threads . . .");
+
+        final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
+
+        // Set up the distributor for this JVM
+        final AxArtifactKey distributorKey = new AxArtifactKey("ApexDistributor", "0.0.1");
+        final Distributor contextDistributor = new DistributorFactory().getDistributor(distributorKey);
+
+        final AxArtifactKey[] usedArtifactStackArray = {new AxArtifactKey("testC-top_" + jvmNo, "0.0.1"),
+                new AxArtifactKey("testC-next_" + jvmNo, "0.0.1"), new AxArtifactKey("testC-bot_" + jvmNo, "0.0.1")};
+
+        final AxContextModel testAxContextModel = TestContextAlbumFactory.createLongContextModel();
+        contextDistributor.registerModel(testAxContextModel);
+        final ContextAlbum testContextAlbum =
+                contextDistributor.createContextAlbum(new AxArtifactKey("LongSameTypeContextAlbum", "0.0.1"));
+        Assertions.argumentNotNull(testContextAlbum, "testContextAlbum may not be null");
+        testContextAlbum.setUserArtifactStack(usedArtifactStackArray);
+
+        final Thread[] threadArray = new Thread[threadCount];
+
+        for (int t = 0; t < threadCount; t++) {
+            threadArray[t] =
+                    new Thread(new ConcurrentContextMetricsThread(jvmNo, t, threadLoops, longArraySize, lockType));
+            threadArray[t].setName(testType + ":ConcurrentContextMetricsThread_" + jvmNo + "_" + t);
+            threadArray[t].start();
+            LOGGER.debug("started thread " + threadArray[t].getName());
+        }
+
+        System.out.println("ReadyToGo");
+        while (true) {
+            final String goLine = bufferedReader.readLine();
+            if (!goLine.trim().equals("OffYouGo")) {
+                throw new IOException("Expected OffYouGo");
+            }
+            break;
+        }
+
+        boolean allFinished;
+        do {
+            allFinished = true;
+            for (int t = 0; t < threadCount; t++) {
+                if (threadArray[t].isAlive()) {
+                    allFinished = false;
+                    ThreadUtilities.sleep(WAIT_10_MS);
+                    break;
+                }
+            }
+        } while (!allFinished);
+
+        System.out.println("AllFinished");
+        while (true) {
+            final String goLine = bufferedReader.readLine();
+            if (!goLine.trim().equals("FinishItOut")) {
+                throw new IOException("Expected FinishItOut");
+            }
+            break;
+        }
+
+        LOGGER.debug("threads finished");
+        contextDistributor.clear();
+    }
+
+    /**
+     * The main method.
+     *
+     * @param args the args
+     * @throws JsonSyntaxException the json syntax exception
+     * @throws ClassNotFoundException the class not found exception
+     */
+    @SuppressWarnings("unchecked")
+    public static void main(final String[] args) throws JsonSyntaxException, ClassNotFoundException {
+        if (args.length < NUM_ARGS || (args.length % 2 != 0)) {
+            LOGGER.error("invalid arguments: " + Arrays.toString(args));
+            LOGGER.error(
+                    "usage: ConcurrentContextMetricsJVM testLabel jvmNo threadCount threadLoops longArraySize lockType [parameterKey parameterJson].... ");
+            return;
+        }
+
+        int jvmNo = -1;
+        int threadCount = -1;
+        int threadLoops = -1;
+        int longArraySize = -1;
+        int lockType = -1;
+
+        try {
+            jvmNo = Integer.parseInt(args[ARG_JVM_NO]);
+        } catch (final Exception e) {
+            LOGGER.error("invalid argument jvmNo", e);
+            return;
+        }
+
+        try {
+            threadCount = Integer.parseInt(args[ARG_THREAD_COUNT]);
+        } catch (final Exception e) {
+            LOGGER.error("invalid argument threadCount", e);
+            return;
+        }
+
+        try {
+            threadLoops = Integer.parseInt(args[ARG_ITERATIONS]);
+        } catch (final Exception e) {
+            LOGGER.error("invalid argument threadLoops", e);
+            return;
+        }
+
+        try {
+            longArraySize = Integer.parseInt(args[ARG_ARRAY_SIZE]);
+        } catch (final Exception e) {
+            LOGGER.error("invalid argument longArraySize", e);
+            return;
+        }
+
+        try {
+            lockType = Integer.parseInt(args[ARG_LOCK_TYPE]);
+        } catch (final Exception e) {
+            LOGGER.error("invalid argument lockType", e);
+            return;
+        }
+
+        for (int p = NUM_ARGS; p < args.length - 1; p += 2) {
+            @SuppressWarnings("rawtypes")
+            final Class parametersClass = Class.forName(args[p]);
+            final AbstractParameters parameters =
+                    (AbstractParameters) new Gson().fromJson(args[p + 1], parametersClass);
+            ParameterService.registerParameters(parametersClass, parameters);
+        }
+
+        try {
+            new ConcurrentContextMetricsJVM(args[0], jvmNo, threadCount, threadLoops, longArraySize, lockType);
+        } catch (final Exception e) {
+            LOGGER.error("error running test in JVM", e);
+            return;
+        }
+    }
+}
diff --git a/plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/ConcurrentContextMetricsJVMThread.java b/plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/ConcurrentContextMetricsJVMThread.java
new file mode 100644 (file)
index 0000000..64bc0ca
--- /dev/null
@@ -0,0 +1,187 @@
+/*-
+ * ============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.plugins.context.metrics;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.service.AbstractParameters;
+import org.onap.policy.apex.model.basicmodel.service.ParameterService;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import com.google.gson.Gson;
+
+/**
+ * The Class ConcurrentContextMetricsJVMThread gets metrics for concurrent use of context.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ConcurrentContextMetricsJVMThread implements Runnable {
+    // Logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ConcurrentContextMetricsJVMThread.class);
+
+    private final String testType;
+    private final int jvm;
+    private final int threadCount;
+    private final int threadLoops;
+    private final int longArraySize;
+    private final int lockType;
+
+    private boolean readyToGo = false;
+    private boolean allFinished = false;
+
+    private PrintWriter processWriter;
+
+    /**
+     * The Constructor.
+     *
+     * @param testType the test type
+     * @param jvm the jvm
+     * @param threadCount the thread count
+     * @param threadLoops the thread loops
+     * @param longArraySize the long array size
+     * @param lockType the lock type
+     * @throws ApexException the apex exception
+     */
+    public ConcurrentContextMetricsJVMThread(final String testType, final int jvm, final int threadCount,
+            final int threadLoops, final int longArraySize, final int lockType) throws ApexException {
+        this.testType = testType;
+        this.jvm = jvm;
+        this.threadCount = threadCount;
+        this.threadLoops = threadLoops;
+        this.longArraySize = longArraySize;
+        this.lockType = lockType;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Runnable#run()
+     */
+    @Override
+    public void run() {
+        final List<String> commandList = new ArrayList<>();
+        commandList.add(System.getProperty("java.home") + System.getProperty("file.separator") + "bin"
+                + System.getProperty("file.separator") + "java");
+        commandList.add("-cp");
+        commandList.add(System.getProperty("java.class.path"));
+        for (final Entry<Object, Object> property : System.getProperties().entrySet()) {
+            if (property.getKey().toString().startsWith("APEX")
+                    || property.getKey().toString().equals("java.net.preferIPv4Stack")
+                    || property.getKey().toString().equals("jgroups.bind_addr")) {
+                commandList.add("-D" + property.getKey().toString() + "=" + property.getValue().toString());
+            }
+        }
+        commandList.add("org.onap.policy.apex.plugins.context.metrics.ConcurrentContextMetricsJVM");
+        commandList.add(testType);
+        commandList.add(new Integer(jvm).toString());
+        commandList.add(new Integer(threadCount).toString());
+        commandList.add(new Integer(threadLoops).toString());
+        commandList.add(new Integer(longArraySize).toString());
+        commandList.add(new Integer(lockType).toString());
+
+        for (final Entry<Class<?>, AbstractParameters> parameterServiceEntry : ParameterService.getAll()) {
+            commandList.add(parameterServiceEntry.getKey().getCanonicalName());
+            commandList.add(new Gson().toJson(parameterServiceEntry.getValue()));
+        }
+
+        LOGGER.info("starting JVM " + jvm);
+
+        // Run the JVM
+        final ProcessBuilder processBuilder = new ProcessBuilder(commandList);
+        processBuilder.redirectErrorStream(true);
+        Process process;
+
+        try {
+            process = processBuilder.start();
+
+            final InputStream is = process.getInputStream();
+            processWriter = new PrintWriter(process.getOutputStream());
+            final InputStreamReader isr = new InputStreamReader(is);
+            final BufferedReader br = new BufferedReader(isr);
+
+            String line;
+
+            LOGGER.info("JVM Output for command " + commandList + "\n");
+            while ((line = br.readLine()) != null) {
+                LOGGER.info(line);
+
+                if (line.trim().equals("ReadyToGo")) {
+                    readyToGo = true;
+                } else if (line.trim().equals("AllFinished")) {
+                    allFinished = true;
+                }
+            }
+
+            // Wait to get exit value
+            try {
+                final int exitValue = process.waitFor();
+                LOGGER.info("\n\nJVM " + jvm + " finished, exit value is " + exitValue);
+            } catch (final InterruptedException e) {
+                e.printStackTrace();
+            }
+        } catch (final IOException e1) {
+            e1.printStackTrace();
+        }
+    }
+
+    /**
+     * Checks if is ready to go.
+     *
+     * @return true, if checks if is ready to go
+     */
+    public boolean isReadyToGo() {
+        return readyToGo;
+    }
+
+    /**
+     * Checks if is all finished.
+     *
+     * @return true, if checks if is all finished
+     */
+    public boolean isAllFinished() {
+        return allFinished;
+    }
+
+    /**
+     * Off you go.
+     */
+    public void offYouGo() {
+        processWriter.println("OffYouGo");
+        processWriter.flush();
+    }
+
+    /**
+     * Finish it out.
+     */
+    public void finishItOut() {
+        processWriter.println("FinishItOut");
+        processWriter.flush();
+    }
+}
diff --git a/plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/ConcurrentContextMetricsThread.java b/plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/ConcurrentContextMetricsThread.java
new file mode 100644 (file)
index 0000000..2752536
--- /dev/null
@@ -0,0 +1,170 @@
+/*-
+ * ============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.plugins.context.metrics;
+
+import java.util.Random;
+
+import org.onap.policy.apex.context.ContextAlbum;
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.context.Distributor;
+import org.onap.policy.apex.context.impl.distribution.DistributorFactory;
+import org.onap.policy.apex.context.test.concepts.TestContextItem003;
+import org.onap.policy.apex.context.test.factory.TestContextAlbumFactory;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextModel;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The Class ConcurrentContextMetricsThread gets metrics for concurrent use of context.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class ConcurrentContextMetricsThread implements Runnable {
+    // Logger for this class
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(ConcurrentContextMetricsThread.class);
+    private final Distributor contextDistributor;
+    private final int jvm;
+    private final int instance;
+    private final int threadLoops;
+    private final int longArraySize;
+    private final int lockType;
+
+    /**
+     * The Constructor.
+     *
+     * @param jvm the jvm
+     * @param instance the instance
+     * @param threadLoops the thread loops
+     * @param longArraySize the long array size
+     * @param lockType the lock type
+     * @throws ApexException the apex exception
+     */
+    public ConcurrentContextMetricsThread(final int jvm, final int instance, final int threadLoops,
+            final int longArraySize, final int lockType) throws ApexException {
+        this.jvm = jvm;
+        this.instance = instance;
+        this.threadLoops = threadLoops;
+        this.longArraySize = longArraySize;
+        this.lockType = lockType;
+
+        final AxArtifactKey distributorKey = new AxArtifactKey("ApexDistributor_" + jvm + "_" + instance, "0.0.1");
+        contextDistributor = new DistributorFactory().getDistributor(distributorKey);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Runnable#run()
+     */
+    @Override
+    public void run() {
+        LOGGER.info("running ConcurrentContextMetricsThread_" + jvm + "_" + instance + " . . .");
+
+        ContextAlbum lTypeAlbum = null;
+        try {
+            final AxContextModel axTestContextModel = TestContextAlbumFactory.createMultiAlbumsContextModel();
+            contextDistributor.registerModel(axTestContextModel);
+            lTypeAlbum = contextDistributor.createContextAlbum(new AxArtifactKey("LTypeContextAlbum", "0.0.1"));
+        } catch (final Exception e) {
+            LOGGER.error("could not get the test context album", e);
+            LOGGER.error("failed ConcurrentContextMetricsThread_" + jvm + "_" + instance);
+            return;
+        }
+
+        if (lTypeAlbum == null) {
+            LOGGER.error("could not find the test context album");
+            LOGGER.error("failed ConcurrentContextMetricsThread_" + jvm + "_" + instance);
+            return;
+        }
+
+        final AxArtifactKey[] usedArtifactStackArray =
+                {new AxArtifactKey("testCC-top", "0.0.1"), new AxArtifactKey("testCC-" + instance, "0.0.1")};
+
+        lTypeAlbum.setUserArtifactStack(usedArtifactStackArray);
+
+        final Random rand = new Random();
+
+        for (int i = 0; i < threadLoops; i++) {
+            // Get the next random entry to use
+            final String nextLongKey = Integer.toString(rand.nextInt(longArraySize));
+
+            if (lockType == 0) {
+                final TestContextItem003 item = (TestContextItem003) lTypeAlbum.get(nextLongKey);
+                final long value = item.getLongValue();
+                if (LOGGER.isTraceEnabled()) {
+                    LOGGER.trace("lock type=" + lockType + ", value=" + value);
+                }
+                continue;
+            }
+
+            if (lockType == 1) {
+                try {
+                    lTypeAlbum.lockForReading(nextLongKey);
+                } catch (final ContextException e) {
+                    LOGGER.error("could not acquire read lock on context album, key=" + nextLongKey, e);
+                    continue;
+                }
+
+                final TestContextItem003 item = (TestContextItem003) lTypeAlbum.get(nextLongKey);
+                final long value = item.getLongValue();
+                if (LOGGER.isTraceEnabled()) {
+                    LOGGER.trace("lock type=" + lockType + ", value=" + value);
+                }
+
+                try {
+                    lTypeAlbum.unlockForReading(nextLongKey);
+                } catch (final ContextException e) {
+                    LOGGER.error("could not release read lock on context album, key=" + nextLongKey, e);
+                }
+
+                continue;
+            }
+
+            if (lockType == 2) {
+                try {
+                    lTypeAlbum.lockForWriting(nextLongKey);
+                } catch (final ContextException e) {
+                    LOGGER.error("could not acquire write lock on context album, key=" + nextLongKey, e);
+                    continue;
+                }
+
+                final TestContextItem003 item = (TestContextItem003) lTypeAlbum.get(nextLongKey);
+                long value = item.getLongValue();
+                if (LOGGER.isTraceEnabled()) {
+                    LOGGER.trace("lock type=" + lockType + ", value=" + value);
+                }
+                item.setLongValue(++value);
+                lTypeAlbum.put(nextLongKey, item);
+
+                try {
+                    lTypeAlbum.unlockForWriting(nextLongKey);
+                } catch (final ContextException e) {
+                    LOGGER.error("could not release write lock on context album, key=" + nextLongKey, e);
+                }
+                continue;
+            }
+        }
+
+        LOGGER.info("completed ConcurrentContextMetricsThread_" + jvm + "_" + instance);
+    }
+}
diff --git a/plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/package-info.java b/plugins/plugins-context/context-metrics/src/main/java/org/onap/policy/apex/plugins/context/metrics/package-info.java
new file mode 100644 (file)
index 0000000..5e916b6
--- /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=========================================================
+ */
+
+/**
+ * Used to get metrics on the performance of Context Album performance for various types of
+ * distribution and locking mechanisms in APEX.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.plugins.context.metrics;
diff --git a/plugins/plugins-context/context-metrics/src/test/java/org/onap/policy/apex/plugins/context/metrics/TestMetrics.java b/plugins/plugins-context/context-metrics/src/test/java/org/onap/policy/apex/plugins/context/metrics/TestMetrics.java
new file mode 100644 (file)
index 0000000..5607f87
--- /dev/null
@@ -0,0 +1,57 @@
+/*-
+ * ============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.plugins.context.metrics;
+
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+
+import org.apache.curator.test.TestingServer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestMetrics {
+    // Zookeeper test server
+    TestingServer zkTestServer;
+
+    @Before
+    public void beforeTest() throws Exception {
+        zkTestServer = new TestingServer(62181);
+    }
+
+    @After
+    public void afterTest() throws IOException {
+        zkTestServer.stop();
+    }
+
+    @Test
+    public void getSingleJVMMetrics() {
+        final String[] args = {"singleJVMTestNL", "1", "32", "1000", "65536", "0", "localhost:62181", "false"};
+
+        try {
+            ConcurrentContextMetrics.main(args);
+        } catch (final Exception e) {
+            fail("Metrics test failed");
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/plugins/plugins-context/context-metrics/src/test/resources/hazelcast/hazelcast.xml b/plugins/plugins-context/context-metrics/src/test/resources/hazelcast/hazelcast.xml
new file mode 100644 (file)
index 0000000..84da495
--- /dev/null
@@ -0,0 +1,643 @@
+<?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=========================================================
+-->
+
+<hazelcast xmlns="http://www.hazelcast.com/schema/config"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+       <group>
+               <name>HazelcastGroup3.0EVAL</name>
+               <password>password3.0EVAL</password>
+       </group>
+       <network>
+               <port auto-increment="true">5706</port>
+               <join>
+                       <multicast enabled="false">
+                               <multicast-group>224.2.2.10</multicast-group>
+                               <multicast-port>54327</multicast-port>
+                       </multicast>
+                       <tcp-ip enabled="true">
+                               <members>10.0.0.0</members>
+                               <!-- members>192.168.219.141</members-->
+                       </tcp-ip>
+               </join>
+               <interfaces enabled="false">
+                       <!-- This value will allow hazelcast to run locally from the IDE -->
+                       <interface>127.0.0.*</interface>
+               </interfaces>
+       </network>
+       <properties>
+               <property name="hazelcast.icmp.enabled">true</property>
+               <property name="hazelcast.logging.type">slf4j</property>
+               <!-- disable the hazelcast shutdown hook - prefer to control the shutdown 
+                       in code -->
+               <property name="hazelcast.shutdownhook.enabled">false</property>
+               <property name="hazelcast.graceful.shutdown.max.wait">60</property>
+       </properties>
+       <executor-service>
+               <pool-size>16</pool-size>
+       </executor-service>
+       <queue name="default">
+               <!-- Maximum size of the queue. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>100000</max-size>
+               <!-- Maximum number of seconds for each item to stay in the queue. Items 
+                       that are not consumed in <time-to-live-seconds> will automatically get evicted 
+                       from the queue. Any integer between 0 and Integer.MAX_VALUE. 0 means infinite. 
+                       Default is 0. -->
+       </queue>
+       <map name="default">
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>1</backup-count>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>NONE</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>0</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>25</eviction-percentage>
+       </map>
+       <map name="L_ATTACH-Map">
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>1</backup-count>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>LRU</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>1000000</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>5</eviction-percentage>
+
+               <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                       that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                       will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means infinite. Default is 0. -->
+               <time-to-live-seconds>0</time-to-live-seconds>
+
+               <!-- <map-store enabled="true"> Name of the class implementing MapLoader 
+                       and/or MapStore. The class should implement at least of these interfaces 
+                       and contain no-argument constructor. Note that the inner classes are not 
+                       supported. <class-name>com.ericsson.xstream.loading.service.buffer.L_ATTACHLoader</class-name> 
+                       Number of seconds to delay to call the MapStore.store(key, value). If the 
+                       value is zero then it is write-through so MapStore.store(key, value) will 
+                       be called as soon as the entry is updated. Otherwise it is write-behind so 
+                       updates will be stored after write-delay-seconds value by calling Hazelcast.storeAll(map). 
+                       Default value is 0. <write-delay-seconds>60000</write-delay-seconds> </map-store> -->
+
+
+       </map>
+       <map name="CTUM-Map">
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>1</backup-count>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>LRU</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>1000000</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>5</eviction-percentage>
+
+               <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                       that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                       will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means infinite. Default is 0. -->
+               <time-to-live-seconds>7200</time-to-live-seconds>
+
+               <!-- <map-store enabled="true"> Name of the class implementing MapLoader 
+                       and/or MapStore. The class should implement at least of these interfaces 
+                       and contain no-argument constructor. Note that the inner classes are not 
+                       supported. <class-name>com.ericsson.xstream.loading.service.buffer.CTUMLoader</class-name> 
+                       Number of seconds to delay to call the MapStore.store(key, value). If the 
+                       value is zero then it is write-through so MapStore.store(key, value) will 
+                       be called as soon as the entry is updated. Otherwise it is write-behind so 
+                       updates will be stored after write-delay-seconds value by calling Hazelcast.storeAll(map). 
+                       Default value is 0. <write-delay-seconds>3600</write-delay-seconds> </map-store> -->
+
+       </map>
+       <map name="L_HANDOVER-Map">
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>1</backup-count>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>LRU</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>1000000</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>5</eviction-percentage>
+
+               <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                       that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                       will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means infinite. Default is 0. -->
+               <time-to-live-seconds>3600</time-to-live-seconds>
+
+               <!-- <map-store enabled="true"> Name of the class implementing MapLoader 
+                       and/or MapStore. The class should implement at least of these interfaces 
+                       and contain no-argument constructor. Note that the inner classes are not 
+                       supported. <class-name>com.ericsson.xstream.base.publishing.hazelcast.L_ATTACHStore</class-name> 
+                       Number of seconds to delay to call the MapStore.store(key, value). If the 
+                       value is zero then it is write-through so MapStore.store(key, value) will 
+                       be called as soon as the entry is updated. Otherwise it is write-behind so 
+                       updates will be stored after write-delay-seconds value by calling Hazelcast.storeAll(map). 
+                       Default value is 0. <write-delay-seconds>5</write-delay-seconds> </map-store> -->
+
+
+       </map>
+
+       <map name="L_SERVICE_REQUEST-Map">
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>1</backup-count>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>LRU</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>1000000</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>5</eviction-percentage>
+
+               <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                       that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                       will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means infinite. Default is 0. -->
+               <time-to-live-seconds>7200</time-to-live-seconds>
+
+               <!-- <map-store enabled="true"> Name of the class implementing MapLoader 
+                       and/or MapStore. The class should implement at least of these interfaces 
+                       and contain no-argument constructor. Note that the inner classes are not 
+                       supported. <class-name>com.ericsson.xstream.base.publishing.hazelcast.L_HandoverStore</class-name> 
+                       Number of seconds to delay to call the MapStore.store(key, value). If the 
+                       value is zero then it is write-through so MapStore.store(key, value) will 
+                       be called as soon as the entry is updated. Otherwise it is write-behind so 
+                       updates will be stored after write-delay-seconds value by calling Hazelcast.storeAll(map). 
+                       Default value is 0. <write-delay-seconds>5</write-delay-seconds> </map-store> -->
+
+
+       </map>
+       <map name="CommonCache">
+
+
+               <!-- Number of async-backups. If 1 is set as the backup-count for example, 
+                       then all entries of the map will be copied to another JVM for fail-safety. 
+                       Valid numbers are 0 (no backup), 1, 2, 3. -->
+               <async-backup-count>1</async-backup-count>
+
+               <!-- Can we read the local backup entries? Default value is false for strong 
+                       consistency. Being able to read backup data will give you greater performance. -->
+               <read-backup-data>true</read-backup-data>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>LRU</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>3000000</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>5</eviction-percentage>
+
+               <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                       that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                       will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means infinite. Default is 0. -->
+               <time-to-live-seconds>7200</time-to-live-seconds>
+
+               <!-- <map-store enabled="true"> Name of the class implementing MapLoader 
+                       and/or MapStore. The class should implement at least of these interfaces 
+                       and contain no-argument constructor. Note that the inner classes are not 
+                       supported. <class-name>com.ericsson.xstream.base.publishing.hazelcast.L_HandoverStore</class-name> 
+                       Number of seconds to delay to call the MapStore.store(key, value). If the 
+                       value is zero then it is write-through so MapStore.store(key, value) will 
+                       be called as soon as the entry is updated. Otherwise it is write-behind so 
+                       updates will be stored after write-delay-seconds value by calling Hazelcast.storeAll(map). 
+                       Default value is 0. <write-delay-seconds>5</write-delay-seconds> </map-store> -->
+
+
+       </map>
+
+
+       <map name="Topology-Map">
+
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>2</backup-count>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>NONE</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>10000000</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>0</eviction-percentage>
+
+
+               <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                       that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                       will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means infinite. Default is 0. -->
+               <time-to-live-seconds>0</time-to-live-seconds>
+
+               <!-- <map-store enabled="true"> Name of the class implementing MapLoader 
+                       and/or MapStore. The class should implement at least of these interfaces 
+                       and contain no-argument constructor. Note that the inner classes are not 
+                       supported. <class-name>com.ericsson.xstream.loading.service.buffer.TopologyCacheLoader</class-name> 
+                       Number of seconds to delay to call the MapStore.store(key, value). If the 
+                       value is zero then it is write-through so MapStore.store(key, value) will 
+                       be called as soon as the entry is updated. Otherwise it is write-behind so 
+                       updates will be stored after write-delay-seconds value by calling Hazelcast.storeAll(map). 
+                       Default value is 0. <write-delay-seconds>5</write-delay-seconds> </map-store> -->
+
+
+
+       </map>
+       <map name="Protocol-cause-code-Map">
+               <near-cache>
+                       <!-- Maximum number of seconds for each entry to stay in the near cache. 
+                               Entries that are older than <time-to-live-seconds> will get automatically 
+                               evicted from the near cache. Any integer between 0 and Integer.MAX_VALUE. 
+                               0 means infinite. Default is 0. -->
+                       <time-to-live-seconds>0</time-to-live-seconds>
+
+                       <!-- Maximum number of seconds each entry can stay in the near cache as 
+                               untouched (not-read). Entries that are not read (touched) more than <max-idle-seconds> 
+                               value will get removed from the near cache. Any integer between 0 and Integer.MAX_VALUE. 
+                               0 means Integer.MAX_VALUE. Default is 0. -->
+                       <max-idle-seconds>0</max-idle-seconds>
+
+                       <!-- Valid values are: NONE (no extra eviction, <time-to-live-seconds> 
+                               may still apply), LRU (Least Recently Used), LFU (Least Frequently Used). 
+                               NONE is the default. Regardless of the eviction policy used, <time-to-live-seconds> 
+                               will still apply. -->
+                       <eviction-policy>NONE</eviction-policy>
+
+                       <!-- Maximum size of the near cache. When max size is reached, cache is 
+                               evicted based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                               0 means Integer.MAX_VALUE. Default is 0. -->
+                       <max-size>2000</max-size>
+
+                       <!-- Should the cached entries get evicted if the entries are changed 
+                               (updated or removed). true of false. Default is true. -->
+                       <invalidate-on-change>true</invalidate-on-change>
+
+               </near-cache>
+
+
+
+       </map>
+       <map name="SessionId_Map">
+
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>1</backup-count>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>NONE</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>10000000</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>0</eviction-percentage>
+
+
+               <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                       that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                       will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means infinite. Default is 0. -->
+               <time-to-live-seconds>60</time-to-live-seconds>
+               <!-- <map-store enabled="true"> Name of the class implementing MapLoader 
+                       and/or MapStore. The class should implement at least of these interfaces 
+                       and contain no-argument constructor. Note that the inner classes are not 
+                       supported. <class-name>com.ericsson.xstream.loading.service.buffer.TopologyCacheLoader</class-name> 
+                       Number of seconds to delay to call the MapStore.store(key, value). If the 
+                       value is zero then it is write-through so MapStore.store(key, value) will 
+                       be called as soon as the entry is updated. Otherwise it is write-behind so 
+                       updates will be stored after write-delay-seconds value by calling Hazelcast.storeAll(map). 
+                       Default value is 0. <write-delay-seconds>5</write-delay-seconds> </map-store> -->
+
+
+       </map>
+       <map name="gpeh-reasons-Map">
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>2</backup-count>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>0</eviction-percentage>
+               <near-cache>
+                       <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                               all entries of the map will be copied to another JVM for fail-safety. Valid 
+                               numbers are 0 (no backup), 1, 2, 3. -->
+                       <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), 
+                               LFU (Least Frequently Used). NONE is the default. -->
+                       <eviction-policy>NONE</eviction-policy>
+                       <!-- Maximum size of the map. When max size is reached, map is evicted 
+                               based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                               0 means Integer.MAX_VALUE. Default is 0. -->
+                       <max-size>1000</max-size>
+
+
+                       <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                               that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                               will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                               0 means infinite. Default is 0. -->
+                       <time-to-live-seconds>0</time-to-live-seconds>
+               </near-cache>
+       </map>
+       <map name="tac-imei-Map">
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>2</backup-count>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>0</eviction-percentage>
+
+               <near-cache>
+                       <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), 
+                               LFU (Least Frequently Used). NONE is the default. -->
+                       <eviction-policy>NONE</eviction-policy>
+                       <!-- Maximum size of the map. When max size is reached, map is evicted 
+                               based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                               0 means Integer.MAX_VALUE. Default is 0. -->
+                       <max-size>10000</max-size>
+
+                       <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                               that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                               will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                               0 means infinite. Default is 0. -->
+                       <time-to-live-seconds>0</time-to-live-seconds>
+               </near-cache>
+       </map>
+
+       <map name="CORE-DATA-Map">
+
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>2</backup-count>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>NONE</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>10000000</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>0</eviction-percentage>
+
+
+               <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                       that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                       will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means infinite. Default is 0. -->
+               <time-to-live-seconds>0</time-to-live-seconds>
+
+               <!-- <map-store enabled="true"> Name of the class implementing MapLoader 
+                       and/or MapStore. The class should implement at least of these interfaces 
+                       and contain no-argument constructor. Note that the inner classes are not 
+                       supported. <class-name>com.ericsson.xstream.loading.service.buffer.TopologyCacheLoader</class-name> 
+                       Number of seconds to delay to call the MapStore.store(key, value). If the 
+                       value is zero then it is write-through so MapStore.store(key, value) will 
+                       be called as soon as the entry is updated. Otherwise it is write-behind so 
+                       updates will be stored after write-delay-seconds value by calling Hazelcast.storeAll(map). 
+                       Default value is 0. <write-delay-seconds>5</write-delay-seconds> </map-store> -->
+
+
+
+       </map>
+       <map name="IMSI-APN-Map">
+
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>2</backup-count>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>NONE</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>10000000</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>0</eviction-percentage>
+
+
+               <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                       that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                       will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means infinite. Default is 0. -->
+               <time-to-live-seconds>0</time-to-live-seconds>
+
+               <!-- <map-store enabled="true"> Name of the class implementing MapLoader 
+                       and/or MapStore. The class should implement at least of these interfaces 
+                       and contain no-argument constructor. Note that the inner classes are not 
+                       supported. <class-name>com.ericsson.xstream.loading.service.buffer.TopologyCacheLoader</class-name> 
+                       Number of seconds to delay to call the MapStore.store(key, value). If the 
+                       value is zero then it is write-through so MapStore.store(key, value) will 
+                       be called as soon as the entry is updated. Otherwise it is write-behind so 
+                       updates will be stored after write-delay-seconds value by calling Hazelcast.storeAll(map). 
+                       Default value is 0. <write-delay-seconds>5</write-delay-seconds> </map-store> -->
+
+
+
+       </map>
+       <map name="CommonDataCache">
+
+
+               <!-- Number of async-backups. If 1 is set as the backup-count for example, 
+                       then all entries of the map will be copied to another JVM for fail-safety. 
+                       Valid numbers are 0 (no backup), 1, 2, 3. -->
+               <async-backup-count>1</async-backup-count>
+
+               <!-- Can we read the local backup entries? Default value is false for strong 
+                       consistency. Being able to read backup data will give you greater performance. -->
+               <read-backup-data>true</read-backup-data>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>LRU</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>3000000</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>5</eviction-percentage>
+
+               <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                       that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                       will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means infinite. Default is 0. -->
+               <time-to-live-seconds>7200</time-to-live-seconds>
+
+               <!-- <map-store enabled="true"> Name of the class implementing MapLoader 
+                       and/or MapStore. The class should implement at least of these interfaces 
+                       and contain no-argument constructor. Note that the inner classes are not 
+                       supported. <class-name>com.ericsson.xstream.base.publishing.hazelcast.L_HandoverStore</class-name> 
+                       Number of seconds to delay to call the MapStore.store(key, value). If the 
+                       value is zero then it is write-through so MapStore.store(key, value) will 
+                       be called as soon as the entry is updated. Otherwise it is write-behind so 
+                       updates will be stored after write-delay-seconds value by calling Hazelcast.storeAll(map). 
+                       Default value is 0. <write-delay-seconds>5</write-delay-seconds> </map-store> -->
+
+
+       </map>
+
+
+       <queue name="raw-distributer-queue">
+               <!-- Maximum size of the queue. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>100000</max-size>
+       </queue>
+       <map name="queue-map">
+
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>0</backup-count>
+
+       </map>
+
+       <map name="radio-correlation-config-Map">
+               <backup-count>2</backup-count>
+               <eviction-policy>NONE</eviction-policy>
+               <max-size>50</max-size>
+               <eviction-percentage>0</eviction-percentage>
+               <time-to-live-seconds>0</time-to-live-seconds>
+       </map>
+
+       <map name="xstream-configuration-map">
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>0</backup-count>
+               <time-to-live-seconds>100000</time-to-live-seconds>
+       </map>
+
+       <map name="TOPIC-TASK-MAP">
+
+               <async-backup-count>3</async-backup-count>
+
+               <read-backup-data>true</read-backup-data>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>NONE</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>1000</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>0</eviction-percentage>
+
+
+
+               <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                       that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                       will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means infinite. Default is 0. -->
+               <time-to-live-seconds>0</time-to-live-seconds>
+       </map>
+       <map name="TOPIC-REGISTRY">
+
+               <async-backup-count>3</async-backup-count>
+
+               <read-backup-data>true</read-backup-data>
+               <!-- Valid values are: NONE (no eviction), LRU (Least Recently Used), LFU 
+                       (Least Frequiently Used). NONE is the default. -->
+               <eviction-policy>NONE</eviction-policy>
+               <!-- Maximum size of the map. When max size is reached, map is evicted 
+                       based on the policy defined. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>1000</max-size>
+               <!-- When max. size is reached, specified percentage of the map will be 
+                       evicted. Any integer between 0 and 100. If 25 is set for example, 25% of 
+                       the entries will get evicted. -->
+               <eviction-percentage>0</eviction-percentage>
+
+
+
+               <!-- Maximum number of seconds for each entry to stay in the map. Entries 
+                       that are older than <time-to-live-seconds> and not updated for <time-to-live-seconds> 
+                       will get automatically evicted from the map. Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means infinite. Default is 0. -->
+               <time-to-live-seconds>0</time-to-live-seconds>
+       </map>
+       <queue name="Pooled-Topic-Request-Queue">
+               <!-- Maximum size of the queue.Any integer between 0 and Integer.MAX_VALUE. 
+                       0 means Integer.MAX_VALUE. Default is 0. -->
+               <max-size>100000</max-size>
+       </queue>
+       <map name="Pooled-Topic-Request-Queue-Backup-map">
+
+               <!-- Number of backups. If 1 is set as the backup-count for example, then 
+                       all entries of the map will be copied to another JVM for fail-safety. Valid 
+                       numbers are 0 (no backup), 1, 2, 3. -->
+               <backup-count>1</backup-count>
+               <eviction-policy>NONE</eviction-policy>
+               <time-to-live-seconds>0</time-to-live-seconds>
+       </map>
+
+</hazelcast>
diff --git a/plugins/plugins-context/context-metrics/src/test/resources/infinispan/infinispan.xml b/plugins/plugins-context/context-metrics/src/test/resources/infinispan/infinispan.xml
new file mode 100644 (file)
index 0000000..a854133
--- /dev/null
@@ -0,0 +1,42 @@
+<?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=========================================================
+-->
+
+<?xml version="1.0" encoding="UTF-8"?>
+
+<infinispan xmlns="urn:infinispan:config:8.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:infinispan:config:8.0 http://infinispan.org/schemas/infinispan-config-8.0.xsd">
+       <jgroups>
+               <stack-file name="external-file" path="default-configs/default-jgroups-tcp.xml" />
+       </jgroups>
+
+       <cache-container name="ApexCacheContainer" default-cache="TestContext_0.0.1">
+               <transport cluster="apexCluster" stack="external-file" />
+               <jmx />
+               <replicated-cache name="LargeContextMap_0.0.1" mode="SYNC" statistics="true">
+                       <state-transfer enabled="true" />
+               </replicated-cache>
+               <replicated-cache name="LongSameTypeContextMap_0.0.1" mode="SYNC" statistics="true">
+                       <state-transfer enabled="true" />
+               </replicated-cache>
+               <replicated-cache name="TestContext_0.0.1" mode="SYNC">
+                       <state-transfer enabled="true" />
+               </replicated-cache>
+       </cache-container>
+</infinispan>
diff --git a/plugins/plugins-context/context-persistence/pom.xml b/plugins/plugins-context/context-persistence/pom.xml
new file mode 100644 (file)
index 0000000..ae56b88
--- /dev/null
@@ -0,0 +1,35 @@
+<!--
+  ============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=========================================================
+-->
+<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.plugins.plugins-context</groupId>
+        <artifactId>plugins-context</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-persistence</groupId>
+    <artifactId>context-persistence</artifactId>
+    <packaging>pom</packaging>
+
+    <name>${project.artifactId}</name>
+    <description>Plugins for 3pps that persist context</description>
+</project>
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/pom.xml b/plugins/plugins-context/context-schema/context-schema-avro/pom.xml
new file mode 100644 (file)
index 0000000..3726867
--- /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=========================================================
+-->
+<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.plugins.plugins-context.context-schema</groupId>
+        <artifactId>context-schema</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>context-schema-avro</artifactId>
+    <name>${project.artifactId}</name>
+    <description>[${project.parent.artifactId}] Plugin for schemas using Avro</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.avro</groupId>
+            <artifactId>avro</artifactId>
+            <version>1.8.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.model</groupId>
+            <artifactId>policy-model</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroArrayObjectMapper.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroArrayObjectMapper.java
new file mode 100644 (file)
index 0000000..56d8425
--- /dev/null
@@ -0,0 +1,44 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData.Array;
+
+/**
+ * Object mapper for arrays, uses default behaviour except for a specific default constructor
+ * implementation.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class AvroArrayObjectMapper extends AvroDirectObjectMapper {
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#createNewinstance(org.
+     * apache.avro.Schema)
+     */
+    @SuppressWarnings("rawtypes")
+    @Override
+    public Object createNewInstance(final Schema avroSchema) {
+        return new Array(0, avroSchema);
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroBytesObjectMapper.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroBytesObjectMapper.java
new file mode 100644 (file)
index 0000000..dc281a5
--- /dev/null
@@ -0,0 +1,149 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import java.nio.ByteBuffer;
+
+import org.apache.avro.Schema;
+import org.apache.avro.Schema.Type;
+import org.onap.policy.apex.context.ContextRuntimeException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This class does string mapping from the Avro BYTES type to a Java byte array.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class AvroBytesObjectMapper implements AvroObjectMapper {
+    // Get a reference to the logger
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(AvroBytesObjectMapper.class);
+
+    // The user keyAvro type for direct mapping
+    private AxKey userKey;
+    private Type avroType;
+
+    // The Apex compatible class
+    private final Class<Byte[]> schemaClass = Byte[].class;
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#getJavaClass()
+     */
+    @Override
+    public Class<?> getJavaClass() {
+        return schemaClass;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#setAvroType(org.apache.
+     * avro. Schema.Type)
+     */
+    @Override
+    public void init(final AxKey intUserKey, final Type initAvroType) {
+        this.userKey = intUserKey;
+        this.avroType = initAvroType;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#createNewinstance(org.
+     * apache. avro.Schema)
+     */
+    @Override
+    public Object createNewInstance(final Schema avroSchema) {
+        // By default, we do not create an instance, normal Java object creation for byte arrays is
+        // sufficient
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#getAvroType()
+     */
+    @Override
+    public Type getAvroType() {
+        return avroType;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#mapFromAvro(java.lang.
+     * Object)
+     */
+    @Override
+    public Object mapFromAvro(final Object avroObject) {
+        // The Avro object should be a Utf8 object
+        if (!(avroObject instanceof ByteBuffer)) {
+            final String returnString =
+                    userKey.getID() + ": object \"" + avroObject + "\" of class \"" + avroObject.getClass()
+                            + "\" cannot be decoded to an object of class \"" + schemaClass.getCanonicalName() + "\"";
+            LOGGER.warn(returnString);
+            throw new ContextRuntimeException(returnString);
+        }
+
+        // Cast the byte buffer object so we get access to its methods
+        final ByteBuffer byteBufferAvroObject = (ByteBuffer) avroObject;
+
+        // read the byte buffer into a byte array
+        final byte[] byteArray = new byte[byteBufferAvroObject.remaining()];
+        byteBufferAvroObject.get(byteArray);
+
+        return byteArray;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#mapToAvro(java.lang.Object)
+     */
+    @Override
+    public Object mapToAvro(final Object object) {
+        if (object == null) {
+            final String returnString = userKey.getID() + ": cannot encode a null object of class \""
+                    + schemaClass.getCanonicalName() + "\"";
+            LOGGER.warn(returnString);
+            throw new ContextRuntimeException(returnString);
+        }
+
+        // The incoming object should be a byte array
+        if (!(object instanceof byte[])) {
+            final String returnString = userKey.getID() + ": object \"" + object + "\" of class \"" + object.getClass()
+                    + "\" cannot be decoded to an object of class \"" + schemaClass.getCanonicalName() + "\"";
+            LOGGER.warn(returnString);
+            throw new ContextRuntimeException(returnString);
+        }
+
+        // Create a ByteBuffer object to serialize the bytes
+        final ByteBuffer byteBuffer = ByteBuffer.wrap((byte[]) object);
+
+        return byteBuffer;
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroDirectObjectMapper.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroDirectObjectMapper.java
new file mode 100644 (file)
index 0000000..acf64c3
--- /dev/null
@@ -0,0 +1,165 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.avro.Schema;
+import org.apache.avro.Schema.Type;
+import org.apache.avro.generic.GenericData;
+import org.onap.policy.apex.context.ContextRuntimeException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This class does direct mapping from Avro classes to Java classes, used for Avro primitive types
+ * that directly produce Java objects.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class AvroDirectObjectMapper implements AvroObjectMapper {
+    // Get a reference to the logger
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(AvroDirectObjectMapper.class);
+
+    // Map for Avro primitive types to Java primitive types
+    private static final Map<Schema.Type, Class<?>> AVRO_JAVA_TYPE_MAP = new TreeMap<>();
+
+    // @formatter:off
+    // Initialize the mapping
+    static {
+        AVRO_JAVA_TYPE_MAP.put(Schema.Type.ARRAY,   GenericData.Array.class);
+        AVRO_JAVA_TYPE_MAP.put(Schema.Type.BOOLEAN, Boolean.class);
+        AVRO_JAVA_TYPE_MAP.put(Schema.Type.DOUBLE,  Double.class);
+        AVRO_JAVA_TYPE_MAP.put(Schema.Type.ENUM,    GenericData.EnumSymbol.class);
+        AVRO_JAVA_TYPE_MAP.put(Schema.Type.FIXED,   GenericData.Fixed.class);
+        AVRO_JAVA_TYPE_MAP.put(Schema.Type.FLOAT,   Float.class);
+        AVRO_JAVA_TYPE_MAP.put(Schema.Type.INT,     Integer.class);
+        AVRO_JAVA_TYPE_MAP.put(Schema.Type.LONG,    Long.class);
+        AVRO_JAVA_TYPE_MAP.put(Schema.Type.MAP,     HashMap.class);
+        AVRO_JAVA_TYPE_MAP.put(Schema.Type.NULL,    null);
+        AVRO_JAVA_TYPE_MAP.put(Schema.Type.RECORD,  GenericData.Record.class);
+    }
+    // @formatter:on
+
+    // The user keyAvro type for direct mapping
+    private AxKey userKey;
+    private Type avroType;
+
+    // The Apex compatible class
+    private Class<?> schemaClass;
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#getJavaClass()
+     */
+    @Override
+    public Class<?> getJavaClass() {
+        return schemaClass;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#setAvroType(org.apache.
+     * avro. Schema.Type)
+     */
+    @Override
+    public void init(final AxKey initUserKey, final Type initAvroType) {
+        this.userKey = initUserKey;
+        this.avroType = initAvroType;
+        schemaClass = AVRO_JAVA_TYPE_MAP.get(avroType);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#createNewinstance(org.
+     * apache. avro.Schema)
+     */
+    @Override
+    public Object createNewInstance(final Schema avroSchema) {
+        // By default, we do not create an instance, normal Java object creation is sufficient
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#getAvroType()
+     */
+    @Override
+    public Type getAvroType() {
+        return avroType;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#mapFromAvro(java.lang.
+     * Object)
+     */
+    @Override
+    public Object mapFromAvro(final Object avroObject) {
+        // Always return null if the schema is a null schema
+        if (schemaClass == null) {
+            return null;
+        }
+
+        // It is legal for the schema class to be null, if the Avro schema has a "null" type then
+        // the decoded object is always returned as a null
+        if (!schemaClass.isAssignableFrom(avroObject.getClass())) {
+            final String returnString =
+                    userKey.getID() + ": object \"" + avroObject + "\" of class \"" + avroObject.getClass()
+                            + "\" cannot be decoded to an object of class \"" + schemaClass.getCanonicalName() + "\"";
+            LOGGER.warn(returnString);
+            throw new ContextRuntimeException(returnString);
+        }
+
+        return avroObject;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#mapToAvro(java.lang.Object)
+     */
+    @Override
+    public Object mapToAvro(final Object object) {
+        // Null values are only allowed if the schema class is null
+        if (object == null) {
+            if (schemaClass != null) {
+                final String returnString = userKey.getID() + ": cannot encode a null object of class \""
+                        + schemaClass.getCanonicalName() + "\"";
+                LOGGER.warn(returnString);
+                throw new ContextRuntimeException(returnString);
+            }
+        }
+
+        // For direct mappings, just work directly with the Java objects
+        return object;
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroEnumObjectMapper.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroEnumObjectMapper.java
new file mode 100644 (file)
index 0000000..ec84450
--- /dev/null
@@ -0,0 +1,53 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import java.util.List;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData.EnumSymbol;
+
+/**
+ * Object mapper for enums, uses default behaviour except for a specific default constructor
+ * implementation.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class AvroEnumObjectMapper extends AvroDirectObjectMapper {
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#createNewinstance(org.
+     * apache.avro.Schema)
+     */
+    @Override
+    public Object createNewInstance(final Schema avroSchema) {
+        // Initialize the ENUM to the first ENUM symbol on the list
+        final List<String> enumSymbols = avroSchema.getEnumSymbols();
+
+        // Check if any ENUM symbols have been defined
+        if (enumSymbols == null || enumSymbols.isEmpty()) {
+            return null;
+        }
+
+        return new EnumSymbol(avroSchema, enumSymbols.get(0));
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroNullableMapper.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroNullableMapper.java
new file mode 100644 (file)
index 0000000..ff8806c
--- /dev/null
@@ -0,0 +1,124 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import org.apache.avro.Schema;
+import org.apache.avro.Schema.Type;
+
+import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+
+/**
+ * The Class AvroNullableMapper handles Avro null mappings to Java null values.
+ *
+ * @author John Keeney (john.keeney@ericsson.com)
+ */
+public class AvroNullableMapper extends AvroDirectObjectMapper {
+    // The wrapped mapper for nullables
+    private final AvroObjectMapper wrappedMapper;
+
+    /**
+     * The Constructor.
+     *
+     * @param wrappedMapper the wrapped mapper
+     */
+    public AvroNullableMapper(final AvroObjectMapper wrappedMapper) {
+        this.wrappedMapper = wrappedMapper;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroDirectObjectMapper#getJavaClass()
+     */
+    @Override
+    public Class<?> getJavaClass() {
+        return wrappedMapper.getJavaClass();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.plugins.context.schema.avro.AvroDirectObjectMapper#init(org.onap.policy.
+     * apex. model.basicmodel.concepts.AxKey, org.apache.avro.Schema.Type)
+     */
+    @Override
+    public void init(final AxKey userKey, final Type avroType) {
+        wrappedMapper.init(userKey, avroType);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.plugins.context.schema.avro.AvroDirectObjectMapper#createNewInstance(
+     * org. apache.avro.Schema)
+     */
+    @Override
+    public Object createNewInstance(final Schema avroSchema) {
+        return wrappedMapper.createNewInstance(avroSchema);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroDirectObjectMapper#getAvroType()
+     */
+    @Override
+    public Type getAvroType() {
+        return Schema.Type.UNION;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.plugins.context.schema.avro.AvroDirectObjectMapper#mapFromAvro(java.
+     * lang. Object)
+     */
+    @Override
+    public Object mapFromAvro(final Object avroObject) {
+        if (avroObject == null) {
+            return null;
+        } else {
+            return wrappedMapper.mapFromAvro(avroObject);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.plugins.context.schema.avro.AvroDirectObjectMapper#mapToAvro(java.lang.
+     * Object)
+     */
+    @Override
+    public Object mapToAvro(final Object object) {
+        if (object == null) {
+            return null;
+        } else {
+            throw new ApexRuntimeException("Unions/Nullable is not supported in output event ... Coming soon!");
+        }
+
+    }
+
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapper.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapper.java
new file mode 100644 (file)
index 0000000..77de592
--- /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.plugins.context.schema.avro;
+
+import org.apache.avro.Schema;
+import org.apache.avro.Schema.Type;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+
+/**
+ * This interface is used to allow mapping of Avro object to and from Java objects.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public interface AvroObjectMapper {
+    /**
+     * Get the Java class produced and consumed by this mapper.
+     *
+     * @return the Java class
+     */
+    Class<?> getJavaClass();
+
+    /**
+     * Initialize the mapper is working with.
+     *
+     * @param userKey the user key
+     * @param avroType the avro type
+     */
+    void init(AxKey userKey, Type avroType);
+
+    /**
+     * Create a new instance of the java object the Avro schema maps to.
+     *
+     * @param avroSchema the Avro schema to use to create the new instance
+     * @return a new instance of the object
+     */
+    Object createNewInstance(Schema avroSchema);
+
+    /**
+     * Set the Avro type the mapper is working with.
+     *
+     * @return the avro type
+     */
+    Type getAvroType();
+
+    /**
+     * Map the Avro object to an object Apex can handler.
+     *
+     * @param avroObject the Avro object to map
+     * @return the Apex-compatible object
+     */
+    Object mapFromAvro(Object avroObject);
+
+    /**
+     * Map the Apex object to an Avro object.
+     *
+     * @param object the Apex-compatible object
+     * @return the Avro object
+     */
+    Object mapToAvro(Object object);
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapperFactory.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapperFactory.java
new file mode 100644 (file)
index 0000000..dd55f44
--- /dev/null
@@ -0,0 +1,131 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.avro.Schema;
+import org.onap.policy.apex.context.ContextRuntimeException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This class maps between Avro types to Java types. This class is thread safe.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class AvroObjectMapperFactory {
+    // Get a reference to the logger
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(AvroObjectMapperFactory.class);
+
+    // Map for Avro primitive types to Java primitive types
+    private static final Map<Schema.Type, Class<? extends AvroObjectMapper>> AVRO_OBJECT_MAPPER_MAP = new TreeMap<>();
+
+    // @formatter:off
+    // Initialize the mapping
+    static {
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.ARRAY, AvroArrayObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.BOOLEAN, AvroDirectObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.BYTES, AvroBytesObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.DOUBLE, AvroDirectObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.ENUM, AvroEnumObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.FIXED, AvroDirectObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.FLOAT, AvroDirectObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.INT, AvroDirectObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.LONG, AvroDirectObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.MAP, AvroDirectObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.NULL, AvroDirectObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.RECORD, AvroRecordObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.STRING, AvroStringObjectMapper.class);
+        AVRO_OBJECT_MAPPER_MAP.put(Schema.Type.UNION, null);
+    }
+    // @formatter:on
+
+    /**
+     * Gets the Avro object mapper to use for an artifact with the given key and schema.
+     *
+     * @param userKey the key of the artifact
+     * @param incomingSchema the incoming schema
+     * @return the avro object mapper
+     */
+    public AvroObjectMapper get(final AxKey userKey, final Schema incomingSchema) {
+        Schema schema = incomingSchema;
+        boolean isnullable = false;
+        if (Schema.Type.UNION.equals(schema.getType())) {
+
+            final List<Schema> types = schema.getTypes();
+            // TODO: properly support UNIONS
+            // currently only support unions with 2 types, one of which is NULL
+            final Schema nullschema = Schema.create(Schema.Type.NULL);
+            if (types.size() != 2 || !types.contains(nullschema)) {
+                final String resultSting = userKey.getID()
+                        + ": Apex currently only supports UNION schemas with 2 options, one must be NULL";
+                LOGGER.warn(resultSting);
+                throw new ContextRuntimeException(resultSting);
+            }
+            isnullable = true;
+            // get the non-null schema given for the union so it can be wrapped
+            schema = types.get(0);
+            if (Schema.Type.NULL.equals(schema.getType())) {
+                schema = types.get(1);
+            }
+            if (Schema.Type.NULL.equals(schema.getType()) || Schema.Type.NULL.equals(schema.getType())) {
+                final String resultSting = userKey.getID()
+                        + ": Apex currently only supports UNION schema2 with 2 options, only one can be NULL, and the other cannot be another UNION";
+                LOGGER.warn(resultSting);
+                throw new ContextRuntimeException(resultSting);
+            }
+        }
+
+        final Schema.Type avroType = schema.getType();
+
+        // Check that there is a definition for the mapper for this type
+        if (!AVRO_OBJECT_MAPPER_MAP.containsKey(avroType) || AVRO_OBJECT_MAPPER_MAP.get(avroType) == null) {
+            final String resultSting =
+                    userKey.getID() + ": no Avro object mapper defined for Avro type \"" + avroType + "\"";
+            LOGGER.warn(resultSting);
+            throw new ContextRuntimeException(resultSting);
+        }
+
+        // Create a mapper
+        AvroObjectMapper avroObjectMapper;
+        try {
+            avroObjectMapper = AVRO_OBJECT_MAPPER_MAP.get(avroType).newInstance();
+            if (isnullable) {
+                avroObjectMapper = new AvroNullableMapper(avroObjectMapper);
+            }
+
+        } catch (final Exception e) {
+            final String resultSting = userKey.getID() + ": could not create an Avro object mapper of type \""
+                    + AVRO_OBJECT_MAPPER_MAP.get(avroType) + "\" for Avro type \"" + avroType + "\" : " + e;
+            LOGGER.warn(resultSting, e);
+            throw new ContextRuntimeException(resultSting, e);
+        }
+
+        // Set the type and return
+        avroObjectMapper.init(userKey, avroType);
+
+        return avroObjectMapper;
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroRecordObjectMapper.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroRecordObjectMapper.java
new file mode 100644 (file)
index 0000000..9d24a9a
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData.Record;
+
+/**
+ * Object mapper for records, uses default behaviour except for a specific default constructor
+ * implementation.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class AvroRecordObjectMapper extends AvroDirectObjectMapper {
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#createNewinstance(org.
+     * apache. avro.Schema)
+     */
+    @Override
+    public Object createNewInstance(final Schema avroSchema) {
+        return new Record(avroSchema);
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelper.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelper.java
new file mode 100644 (file)
index 0000000..2543dd1
--- /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.plugins.context.schema.avro;
+
+import java.io.ByteArrayOutputStream;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericDatumReader;
+import org.apache.avro.generic.GenericDatumWriter;
+import org.apache.avro.generic.GenericRecord;
+import org.apache.avro.io.DatumWriter;
+import org.apache.avro.io.DecoderFactory;
+import org.apache.avro.io.EncoderFactory;
+import org.apache.avro.io.JsonDecoder;
+import org.apache.avro.io.JsonEncoder;
+import org.onap.policy.apex.context.ContextRuntimeException;
+import org.onap.policy.apex.context.impl.schema.AbstractSchemaHelper;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+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;
+
+/**
+ * This class is the implementation of the {@link org.onap.policy.apex.context.SchemaHelper}
+ * interface for Avro schemas.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class AvroSchemaHelper extends AbstractSchemaHelper {
+    // Get a reference to the logger
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(AvroSchemaHelper.class);
+
+    // The Avro schema for this context schema
+    private Schema avroSchema;
+
+    // The mapper that translates between Java and Avro objects
+    private AvroObjectMapper avroObjectMapper;
+
+    @Override
+    public void init(final AxKey userKey, final AxContextSchema schema) throws ContextRuntimeException {
+        super.init(userKey, schema);
+
+        // Configure the Avro schema
+        try {
+            avroSchema = new Schema.Parser().parse(schema.getSchema());
+        } catch (final Exception e) {
+            final String resultSting = userKey.getID() + ": avro context schema \"" + schema.getID()
+                    + "\" schema is invalid: " + e.getMessage() + ", schema: " + schema.getSchema();
+            LOGGER.warn(resultSting);
+            throw new ContextRuntimeException(resultSting);
+        }
+
+        // Get the object mapper for the schema type to a Java class
+        avroObjectMapper = new AvroObjectMapperFactory().get(userKey, avroSchema);
+
+        // Get the Java type for this schema, if it is a primitive type then we can do direct
+        // conversion to JAva
+        setSchemaClass(avroObjectMapper.getJavaClass());
+    }
+
+    /**
+     * Getter to get the Avro schema.
+     *
+     * @return the Avro schema
+     */
+    public Schema getAvroSchema() {
+        return avroSchema;
+    }
+
+    @Override
+    public Object getSchemaObject() {
+        return avroSchema;
+    }
+
+    @Override
+    public Object createNewInstance() {
+        // Create a new instance using the Avro object mapper
+        final Object newInstance = avroObjectMapper.createNewInstance(avroSchema);
+
+        // If no new instance is created, use default schema handler behavior
+        if (newInstance != null) {
+            return newInstance;
+        } else {
+            return super.createNewInstance();
+        }
+    }
+
+    @Override
+    public Object createNewInstance(final String stringValue) {
+        return unmarshal(stringValue);
+    }
+
+    @Override
+    public Object createNewInstance(final JsonElement jsonElement) {
+        final Gson gson = new GsonBuilder().serializeNulls().create();
+        final String elementJsonString = gson.toJson(jsonElement);
+
+        return createNewInstance(elementJsonString);
+    }
+
+    @Override
+    public Object unmarshal(final Object object) {
+        // If an object is already in the correct format, just carry on
+        if (passThroughObject(object)) {
+            return object;
+        }
+
+        // Check that the incoming object is a string, the incoming object must be a string
+        // containing Json
+        String objectString;
+        try {
+            if (object == null) {
+                objectString = null;
+            }
+            if (object != null && avroSchema.getType().equals(Schema.Type.STRING)) {
+                objectString = object.toString().trim();
+                if (objectString.length() == 0) {
+                    objectString = "\"\"";
+                } else if (objectString.length() == 1) {
+                    objectString = "\"" + objectString + "\"";
+                } else {
+                    // All strings must be quoted for decoding
+                    if (objectString.charAt(0) != '"') {
+                        objectString = '"' + objectString;
+                    }
+                    if (objectString.charAt(objectString.length() - 1) != '"') {
+                        objectString += '"';
+                    }
+                }
+            } else {
+                objectString = (String) object;
+            }
+        } catch (final ClassCastException e) {
+            final String returnString = getUserKey().getID() + ": object \"" + object.toString() + "\" of type \""
+                    + object.getClass().getCanonicalName() + "\" must be assignable to \""
+                    + getSchemaClass().getCanonicalName()
+                    + "\" or be a Json string representation of it for Avro unmarshalling";
+            LOGGER.warn(returnString);
+            throw new ContextRuntimeException(returnString);
+        }
+
+        // Translate illegal characters in incoming JSON keys to legal Avro values
+        objectString = AvroSchemaKeyTranslationUtilities.translateIllegalKeys(objectString, false);
+
+        // Decode the object
+        Object decodedObject;
+        try {
+            final JsonDecoder jsonDecoder = DecoderFactory.get().jsonDecoder(avroSchema, objectString);
+            decodedObject = new GenericDatumReader<GenericRecord>(avroSchema).read(null, jsonDecoder);
+        } catch (final Exception e) {
+            final String returnString = getUserKey().getID() + ": object \"" + objectString
+                    + "\" Avro unmarshalling failed: " + e.getMessage();
+            LOGGER.warn(returnString, e);
+            throw new ContextRuntimeException(returnString, e);
+        }
+
+        // Now map the decoded object into something we can handle
+        return avroObjectMapper.mapFromAvro(decodedObject);
+    }
+
+    @Override
+    public String marshal2Json(final Object object) {
+        // Condition the object for Avro encoding
+        final Object conditionedObject = avroObjectMapper.mapToAvro(object);
+
+        final ByteArrayOutputStream output = new ByteArrayOutputStream();
+        try {
+            final DatumWriter<Object> writer = new GenericDatumWriter<>(avroSchema);
+            final JsonEncoder jsonEncoder = EncoderFactory.get().jsonEncoder(avroSchema, output, true);
+            writer.write(conditionedObject, jsonEncoder);
+            jsonEncoder.flush();
+            output.close();
+        } catch (final Exception e) {
+            final String returnString =
+                    getUserKey().getID() + ": object \"" + object + "\" Avro marshalling failed: " + e.getMessage();
+            LOGGER.warn(returnString);
+            throw new ContextRuntimeException(returnString, e);
+        }
+
+        return AvroSchemaKeyTranslationUtilities.translateIllegalKeys(new String(output.toByteArray()), true);
+    }
+
+    @Override
+    public JsonElement marshal2JsonElement(final Object schemaObject) {
+        // Get the object as a Json string
+        final String schemaObjectAsString = marshal2Json(schemaObject);
+
+        // Get a Gson instance to convert the Json string to an object created by Json
+        final Gson gson = new Gson();
+
+        // Convert the Json string into an object
+        final Object schemaObjectAsObject = gson.fromJson(schemaObjectAsString, Object.class);
+
+        return gson.toJsonTree(schemaObjectAsObject);
+    }
+
+    /**
+     * Check if we can pass this object straight through encoding or decoding, is it an object
+     * native to the schema.
+     *
+     * @param object the object to check
+     * @return true if it's a straight pass through
+     */
+    private boolean passThroughObject(final Object object) {
+        if (object == null || getSchemaClass() == null) {
+            return false;
+        }
+
+        // All strings must be mapped
+        if (object instanceof String) {
+            return false;
+        }
+
+        // Now, check if the object is native
+        return getSchemaClass().isAssignableFrom(object.getClass());
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelperParameters.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelperParameters.java
new file mode 100644 (file)
index 0000000..5a8fac4
--- /dev/null
@@ -0,0 +1,38 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import org.onap.policy.apex.context.parameters.SchemaHelperParameters;
+
+/**
+ * Schema helper parameter class for the Avro schema helper.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class AvroSchemaHelperParameters extends SchemaHelperParameters {
+    /**
+     * The Default Constructor sets the {@link AvroSchemaHelper} as the schema helper class for Avro
+     * schemas.
+     */
+    public AvroSchemaHelperParameters() {
+        this.setSchemaHelperPluginClass(AvroSchemaHelper.class.getCanonicalName());
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaKeyTranslationUtilities.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaKeyTranslationUtilities.java
new file mode 100644 (file)
index 0000000..dc3770a
--- /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.plugins.context.schema.avro;
+
+import java.util.Map.Entry;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+/**
+ * This static final class contains utility methods for Avro schemas.
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public final class AvroSchemaKeyTranslationUtilities {
+    // Constants for key replacements
+    private static final String DOT_STRING = "\\.";
+    private static final String DOT_STRING_REPLACEMENT = "_DoT_";
+    private static final String DASH_STRING = "-";
+    private static final String DASH_STRING_REPLACEMENT = "_DasH_";
+
+    /**
+     * Default constructor to avoid subclassing.
+     */
+    private AvroSchemaKeyTranslationUtilities() {}
+
+    /**
+     * Translate characters in JSON keys to values that are legal in Avro. Avro names must start
+     * with [A-Za-z_] and subsequently contain only [A-Za-z0-9_]
+     *
+     * @param jsonString The JSON string to translate
+     * @param revert True if we want to revert the field names to their original values
+     * @return the translated JSON string
+     */
+    public static String translateIllegalKeys(final String jsonString, final boolean revert) {
+        if (jsonString == null) {
+            return jsonString;
+        }
+
+        // Create a JSON element for the incoming JSON string
+        final JsonElement jsonElement =
+                new GsonBuilder().serializeNulls().create().fromJson(jsonString, JsonElement.class);
+
+        final JsonElement translatedJsonElement = translateIllegalKeys(jsonElement, revert);
+
+        return new GsonBuilder().serializeNulls().create().toJson(translatedJsonElement);
+    }
+
+    /**
+     * Translate characters in JSON keys to values that are legal in Avro. Avro names must start
+     * with [A-Za-z_] and subsequently contain only [A-Za-z0-9_]
+     *
+     * @param jsonElement The JSON element to translate
+     * @param revert True if we want to revert the field names to their original values
+     * @return the translated JSON element
+     */
+    public static JsonElement translateIllegalKeys(final JsonElement jsonElement, final boolean revert) {
+        // We only act on JSON objects and arrays
+        if (jsonElement.isJsonObject()) {
+            return translateIllegalKeys(jsonElement.getAsJsonObject(), revert);
+        } else if (jsonElement.isJsonArray()) {
+            return translateIllegalKeys(jsonElement.getAsJsonArray(), revert);
+        } else {
+            return jsonElement;
+        }
+    }
+
+    /**
+     * Translate characters in JSON keys to values that are legal in Avro. Avro names must start
+     * with [A-Za-z_] and subsequently contain only [A-Za-z0-9_]
+     *
+     * @param jsonObject The JSON object to translate
+     * @param revert True if we want to revert the field names to their original values
+     * @return the translated JSON element
+     */
+    public static JsonElement translateIllegalKeys(final JsonObject jsonObject, final boolean revert) {
+        final JsonObject newJsonObject = new JsonObject();
+
+        for (final Entry<String, JsonElement> jsonObjectEntry : jsonObject.entrySet()) {
+            newJsonObject.add(translateIllegalKey(jsonObjectEntry.getKey(), revert),
+                    translateIllegalKeys(jsonObjectEntry.getValue(), revert));
+        }
+
+        return newJsonObject;
+    }
+
+    /**
+     * Translate characters in JSON keys to values that are legal in Avro. Avro names must start
+     * with [A-Za-z_] and subsequently contain only [A-Za-z0-9_]
+     *
+     * @param jsonArray The JSON array to translate
+     * @param revert True if we want to revert the field names to their original values
+     * @return the translated JSON element
+     */
+    public static JsonElement translateIllegalKeys(final JsonArray jsonArray, final boolean revert) {
+        final JsonArray newJsonArray = new JsonArray();
+
+        for (int i = 0; i < jsonArray.size(); i++) {
+            newJsonArray.add(translateIllegalKeys(jsonArray.get(i), revert));
+        }
+
+        return newJsonArray;
+    }
+
+    /**
+     * Translate characters in a single JSON key to values that are legal in Avro. Avro names must
+     * start with [A-Za-z_] and subsequently contain only [A-Za-z0-9_]
+     *
+     * @param key The key to translate
+     * @param revert True if we want to revert the field names to their original values
+     * @return the translated key
+     */
+    private static String translateIllegalKey(final String key, final boolean revert) {
+        if (revert) {
+            return key.replaceAll(DOT_STRING_REPLACEMENT, DOT_STRING).replaceAll(DASH_STRING_REPLACEMENT, DASH_STRING);
+        } else {
+            return key.replaceAll(DOT_STRING, DOT_STRING_REPLACEMENT).replaceAll(DASH_STRING, DASH_STRING_REPLACEMENT);
+        }
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroStringObjectMapper.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroStringObjectMapper.java
new file mode 100644 (file)
index 0000000..cb3625f
--- /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.plugins.context.schema.avro;
+
+import org.apache.avro.Schema;
+import org.apache.avro.Schema.Type;
+import org.apache.avro.util.Utf8;
+import org.onap.policy.apex.context.ContextRuntimeException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * This class does string mapping from the Avro Utf8 class to the Java String class.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class AvroStringObjectMapper implements AvroObjectMapper {
+    // Get a reference to the logger
+    private static final XLogger LOGGER = XLoggerFactory.getXLogger(AvroStringObjectMapper.class);
+
+    // The user keyAvro type for direct mapping
+    private AxKey userKey;
+    private Type avroType;
+
+    // The Apex compatible class
+    private final Class<String> schemaClass = String.class;
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#getJavaClass()
+     */
+    @Override
+    public Class<?> getJavaClass() {
+        return schemaClass;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#setAvroType(org.apache.
+     * avro. Schema.Type)
+     */
+    @Override
+    public void init(final AxKey initUserKey, final Type initAvroType) {
+        this.userKey = initUserKey;
+        this.avroType = initAvroType;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#createNewinstance(org.
+     * apache. avro.Schema)
+     */
+    @Override
+    public Object createNewInstance(final Schema avroSchema) {
+        // By default, we do not create an instance, normal Java object creation for strings is
+        // sufficient
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#getAvroType()
+     */
+    @Override
+    public Type getAvroType() {
+        return avroType;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#mapFromAvro(java.lang.
+     * Object)
+     */
+    @Override
+    public Object mapFromAvro(final Object avroObject) {
+        // The Avro object should be a Utf8 object
+        if (!(avroObject instanceof Utf8)) {
+            final String returnString =
+                    userKey.getID() + ": object \"" + avroObject + "\" of class \"" + avroObject.getClass()
+                            + "\" cannot be decoded to an object of class \"" + schemaClass.getCanonicalName() + "\"";
+            LOGGER.warn(returnString);
+            throw new ContextRuntimeException(returnString);
+        }
+
+        return avroObject.toString();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.onap.policy.apex.plugins.context.schema.avro.AvroObjectMapper#mapToAvro(java.lang.Object)
+     */
+    @Override
+    public Object mapToAvro(final Object object) {
+        if (object == null) {
+            final String returnString = userKey.getID() + ": cannot encode a null object of class \""
+                    + schemaClass.getCanonicalName() + "\"";
+            LOGGER.warn(returnString);
+            throw new ContextRuntimeException(returnString);
+        }
+
+        return object;
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/package-info.java b/plugins/plugins-context/context-schema/context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/package-info.java
new file mode 100644 (file)
index 0000000..93f4943
--- /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 <a href="https://avro.apache.org/">Avro</a> schem handling for use in event fields and
+ * context albums in APEX.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.plugins.context.schema.avro;
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaAAI.java b/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaAAI.java
new file mode 100644 (file)
index 0000000..65eef39
--- /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.plugins.context.schema.avro;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.avro.generic.GenericData.Array;
+import org.apache.avro.generic.GenericRecord;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+import org.onap.policy.apex.model.utilities.TextFileUtils;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @version
+ */
+public class TestAvroSchemaAAI {
+    private final AxKey testKey = new AxArtifactKey("AvroTest", "0.0.1");
+    private AxContextSchemas schemas;
+    private String aaiInventoryResponseSchema;
+
+    @Before
+    public void initTest() throws IOException {
+        schemas = new AxContextSchemas(new AxArtifactKey("AvroSchemas", "0.0.1"));
+        ModelService.registerModel(AxContextSchemas.class, schemas);
+        new SchemaParameters().getSchemaHelperParameterMap().put("Avro", new AvroSchemaHelperParameters());
+        aaiInventoryResponseSchema =
+                TextFileUtils.getTextFileAsString("src/test/resources/avsc/AAIInventoryResponseItemType.avsc");
+    }
+
+    @Test
+    public void testAAIResponsePolicy() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", aaiInventoryResponseSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        final Array<?> newArrayEmpty = (Array<?>) schemaHelper.createNewInstance();
+        assertEquals(0, newArrayEmpty.size());
+
+        final String inString = TextFileUtils.getTextFileAsString("src/test/resources/data/AAIResponse4Policy.json");
+        final Array<?> newArrayFull = (Array<?>) schemaHelper.createNewInstance(inString);
+        final String vnfName = ((GenericRecord) ((GenericRecord) newArrayFull.get(0)).get("generic_DasH_vnf"))
+                .get("vnf_DasH_name").toString();
+        assertEquals("ZRDM2MMEX39", vnfName);
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaArray.java b/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaArray.java
new file mode 100644 (file)
index 0000000..dc65c10
--- /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.plugins.context.schema.avro;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.avro.generic.GenericData.Array;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+import org.onap.policy.apex.model.utilities.TextFileUtils;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @version
+ */
+public class TestAvroSchemaArray {
+    private final AxKey testKey = new AxArtifactKey("AvroTest", "0.0.1");
+    private AxContextSchemas schemas;
+    private String longArraySchema;
+    private String addressArraySchema;
+
+    @Before
+    public void initTest() throws IOException {
+        schemas = new AxContextSchemas(new AxArtifactKey("AvroSchemas", "0.0.1"));
+        ModelService.registerModel(AxContextSchemas.class, schemas);
+        new SchemaParameters().getSchemaHelperParameterMap().put("Avro", new AvroSchemaHelperParameters());
+        longArraySchema = TextFileUtils.getTextFileAsString("src/test/resources/avsc/ArrayExampleLong.avsc");
+        addressArraySchema = TextFileUtils.getTextFileAsString("src/test/resources/avsc/ArrayExampleAddress.avsc");
+    }
+
+    @Test
+    public void testArrayInit() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", addressArraySchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        final Array<?> newArrayEmpty = (Array<?>) schemaHelper.createNewInstance();
+        assertEquals(0, newArrayEmpty.size());
+
+        final String inString =
+                TextFileUtils.getTextFileAsString("src/test/resources/data/ArrayExampleAddressFull.json");
+        final Array<?> newArrayFull = (Array<?>) schemaHelper.createNewInstance(inString);
+        assertEquals("{\"streetaddress\": \"1600 Pennsylvania Avenue\", \"city\": \"Washington DC\"}",
+                newArrayFull.get(0).toString());
+    }
+
+    @Test
+    public void testLongArrayUnmarshalMarshal() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroArray", "0.0.1"), "Avro", longArraySchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/ArrayExampleLongNull.json");
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/ArrayExampleLongFull.json");
+    }
+
+    @Test
+    public void testAddressArrayUnmarshalMarshal() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroArray", "0.0.1"), "Avro", addressArraySchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/ArrayExampleAddressNull.json");
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/ArrayExampleAddressFull.json");
+    }
+
+    private void testUnmarshalMarshal(final SchemaHelper schemaHelper, final String fileName) throws IOException {
+        final String inString = TextFileUtils.getTextFileAsString(fileName);
+        final Array<?> schemaObject = (Array<?>) schemaHelper.unmarshal(inString);
+        final String outString = schemaHelper.marshal2Json(schemaObject);
+        assertEquals(inString.replaceAll("\\s+", ""), outString.replaceAll("\\s+", ""));
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaEnum.java b/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaEnum.java
new file mode 100644 (file)
index 0000000..0302345
--- /dev/null
@@ -0,0 +1,120 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+
+import org.apache.avro.generic.GenericData.EnumSymbol;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+import org.onap.policy.apex.model.utilities.TextFileUtils;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @version
+ */
+public class TestAvroSchemaEnum {
+    private final AxKey testKey = new AxArtifactKey("AvroTest", "0.0.1");
+    private AxContextSchemas schemas;
+    private String enumSchema;
+
+    @Before
+    public void initTest() throws IOException {
+        schemas = new AxContextSchemas(new AxArtifactKey("AvroSchemas", "0.0.1"));
+        ModelService.registerModel(AxContextSchemas.class, schemas);
+        new SchemaParameters().getSchemaHelperParameterMap().put("Avro", new AvroSchemaHelperParameters());
+        enumSchema = TextFileUtils.getTextFileAsString("src/test/resources/avsc/EnumSchema.avsc");
+    }
+
+    @Test
+    public void testEnumInit() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", enumSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        final EnumSymbol newEnumEmpty = (EnumSymbol) schemaHelper.createNewInstance();
+        assertEquals("SPADES", newEnumEmpty.toString());
+
+        final EnumSymbol newEnumFull = (EnumSymbol) schemaHelper.createNewInstance("\"HEARTS\"");
+        assertEquals("HEARTS", newEnumFull.toString());
+    }
+
+    @Test
+    public void testEnumUnmarshalMarshal() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroArray", "0.0.1"), "Avro", enumSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/EnumExampleHearts.json");
+
+        try {
+            testUnmarshalMarshal(schemaHelper, "src/test/resources/data/EnumExampleNull.json");
+            fail("This test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("AvroTest:0.0.1: object \"null\" Avro unmarshalling failed: Expected fixed. Got VALUE_NULL",
+                    e.getMessage());
+        }
+        try {
+            testUnmarshalMarshal(schemaHelper, "src/test/resources/data/EnumExampleNull.json");
+            fail("This test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("AvroTest:0.0.1: object \"null\" Avro unmarshalling failed: Expected fixed. Got VALUE_NULL",
+                    e.getMessage());
+        }
+        try {
+            testUnmarshalMarshal(schemaHelper, "src/test/resources/data/EnumExampleBad0.json");
+            fail("This test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("AvroTest:0.0.1: object \"\"TWEED\"\" Avro unmarshalling failed: Unknown symbol in enum TWEED",
+                    e.getMessage());
+        }
+        try {
+            testUnmarshalMarshal(schemaHelper, "src/test/resources/data/EnumExampleBad1.json");
+            fail("This test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "AvroTest:0.0.1: object \"\"Hearts\"\" Avro unmarshalling failed: Unknown symbol in enum Hearts",
+                    e.getMessage());
+        }
+    }
+
+    private void testUnmarshalMarshal(final SchemaHelper schemaHelper, final String fileName) throws IOException {
+        final String inString = TextFileUtils.getTextFileAsString(fileName);
+        final EnumSymbol decodedObject = (EnumSymbol) schemaHelper.unmarshal(inString);
+        final String outString = schemaHelper.marshal2Json(decodedObject);
+        assertEquals(inString.replaceAll("[\\r?\\n]+", " "), outString.replaceAll("[\\r?\\n]+", " "));
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaFixed.java b/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaFixed.java
new file mode 100644 (file)
index 0000000..f4906e5
--- /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.plugins.context.schema.avro;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+
+import org.apache.avro.generic.GenericData.Fixed;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+import org.onap.policy.apex.model.utilities.TextFileUtils;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @version
+ */
+public class TestAvroSchemaFixed {
+    private final AxKey testKey = new AxArtifactKey("AvroTest", "0.0.1");
+    private AxContextSchemas schemas;
+    private String fixedSchema;
+
+    @Before
+    public void initTest() throws IOException {
+        schemas = new AxContextSchemas(new AxArtifactKey("AvroSchemas", "0.0.1"));
+        ModelService.registerModel(AxContextSchemas.class, schemas);
+        new SchemaParameters().getSchemaHelperParameterMap().put("Avro", new AvroSchemaHelperParameters());
+        fixedSchema = TextFileUtils.getTextFileAsString("src/test/resources/avsc/FixedSchema.avsc");
+    }
+
+    @Test
+    public void testFixedInit() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", fixedSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        try {
+            schemaHelper.createNewInstance();
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "AvroTest:0.0.1: could not create an instance of class \"org.apache.avro.generic.GenericData.Fixed\" using the default constructor \"Fixed()\"",
+                    e.getMessage());
+        }
+
+        final String inString = TextFileUtils.getTextFileAsString("src/test/resources/data/FixedExampleGood.json");
+        final Fixed newFixedFull = (Fixed) schemaHelper.createNewInstance(inString);
+        assertTrue(newFixedFull.toString().startsWith("[48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65"));
+        assertTrue(newFixedFull.toString().endsWith("53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70]"));
+    }
+
+    @Test
+    public void testFixedUnmarshalMarshal() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroArray", "0.0.1"), "Avro", fixedSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/FixedExampleGood.json");
+
+        try {
+            testUnmarshalMarshal(schemaHelper, "src/test/resources/data/FixedExampleNull.json");
+            fail("This test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("AvroTest:0.0.1: object \"null\" Avro unmarshalling failed: Expected fixed. Got VALUE_NULL",
+                    e.getMessage());
+        }
+        try {
+            testUnmarshalMarshal(schemaHelper, "src/test/resources/data/FixedExampleNull.json");
+            fail("This test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("AvroTest:0.0.1: object \"null\" Avro unmarshalling failed: Expected fixed. Got VALUE_NULL",
+                    e.getMessage());
+        }
+        try {
+            testUnmarshalMarshal(schemaHelper, "src/test/resources/data/FixedExampleBad0.json");
+            fail("This test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "AvroTest:0.0.1: object \"\"BADBAD\"\" Avro unmarshalling failed: Expected fixed length 64, but got6",
+                    e.getMessage());
+        }
+        try {
+            testUnmarshalMarshal(schemaHelper, "src/test/resources/data/FixedExampleBad1.json");
+            fail("This test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "AvroTest:0.0.1: object \"\"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0\"\" Avro unmarshalling failed: Expected fixed length 64, but got65",
+                    e.getMessage());
+        }
+    }
+
+    private void testUnmarshalMarshal(final SchemaHelper schemaHelper, final String fileName) throws IOException {
+        final String inString = TextFileUtils.getTextFileAsString(fileName);
+        final Fixed decodedObject = (Fixed) schemaHelper.unmarshal(inString);
+        final String outString = schemaHelper.marshal2Json(decodedObject);
+        assertEquals(inString.replaceAll("[\\r?\\n]+", " "), outString.replaceAll("[\\r?\\n]+", " "));
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaHelperBadSchemas.java b/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaHelperBadSchemas.java
new file mode 100644 (file)
index 0000000..1e1a0be
--- /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.plugins.context.schema.avro;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @version
+ */
+public class TestAvroSchemaHelperBadSchemas {
+    private final AxKey testKey = new AxArtifactKey("AvroTest", "0.0.1");
+    private AxContextSchemas schemas;
+
+    @Before
+    public void initTest() {
+        schemas = new AxContextSchemas(new AxArtifactKey("AvroSchemas", "0.0.1"));
+        ModelService.registerModel(AxContextSchemas.class, schemas);
+        new SchemaParameters().getSchemaHelperParameterMap().put("Avro", new AvroSchemaHelperParameters());
+    }
+
+    @Test
+    public void badSchemaTest() {
+        final AxContextSchema avroBadSchema0 = new AxContextSchema(new AxArtifactKey("AvroBad0", "0.0.1"), "Avro", "}");
+        schemas.getSchemasMap().put(avroBadSchema0.getKey(), avroBadSchema0);
+
+        try {
+            new SchemaHelperFactory().createSchemaHelper(testKey, avroBadSchema0.getKey());
+            fail("This test should throw an exception");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage()
+                    .startsWith("AvroTest:0.0.1: avro context schema \"AvroBad0:0.0.1\" schema is invalid"));
+        }
+
+        final AxContextSchema avroBadSchema1 = new AxContextSchema(new AxArtifactKey("AvroBad1", "0.0.1"), "Avro", "");
+        schemas.getSchemasMap().put(avroBadSchema1.getKey(), avroBadSchema1);
+
+        try {
+            new SchemaHelperFactory().createSchemaHelper(testKey, avroBadSchema1.getKey());
+            fail("This test should throw an exception");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage()
+                    .startsWith("AvroTest:0.0.1: avro context schema \"AvroBad1:0.0.1\" schema is invalid"));
+        }
+
+        final AxContextSchema avroBadSchema2 =
+                new AxContextSchema(new AxArtifactKey("AvroBad2", "0.0.1"), "Avro", "{}");
+        schemas.getSchemasMap().put(avroBadSchema2.getKey(), avroBadSchema2);
+
+        try {
+            new SchemaHelperFactory().createSchemaHelper(testKey, avroBadSchema2.getKey());
+            fail("This test should throw an exception");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage()
+                    .startsWith("AvroTest:0.0.1: avro context schema \"AvroBad2:0.0.1\" schema is invalid"));
+        }
+
+        final AxContextSchema avroBadSchema3 =
+                new AxContextSchema(new AxArtifactKey("AvroBad3", "0.0.1"), "Avro", "{zooby}");
+        schemas.getSchemasMap().put(avroBadSchema3.getKey(), avroBadSchema3);
+
+        try {
+            new SchemaHelperFactory().createSchemaHelper(testKey, avroBadSchema3.getKey());
+            fail("This test should throw an exception");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage()
+                    .startsWith("AvroTest:0.0.1: avro context schema \"AvroBad3:0.0.1\" schema is invalid"));
+        }
+
+        final AxContextSchema avroBadSchema4 =
+                new AxContextSchema(new AxArtifactKey("AvroBad4", "0.0.1"), "Avro", "{\"zooby\"}");
+        schemas.getSchemasMap().put(avroBadSchema4.getKey(), avroBadSchema4);
+
+        try {
+            new SchemaHelperFactory().createSchemaHelper(testKey, avroBadSchema4.getKey());
+            fail("This test should throw an exception");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage()
+                    .startsWith("AvroTest:0.0.1: avro context schema \"AvroBad4:0.0.1\" schema is invalid"));
+        }
+
+        final AxContextSchema avroBadSchema5 =
+                new AxContextSchema(new AxArtifactKey("AvroBad5", "0.0.1"), "Avro", "{\"type\": \"zooby\"}");
+        schemas.getSchemasMap().put(avroBadSchema5.getKey(), avroBadSchema5);
+
+        try {
+            new SchemaHelperFactory().createSchemaHelper(testKey, avroBadSchema5.getKey());
+            fail("This test should throw an exception");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage()
+                    .startsWith("AvroTest:0.0.1: avro context schema \"AvroBad5:0.0.1\" schema is invalid"));
+        }
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaHelperMarshal.java b/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaHelperMarshal.java
new file mode 100644 (file)
index 0000000..1b35d82
--- /dev/null
@@ -0,0 +1,277 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @version
+ */
+public class TestAvroSchemaHelperMarshal {
+    private final AxKey testKey = new AxArtifactKey("AvroTest", "0.0.1");
+    private AxContextSchemas schemas;
+
+    @Before
+    public void initTest() {
+        schemas = new AxContextSchemas(new AxArtifactKey("AvroSchemas", "0.0.1"));
+        ModelService.registerModel(AxContextSchemas.class, schemas);
+        new SchemaParameters().getSchemaHelperParameterMap().put("Avro", new AvroSchemaHelperParameters());
+    }
+
+    @Test
+    public void testNullMarshal() {
+        final AxContextSchema avroNullSchema =
+                new AxContextSchema(new AxArtifactKey("AvroNull", "0.0.1"), "Avro", "{\"type\": \"null\"}");
+
+        schemas.getSchemasMap().put(avroNullSchema.getKey(), avroNullSchema);
+        final SchemaHelper schemaHelper0 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroNullSchema.getKey());
+
+        assertEquals("null", schemaHelper0.marshal2Json(null));
+        assertEquals("null", schemaHelper0.marshal2Json(123));
+        assertEquals("null", schemaHelper0.marshal2Json("Everything is marshalled to Null, no matter what it is"));
+    }
+
+    @Test
+    public void testBooleanMarshal() {
+        final AxContextSchema avroBooleanSchema =
+                new AxContextSchema(new AxArtifactKey("AvroBoolean", "0.0.1"), "Avro", "{\"type\": \"boolean\"}");
+
+        schemas.getSchemasMap().put(avroBooleanSchema.getKey(), avroBooleanSchema);
+        final SchemaHelper schemaHelper1 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroBooleanSchema.getKey());
+
+        assertEquals("true", schemaHelper1.marshal2Json(true));
+        assertEquals("false", schemaHelper1.marshal2Json(false));
+        try {
+            schemaHelper1.marshal2Json(0);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            e.printStackTrace();
+            assertEquals(
+                    "AvroTest:0.0.1: object \"0\" Avro marshalling failed: java.lang.Integer cannot be cast to java.lang.Boolean",
+                    e.getMessage());
+        }
+        try {
+            schemaHelper1.marshal2Json("0");
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            e.printStackTrace();
+            assertEquals(
+                    "AvroTest:0.0.1: object \"0\" Avro marshalling failed: java.lang.String cannot be cast to java.lang.Boolean",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void testIntMarshal() {
+        final AxContextSchema avroIntSchema =
+                new AxContextSchema(new AxArtifactKey("AvroInt", "0.0.1"), "Avro", "{\"type\": \"int\"}");
+
+        schemas.getSchemasMap().put(avroIntSchema.getKey(), avroIntSchema);
+        final SchemaHelper schemaHelper2 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroIntSchema.getKey());
+
+        assertEquals("0", schemaHelper2.marshal2Json(0));
+        assertEquals("1", schemaHelper2.marshal2Json(1));
+        assertEquals("-1", schemaHelper2.marshal2Json(-1));
+        assertEquals("1", schemaHelper2.marshal2Json(1.23));
+        assertEquals("-1", schemaHelper2.marshal2Json(-1.23));
+        assertEquals("2147483647", schemaHelper2.marshal2Json(2147483647));
+        assertEquals("-2147483648", schemaHelper2.marshal2Json(-2147483648));
+        try {
+            schemaHelper2.marshal2Json("Hello");
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().startsWith(
+                    "AvroTest:0.0.1: object \"Hello\" Avro marshalling failed: java.lang.String cannot be cast to java.lang.Number"));
+        }
+        try {
+            schemaHelper2.marshal2Json(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage()
+                    .startsWith("AvroTest:0.0.1: cannot encode a null object of class \"java.lang.Integer\""));
+        }
+    }
+
+    @Test
+    public void testLongMarshal() {
+        final AxContextSchema avroLongSchema =
+                new AxContextSchema(new AxArtifactKey("AvroLong", "0.0.1"), "Avro", "{\"type\": \"long\"}");
+
+        schemas.getSchemasMap().put(avroLongSchema.getKey(), avroLongSchema);
+        final SchemaHelper schemaHelper3 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroLongSchema.getKey());
+
+        assertEquals("0", schemaHelper3.marshal2Json(0L));
+        assertEquals("1", schemaHelper3.marshal2Json(1L));
+        assertEquals("-1", schemaHelper3.marshal2Json(-1L));
+        assertEquals("9223372036854775807", schemaHelper3.marshal2Json(9223372036854775807L));
+        assertEquals("-9223372036854775808", schemaHelper3.marshal2Json(-9223372036854775808L));
+        try {
+            schemaHelper3.marshal2Json("Hello");
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().startsWith(
+                    "AvroTest:0.0.1: object \"Hello\" Avro marshalling failed: java.lang.String cannot be cast to java.lang.Long"));
+        }
+        try {
+            schemaHelper3.marshal2Json(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage()
+                    .startsWith("AvroTest:0.0.1: cannot encode a null object of class \"java.lang.Long\""));
+        }
+    }
+
+    @Test
+    public void testFloatMarshal() {
+        final AxContextSchema avroFloatSchema =
+                new AxContextSchema(new AxArtifactKey("AvroFloat", "0.0.1"), "Avro", "{\"type\": \"float\"}");
+
+        schemas.getSchemasMap().put(avroFloatSchema.getKey(), avroFloatSchema);
+        final SchemaHelper schemaHelper4 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroFloatSchema.getKey());
+
+        assertEquals("0.0", schemaHelper4.marshal2Json(0F));
+        assertEquals("1.0", schemaHelper4.marshal2Json(1F));
+        assertEquals("-1.0", schemaHelper4.marshal2Json(-1F));
+        assertEquals("1.23", schemaHelper4.marshal2Json(1.23F));
+        assertEquals("-1.23", schemaHelper4.marshal2Json(-1.23F));
+        assertEquals("9.223372E18", schemaHelper4.marshal2Json(9.223372E18F));
+        assertEquals("-9.223372E18", schemaHelper4.marshal2Json(-9.223372E18F));
+        assertEquals("9.223372E18", schemaHelper4.marshal2Json(9.223372E18F));
+        assertEquals("-9.223372E18", schemaHelper4.marshal2Json(-9.223372E18F));
+        try {
+            schemaHelper4.marshal2Json("Hello");
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().startsWith(
+                    "AvroTest:0.0.1: object \"Hello\" Avro marshalling failed: java.lang.String cannot be cast to java.lang.Float"));
+        }
+        try {
+            schemaHelper4.marshal2Json(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage()
+                    .startsWith("AvroTest:0.0.1: cannot encode a null object of class \"java.lang.Float\""));
+        }
+    }
+
+
+    @Test
+    public void testDoubleMarshal() {
+        final AxContextSchema avroDoubleSchema =
+                new AxContextSchema(new AxArtifactKey("AvroDouble", "0.0.1"), "Avro", "{\"type\": \"double\"}");
+
+        schemas.getSchemasMap().put(avroDoubleSchema.getKey(), avroDoubleSchema);
+        final SchemaHelper schemaHelper5 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroDoubleSchema.getKey());
+
+        assertEquals("0.0", schemaHelper5.marshal2Json(0D));
+        assertEquals("1.0", schemaHelper5.marshal2Json(1D));
+        assertEquals("-1.0", schemaHelper5.marshal2Json(-1D));
+        assertEquals("1.23", schemaHelper5.marshal2Json(1.23));
+        assertEquals("-1.23", schemaHelper5.marshal2Json(-1.23));
+        assertEquals("9.223372036854776E18", schemaHelper5.marshal2Json(9.223372036854776E18));
+        assertEquals("-9.223372036854776E18", schemaHelper5.marshal2Json(-9.223372036854776E18));
+        assertEquals("9.223372036854776E18", schemaHelper5.marshal2Json(9.223372036854776E18));
+        assertEquals("-9.223372036854776E18", schemaHelper5.marshal2Json(-9.223372036854776E18));
+        try {
+            schemaHelper5.marshal2Json("Hello");
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().startsWith(
+                    "AvroTest:0.0.1: object \"Hello\" Avro marshalling failed: java.lang.String cannot be cast to java.lang.Double"));
+        }
+        try {
+            schemaHelper5.marshal2Json(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage()
+                    .startsWith("AvroTest:0.0.1: cannot encode a null object of class \"java.lang.Double\""));
+        }
+    }
+
+    @Test
+    public void testStringMarshal() {
+        final AxContextSchema avroStringSchema =
+                new AxContextSchema(new AxArtifactKey("AvroString", "0.0.1"), "Avro", "{\"type\": \"string\"}");
+
+        schemas.getSchemasMap().put(avroStringSchema.getKey(), avroStringSchema);
+        final SchemaHelper schemaHelper7 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroStringSchema.getKey());
+
+        assertEquals("\"0\"", schemaHelper7.marshal2Json("0"));
+        assertEquals("\"1\"", schemaHelper7.marshal2Json("1"));
+        assertEquals("\"-1\"", schemaHelper7.marshal2Json("-1"));
+        assertEquals("\"1.23\"", schemaHelper7.marshal2Json("1.23"));
+        assertEquals("\"-1.23\"", schemaHelper7.marshal2Json("-1.23"));
+        assertEquals("\"9223372036854775807\"", schemaHelper7.marshal2Json("9223372036854775807"));
+        assertEquals("\"-9223372036854775808\"", schemaHelper7.marshal2Json("-9223372036854775808"));
+        assertEquals("\"9223372036854775808\"", schemaHelper7.marshal2Json("9223372036854775808"));
+        assertEquals("\"-9223372036854775809\"", schemaHelper7.marshal2Json("-9223372036854775809"));
+        assertEquals("\"Hello\"", schemaHelper7.marshal2Json("Hello"));
+        try {
+            schemaHelper7.marshal2Json(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage()
+                    .startsWith("AvroTest:0.0.1: cannot encode a null object of class \"java.lang.String\""));
+        }
+    }
+
+    @Test
+    public void testBytesMarshal() {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroString", "0.0.1"), "Avro", "{\"type\": \"bytes\"}");
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        final byte[] helloBytes = {104, 101, 108, 108, 111};
+        final String helloOut = schemaHelper.marshal2Json(helloBytes);
+        assertEquals("\"hello\"", helloOut);
+
+        try {
+            schemaHelper.marshal2Json(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage()
+                    .startsWith("AvroTest:0.0.1: cannot encode a null object of class \"java.lang.Byte[]\""));
+        }
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaHelperUnmarshal.java b/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaHelperUnmarshal.java
new file mode 100644 (file)
index 0000000..725ebb2
--- /dev/null
@@ -0,0 +1,371 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.avro.util.Utf8;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @version
+ */
+public class TestAvroSchemaHelperUnmarshal {
+    private final AxKey testKey = new AxArtifactKey("AvroTest", "0.0.1");
+    private AxContextSchemas schemas;
+
+    @Before
+    public void initTest() {
+        schemas = new AxContextSchemas(new AxArtifactKey("AvroSchemas", "0.0.1"));
+        ModelService.registerModel(AxContextSchemas.class, schemas);
+        new SchemaParameters().getSchemaHelperParameterMap().put("Avro", new AvroSchemaHelperParameters());
+    }
+
+    // @Test
+    public void testNullUnmarshal() {
+        final AxContextSchema avroNullSchema =
+                new AxContextSchema(new AxArtifactKey("AvroNull", "0.0.1"), "Avro", "{\"type\": \"null\"}");
+
+        schemas.getSchemasMap().put(avroNullSchema.getKey(), avroNullSchema);
+        final SchemaHelper schemaHelper0 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroNullSchema.getKey());
+
+        try {
+            schemaHelper0.createNewInstance();
+            fail("test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("AvroTest:0.0.1: could not create an instance, schema class for the schema is null",
+                    e.getMessage());
+        }
+
+        assertEquals(null, schemaHelper0.unmarshal("null"));
+
+        try {
+            schemaHelper0.unmarshal("123");
+            fail("test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "AvroTest:0.0.1: object \"123\" Avro unmarshalling failed: Expected null. Got VALUE_NUMBER_INT",
+                    e.getMessage());
+        }
+    }
+
+    // @Test
+    public void testBooleanUnmarshal() {
+        final AxContextSchema avroBooleanSchema =
+                new AxContextSchema(new AxArtifactKey("AvroBoolean", "0.0.1"), "Avro", "{\"type\": \"boolean\"}");
+
+        schemas.getSchemasMap().put(avroBooleanSchema.getKey(), avroBooleanSchema);
+        final SchemaHelper schemaHelper1 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroBooleanSchema.getKey());
+
+        try {
+            schemaHelper1.createNewInstance();
+            fail("test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "AvroTest:0.0.1: could not create an instance of class \"java.lang.Boolean\" using the default constructor \"Boolean()\"",
+                    e.getMessage());
+        }
+        assertEquals(true, schemaHelper1.createNewInstance("true"));
+
+        assertEquals(true, schemaHelper1.unmarshal("true"));
+        assertEquals(false, schemaHelper1.unmarshal("false"));
+        try {
+            schemaHelper1.unmarshal(0);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "AvroTest:0.0.1: object \"0\" Avro unmarshalling failed: Expected boolean. Got VALUE_NUMBER_INT",
+                    e.getMessage());
+        }
+    }
+
+    // @Test
+    public void testIntUnmarshal() {
+        final AxContextSchema avroIntSchema =
+                new AxContextSchema(new AxArtifactKey("AvroInt", "0.0.1"), "Avro", "{\"type\": \"int\"}");
+
+        schemas.getSchemasMap().put(avroIntSchema.getKey(), avroIntSchema);
+        final SchemaHelper schemaHelper2 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroIntSchema.getKey());
+
+        try {
+            schemaHelper2.createNewInstance();
+            fail("test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "AvroTest:0.0.1: could not create an instance of class \"java.lang.Integer\" using the default constructor \"Integer()\"",
+                    e.getMessage());
+        }
+        assertEquals(123, schemaHelper2.createNewInstance("123"));
+
+        assertEquals(0, schemaHelper2.unmarshal("0"));
+        assertEquals(1, schemaHelper2.unmarshal("1"));
+        assertEquals(-1, schemaHelper2.unmarshal("-1"));
+        assertEquals(1, schemaHelper2.unmarshal("1.23"));
+        assertEquals(-1, schemaHelper2.unmarshal("-1.23"));
+        assertEquals(2147483647, schemaHelper2.unmarshal("2147483647"));
+        assertEquals(-2147483648, schemaHelper2.unmarshal("-2147483648"));
+        try {
+            schemaHelper2.unmarshal("2147483648");
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().startsWith(
+                    "AvroTest:0.0.1: object \"2147483648\" Avro unmarshalling failed: Numeric value (2147483648) out of range of int"));
+        }
+        try {
+            schemaHelper2.unmarshal("-2147483649");
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().startsWith(
+                    "AvroTest:0.0.1: object \"-2147483649\" Avro unmarshalling failed: Numeric value (-2147483649) out of range of int"));
+        }
+        try {
+            schemaHelper2.unmarshal(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().equals(
+                    "AvroTest:0.0.1: object \"null\" Avro unmarshalling failed: String to read from cannot be null!"));
+        }
+    }
+
+    // @Test
+    public void testLongUnmarshal() {
+        final AxContextSchema avroLongSchema =
+                new AxContextSchema(new AxArtifactKey("AvroLong", "0.0.1"), "Avro", "{\"type\": \"long\"}");
+
+        schemas.getSchemasMap().put(avroLongSchema.getKey(), avroLongSchema);
+        final SchemaHelper schemaHelper3 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroLongSchema.getKey());
+
+        try {
+            schemaHelper3.createNewInstance();
+            fail("test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "AvroTest:0.0.1: could not create an instance of class \"java.lang.Long\" using the default constructor \"Long()\"",
+                    e.getMessage());
+        }
+        assertEquals(123456789L, schemaHelper3.createNewInstance("123456789"));
+
+        assertEquals(0L, schemaHelper3.unmarshal("0"));
+        assertEquals(1L, schemaHelper3.unmarshal("1"));
+        assertEquals(-1L, schemaHelper3.unmarshal("-1"));
+        assertEquals(1L, schemaHelper3.unmarshal("1.23"));
+        assertEquals(-1L, schemaHelper3.unmarshal("-1.23"));
+        assertEquals(9223372036854775807L, schemaHelper3.unmarshal("9223372036854775807"));
+        assertEquals(-9223372036854775808L, schemaHelper3.unmarshal("-9223372036854775808"));
+        try {
+            schemaHelper3.unmarshal("9223372036854775808");
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().startsWith(
+                    "AvroTest:0.0.1: object \"9223372036854775808\" Avro unmarshalling failed: Numeric value (9223372036854775808) out of range of long"));
+        }
+        try {
+            schemaHelper3.unmarshal("-9223372036854775809");
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().startsWith(
+                    "AvroTest:0.0.1: object \"-9223372036854775809\" Avro unmarshalling failed: Numeric value (-9223372036854775809) out of range of long"));
+        }
+        try {
+            schemaHelper3.unmarshal("\"Hello\"");
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().equals(
+                    "AvroTest:0.0.1: object \"\"Hello\"\" Avro unmarshalling failed: Expected long. Got VALUE_STRING"));
+        }
+        try {
+            schemaHelper3.unmarshal(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().equals(
+                    "AvroTest:0.0.1: object \"null\" Avro unmarshalling failed: String to read from cannot be null!"));
+        }
+    }
+
+    // @Test
+    public void testFloatUnmarshal() {
+        final AxContextSchema avroFloatSchema =
+                new AxContextSchema(new AxArtifactKey("AvroFloat", "0.0.1"), "Avro", "{\"type\": \"float\"}");
+
+        schemas.getSchemasMap().put(avroFloatSchema.getKey(), avroFloatSchema);
+        final SchemaHelper schemaHelper4 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroFloatSchema.getKey());
+
+        try {
+            schemaHelper4.createNewInstance();
+            fail("test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "AvroTest:0.0.1: could not create an instance of class \"java.lang.Float\" using the default constructor \"Float()\"",
+                    e.getMessage());
+        }
+        assertEquals(1.2345F, schemaHelper4.createNewInstance("1.2345"));
+
+        assertEquals(0.0F, schemaHelper4.unmarshal("0"));
+        assertEquals(1.0F, schemaHelper4.unmarshal("1"));
+        assertEquals(-1.0F, schemaHelper4.unmarshal("-1"));
+        assertEquals(1.23F, schemaHelper4.unmarshal("1.23"));
+        assertEquals(-1.23F, schemaHelper4.unmarshal("-1.23"));
+        assertEquals(9.223372E18F, schemaHelper4.unmarshal("9223372036854775807"));
+        assertEquals(-9.223372E18F, schemaHelper4.unmarshal("-9223372036854775808"));
+        assertEquals(9.223372E18F, schemaHelper4.unmarshal("9223372036854775808"));
+        assertEquals(-9.223372E18F, schemaHelper4.unmarshal("-9223372036854775809"));
+        try {
+            schemaHelper4.unmarshal("\"Hello\"");
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().equals(
+                    "AvroTest:0.0.1: object \"\"Hello\"\" Avro unmarshalling failed: Expected float. Got VALUE_STRING"));
+        }
+        try {
+            schemaHelper4.unmarshal(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().equals(
+                    "AvroTest:0.0.1: object \"null\" Avro unmarshalling failed: String to read from cannot be null!"));
+        }
+    }
+
+    // @Test
+    public void testDoubleUnmarshal() {
+        final AxContextSchema avroDoubleSchema =
+                new AxContextSchema(new AxArtifactKey("AvroDouble", "0.0.1"), "Avro", "{\"type\": \"double\"}");
+
+        schemas.getSchemasMap().put(avroDoubleSchema.getKey(), avroDoubleSchema);
+        final SchemaHelper schemaHelper5 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroDoubleSchema.getKey());
+
+        try {
+            schemaHelper5.createNewInstance();
+            fail("test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "AvroTest:0.0.1: could not create an instance of class \"java.lang.Double\" using the default constructor \"Double()\"",
+                    e.getMessage());
+        }
+        assertEquals(1.2345E06, schemaHelper5.createNewInstance("1.2345E06"));
+
+        assertEquals(0.0, schemaHelper5.unmarshal("0"));
+        assertEquals(1.0, schemaHelper5.unmarshal("1"));
+        assertEquals(-1.0, schemaHelper5.unmarshal("-1"));
+        assertEquals(1.23, schemaHelper5.unmarshal("1.23"));
+        assertEquals(-1.23, schemaHelper5.unmarshal("-1.23"));
+        assertEquals(9.223372036854776E18, schemaHelper5.unmarshal("9223372036854775807"));
+        assertEquals(-9.223372036854776E18, schemaHelper5.unmarshal("-9223372036854775808"));
+        assertEquals(9.223372036854776E18, schemaHelper5.unmarshal("9223372036854775808"));
+        assertEquals(-9.223372036854776E18, schemaHelper5.unmarshal("-9223372036854775809"));
+        try {
+            schemaHelper5.unmarshal("\"Hello\"");
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().equals(
+                    "AvroTest:0.0.1: object \"\"Hello\"\" Avro unmarshalling failed: Expected double. Got VALUE_STRING"));
+        }
+        try {
+            schemaHelper5.unmarshal(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().equals(
+                    "AvroTest:0.0.1: object \"null\" Avro unmarshalling failed: String to read from cannot be null!"));
+        }
+    }
+
+    @Test
+    public void testStringUnmarshal() {
+        final AxContextSchema avroStringSchema =
+                new AxContextSchema(new AxArtifactKey("AvroString", "0.0.1"), "Avro", "{\"type\": \"string\"}");
+
+        schemas.getSchemasMap().put(avroStringSchema.getKey(), avroStringSchema);
+        final SchemaHelper schemaHelper7 =
+                new SchemaHelperFactory().createSchemaHelper(testKey, avroStringSchema.getKey());
+
+        assertEquals("", schemaHelper7.createNewInstance(""));
+        assertEquals("1.2345E06", schemaHelper7.createNewInstance("1.2345E06"));
+
+        assertEquals("0", schemaHelper7.unmarshal("0"));
+        assertEquals("1", schemaHelper7.unmarshal("1"));
+        assertEquals("-1", schemaHelper7.unmarshal("-1"));
+        assertEquals("1.23", schemaHelper7.unmarshal("1.23"));
+        assertEquals("-1.23", schemaHelper7.unmarshal("-1.23"));
+        assertEquals("9223372036854775807", schemaHelper7.unmarshal("9223372036854775807"));
+        assertEquals("-9223372036854775808", schemaHelper7.unmarshal("-9223372036854775808"));
+        assertEquals("9223372036854775808", schemaHelper7.unmarshal("9223372036854775808"));
+        assertEquals("-9223372036854775809", schemaHelper7.unmarshal("-9223372036854775809"));
+        assertEquals("Hello", schemaHelper7.unmarshal("Hello"));
+        assertEquals("Hello", schemaHelper7.unmarshal(new Utf8("Hello")));
+        try {
+            schemaHelper7.unmarshal(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().equals(
+                    "AvroTest:0.0.1: object \"null\" Avro unmarshalling failed: String to read from cannot be null!"));
+        }
+    }
+
+    @Test
+    public void testBytesUnmarshal() {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroString", "0.0.1"), "Avro", "{\"type\": \"bytes\"}");
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        try {
+            schemaHelper.createNewInstance();
+            fail("test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals(
+                    "AvroTest:0.0.1: could not create an instance of class \"java.lang.Byte[]\" using the default constructor \"Byte[]()\"",
+                    e.getMessage());
+        }
+        final byte[] newBytes = (byte[]) schemaHelper.createNewInstance("\"hello\"");
+        assertEquals(5, newBytes.length);
+        assertEquals(104, newBytes[0]);
+        assertEquals(101, newBytes[1]);
+        assertEquals(108, newBytes[2]);
+        assertEquals(108, newBytes[3]);
+        assertEquals(111, newBytes[4]);
+
+        try {
+            schemaHelper.unmarshal(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertTrue(e.getMessage().equals(
+                    "AvroTest:0.0.1: object \"null\" Avro unmarshalling failed: String to read from cannot be null!"));
+        }
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaMap.java b/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaMap.java
new file mode 100644 (file)
index 0000000..74591bb
--- /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.plugins.context.schema.avro;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+
+import org.apache.avro.util.Utf8;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+import org.onap.policy.apex.model.utilities.TextFileUtils;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @version
+ */
+public class TestAvroSchemaMap {
+    private final AxKey testKey = new AxArtifactKey("AvroTest", "0.0.1");
+    private AxContextSchemas schemas;
+    private String longMapSchema;
+    private String addressMapSchema;
+    private String addressMapSchemaInvalidFields;
+
+    @Before
+    public void initTest() throws IOException {
+        schemas = new AxContextSchemas(new AxArtifactKey("AvroSchemas", "0.0.1"));
+        ModelService.registerModel(AxContextSchemas.class, schemas);
+        new SchemaParameters().getSchemaHelperParameterMap().put("Avro", new AvroSchemaHelperParameters());
+        longMapSchema = TextFileUtils.getTextFileAsString("src/test/resources/avsc/MapExampleLong.avsc");
+        addressMapSchema = TextFileUtils.getTextFileAsString("src/test/resources/avsc/MapExampleAddress.avsc");
+        addressMapSchemaInvalidFields =
+                TextFileUtils.getTextFileAsString("src/test/resources/avsc/MapExampleAddressInvalidFields.avsc");
+    }
+
+    @Test
+    public void testMapInit() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", addressMapSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        final HashMap<?, ?> newMapEmpty = (HashMap<?, ?>) schemaHelper.createNewInstance();
+        assertEquals(0, newMapEmpty.size());
+
+        final String inString = TextFileUtils.getTextFileAsString("src/test/resources/data/MapExampleAddressFull.json");
+        final HashMap<?, ?> newMapFull = (HashMap<?, ?>) schemaHelper.createNewInstance(inString);
+
+        assertEquals("{\"streetaddress\": \"221 B Baker St.\", \"city\": \"London\"}",
+                newMapFull.get(new Utf8("address2")).toString());
+    }
+
+    @Test
+    public void testLongMapUnmarshalMarshal() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroMap", "0.0.1"), "Avro", longMapSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/MapExampleLongNull.json");
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/MapExampleLongFull.json");
+    }
+
+    @Test
+    public void testAddressMapUnmarshalMarshal() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroMap", "0.0.1"), "Avro", addressMapSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/MapExampleAddressNull.json");
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/MapExampleAddressFull.json");
+    }
+
+    @Test
+    public void testAddressMapUnmarshalMarshalInvalidFields() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroMap", "0.0.1"), "Avro", addressMapSchemaInvalidFields);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/MapExampleAddressInvalidFields.json");
+    }
+
+    private void testUnmarshalMarshal(final SchemaHelper schemaHelper, final String fileName) throws IOException {
+        final String originalInString = TextFileUtils.getTextFileAsString(fileName);
+        final HashMap<?, ?> firstDecodedMap = (HashMap<?, ?>) schemaHelper.unmarshal(originalInString);
+
+        final String outString = schemaHelper.marshal2Json(firstDecodedMap);
+
+        final File tempOutFile = File.createTempFile("ApexAvro", ".json");
+        TextFileUtils.putStringAsFile(outString, tempOutFile);
+
+        final String decodeEncodeInString = TextFileUtils.getTextFileAsString(fileName);
+        tempOutFile.delete();
+
+        final HashMap<?, ?> secondDecodedMap = (HashMap<?, ?>) schemaHelper.unmarshal(decodeEncodeInString);
+
+        // Now check that our doubly encoded map equals the first decoded map, Java map equals
+        // checks values and keys
+        assertEquals(firstDecodedMap, secondDecodedMap);
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaRecord.java b/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaRecord.java
new file mode 100644 (file)
index 0000000..b793ef0
--- /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.plugins.context.schema.avro;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.avro.generic.GenericRecord;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+import org.onap.policy.apex.model.utilities.TextFileUtils;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @version
+ */
+public class TestAvroSchemaRecord {
+    private final AxKey testKey = new AxArtifactKey("AvroTest", "0.0.1");
+    private AxContextSchemas schemas;
+    private String recordSchema;
+    private String recordSchemaVPN;
+    private String recordSchemaVPNReuse;
+    private String recordSchemaInvalidFields;
+
+    @Before
+    public void initTest() throws IOException {
+        schemas = new AxContextSchemas(new AxArtifactKey("AvroSchemas", "0.0.1"));
+        ModelService.registerModel(AxContextSchemas.class, schemas);
+        new SchemaParameters().getSchemaHelperParameterMap().put("Avro", new AvroSchemaHelperParameters());
+        recordSchema = TextFileUtils.getTextFileAsString("src/test/resources/avsc/RecordExample.avsc");
+        recordSchemaVPN = TextFileUtils.getTextFileAsString("src/test/resources/avsc/RecordExampleVPN.avsc");
+        recordSchemaVPNReuse = TextFileUtils.getTextFileAsString("src/test/resources/avsc/RecordExampleVPNReuse.avsc");
+        recordSchemaInvalidFields =
+                TextFileUtils.getTextFileAsString("src/test/resources/avsc/RecordExampleInvalidFields.avsc");
+    }
+
+    @Test
+    public void testRecordInit() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", recordSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        final GenericRecord newRecordEmpty = (GenericRecord) schemaHelper.createNewInstance();
+        assertEquals(null, newRecordEmpty.get("passwordHash"));
+
+        final String inString = TextFileUtils.getTextFileAsString("src/test/resources/data/RecordExampleFull.json");
+        final GenericRecord newRecordFull = (GenericRecord) schemaHelper.createNewInstance(inString);
+        assertEquals("gobbledygook", newRecordFull.get("passwordHash").toString());
+    }
+
+    @Test
+    public void testRecordUnmarshalMarshal() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", recordSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/RecordExampleNull.json");
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/RecordExampleFull.json");
+    }
+
+    @Test
+    public void testRecordUnmarshalMarshalInvalid() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", recordSchemaInvalidFields);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/RecordExampleInvalidFields.json");
+    }
+
+    @Test
+    public void testVPNRecordUnmarshalMarshal() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", recordSchemaVPN);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/RecordExampleVPNFull.json");
+    }
+
+    @Test
+    public void testVPNRecordReuse() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", recordSchemaVPNReuse);
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+    }
+
+    private void testUnmarshalMarshal(final SchemaHelper schemaHelper, final String fileName) throws IOException {
+        final String inString = TextFileUtils.getTextFileAsString(fileName);
+        final GenericRecord decodedObject = (GenericRecord) schemaHelper.unmarshal(inString);
+        final String outString = schemaHelper.marshal2Json(decodedObject);
+        assertEquals(inString.replaceAll("\\s+", ""), outString.replaceAll("\\s+", ""));
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaUnion.java b/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestAvroSchemaUnion.java
new file mode 100644 (file)
index 0000000..100b51d
--- /dev/null
@@ -0,0 +1,109 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.avro.generic.GenericRecord;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+import org.onap.policy.apex.model.utilities.TextFileUtils;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ * @version
+ */
+public class TestAvroSchemaUnion {
+    private final AxKey testKey = new AxArtifactKey("AvroTest", "0.0.1");
+    private AxContextSchemas schemas;
+    private String uinionSchema;
+
+    @Before
+    public void initTest() throws IOException {
+        schemas = new AxContextSchemas(new AxArtifactKey("AvroSchemas", "0.0.1"));
+        ModelService.registerModel(AxContextSchemas.class, schemas);
+        new SchemaParameters().getSchemaHelperParameterMap().put("Avro", new AvroSchemaHelperParameters());
+        uinionSchema = TextFileUtils.getTextFileAsString("src/test/resources/avsc/UnionExample.avsc");
+    }
+
+    @Ignore
+    @Test
+    public void testUnionAllFields() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", uinionSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        final String inString = TextFileUtils.getTextFileAsString("src/test/resources/data/UnionExampleAllFields.json");
+        final GenericRecord user = (GenericRecord) schemaHelper.createNewInstance(inString);
+
+        assertEquals("Ben", user.get("name").toString());
+        assertEquals(7, user.get("favourite_number"));
+        assertEquals("red", user.get("favourite_colour").toString());
+    }
+
+    @Ignore
+    @Test
+    public void testUnionOptionalField() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", uinionSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        final String inString =
+                TextFileUtils.getTextFileAsString("src/test/resources/data/UnionExampleOptionalField.json");
+        final GenericRecord user = (GenericRecord) schemaHelper.createNewInstance(inString);
+
+        assertEquals("Ben", user.get("name").toString());
+        assertEquals(7, user.get("favourite_number"));
+        assertEquals("red", user.get("favourite_colour").toString());
+    }
+
+    @Ignore
+    @Test
+    public void testUnionNullField() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", uinionSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        final String inString = TextFileUtils.getTextFileAsString("src/test/resources/data/UnionExampleNullField.json");
+        final GenericRecord user = (GenericRecord) schemaHelper.createNewInstance(inString);
+
+        assertEquals("Ben", user.get("name").toString());
+        assertEquals(7, user.get("favourite_number"));
+        assertEquals("red", user.get("favourite_colour").toString());
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestHealthCheckSchema.java b/plugins/plugins-context/context-schema/context-schema-avro/src/test/java/org/onap/policy/apex/plugins/context/schema/avro/TestHealthCheckSchema.java
new file mode 100644 (file)
index 0000000..c32d9b3
--- /dev/null
@@ -0,0 +1,119 @@
+/*-
+ * ============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.plugins.context.schema.avro;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericData.Record;
+import org.apache.avro.generic.GenericRecord;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+import org.onap.policy.apex.model.utilities.TextFileUtils;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class TestHealthCheckSchema {
+    private final AxKey testKey = new AxArtifactKey("AvroTest", "0.0.1");
+    private AxContextSchemas schemas;
+    private String healthCheckSchema;
+
+    @Before
+    public void initTest() throws IOException {
+        schemas = new AxContextSchemas(new AxArtifactKey("AvroSchemas", "0.0.1"));
+        ModelService.registerModel(AxContextSchemas.class, schemas);
+
+        new SchemaParameters().getSchemaHelperParameterMap().put("Avro", new AvroSchemaHelperParameters());
+        healthCheckSchema = TextFileUtils.getTextFileAsString("src/test/resources/avsc/HealthCheckBodyType.avsc");
+    }
+
+
+    @Test
+    public void testHealthCheck() throws IOException {
+        final AxContextSchema avroSchema =
+                new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "Avro", healthCheckSchema);
+
+        schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
+        final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
+
+        testUnmarshalMarshal(schemaHelper, "src/test/resources/data/HealthCheckEvent.json");
+
+        final GenericRecord healthCheckRecord = (Record) schemaHelper.createNewInstance();
+        final Schema healthCheckRecordSchema = healthCheckRecord.getSchema();
+
+        final GenericRecord inputRecord = new GenericData.Record(healthCheckRecordSchema.getField("input").schema());
+        final Schema inputRecordRecordSchema = inputRecord.getSchema();
+
+        final GenericRecord actionIndentifiersRecord =
+                new GenericData.Record(inputRecordRecordSchema.getField("action_DasH_identifiers").schema());
+
+        final GenericRecord commonHeaderRecord =
+                new GenericData.Record(inputRecordRecordSchema.getField("common_DasH_header").schema());
+        final Schema commonHeaderRecordSchema = commonHeaderRecord.getSchema();
+
+        final GenericRecord commonHeaderFlagsRecord =
+                new GenericData.Record(commonHeaderRecordSchema.getField("flags").schema());
+
+        healthCheckRecord.put("input", inputRecord);
+        inputRecord.put("action_DasH_identifiers", actionIndentifiersRecord);
+        inputRecord.put("common_DasH_header", commonHeaderRecord);
+        commonHeaderRecord.put("flags", commonHeaderFlagsRecord);
+
+        inputRecord.put("action", "HealthCheck");
+        inputRecord.put("payload",
+                "{\"host-ip-address\":\"131.160.203.125\",\"input.url\":\"131.160.203.125/afr\",\"request-action-type\":\"GET\",\"request-action\":\"AFR\"}");
+
+        actionIndentifiersRecord.put("vnf_DasH_id", "49414df5-3482-4fd8-9952-c463dff2770b");
+
+        commonHeaderRecord.put("request_DasH_id", "afr-request3");
+        commonHeaderRecord.put("originator_DasH_id", "AFR");
+        commonHeaderRecord.put("api_DasH_ver", "2.15");
+        commonHeaderRecord.put("sub_DasH_request_DasH_id", "AFR-subrequest");
+        commonHeaderRecord.put("timestamp", "2017-11-06T15:15:18.97Z");
+
+        commonHeaderFlagsRecord.put("ttl", "10000");
+        commonHeaderFlagsRecord.put("force", "TRUE");
+        commonHeaderFlagsRecord.put("mode", "EXCLUSIVE");
+
+        final String eventString = TextFileUtils.getTextFileAsString("src/test/resources/data/HealthCheckEvent.json");
+        final String outString = schemaHelper.marshal2Json(healthCheckRecord);
+        assertEquals(eventString.toString().replaceAll("\\s+", ""), outString.replaceAll("\\s+", ""));
+    }
+
+    private void testUnmarshalMarshal(final SchemaHelper schemaHelper, final String fileName) throws IOException {
+        final String inString = TextFileUtils.getTextFileAsString(fileName);
+        final GenericRecord decodedObject = (GenericRecord) schemaHelper.unmarshal(inString);
+        final String outString = schemaHelper.marshal2Json(decodedObject);
+        assertEquals(inString.replaceAll("\\s+", ""), outString.replaceAll("\\s+", ""));
+    }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/AAIInventoryResponseItemType.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/AAIInventoryResponseItemType.avsc
new file mode 100644 (file)
index 0000000..d4ae592
--- /dev/null
@@ -0,0 +1,70 @@
+{
+       "type": "array",
+       "items": {
+               "type": "record",
+               "name": "AAIInventoryResponseItem_Type",
+               "fields": [
+                       {
+                               "name": "model_DasH_name",
+                               "type": "string"
+                       },
+                       {
+                               "name": "extra_DasH_properties",
+                               "type": {
+                                       "type": "record",
+                                       "name": "AAIInventoryResponseItemExtraProperties_Type",
+                                       "fields": []
+                               }
+                       },
+                       {
+                               "name": "generic_DasH_vnf",
+                               "type": {
+                                       "type": "record",
+                                       "name": "AAIInventoryResponseItemGenericVNF_Type",
+                                       "fields": [
+                                               {
+                                                       "name": "vnf_DasH_id",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "vnf_DasH_name",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "vnf_DasH_type",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "service_DasH_id",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "orchestration_DasH_status",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "in_DasH_maint",
+                                                       "type": "boolean"
+                                               },
+                                               {
+                                                       "name": "is_DasH_closed_DasH_loop_DasH_disabled",
+                                                       "type": "boolean"
+                                               },
+                                               {
+                                                       "name": "resource_DasH_version",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "model_DasH_invariant_DasH_id",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "model_DasH_version_DasH_id",
+                                                       "type": "string"
+                                               }
+                                       ]
+                               }
+                       }
+               ]
+       }
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/ArrayExampleAddress.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/ArrayExampleAddress.avsc
new file mode 100644 (file)
index 0000000..0967d62
--- /dev/null
@@ -0,0 +1,10 @@
+{
+       "type": "array", "items": {
+               "type" : "record",
+               "name" : "AddressUSRecord",
+               "fields" : [
+                       {"name": "streetaddress", "type": "string"},
+                       {"name": "city", "type": "string"}
+                       ]
+       }
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/ArrayExampleLong.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/ArrayExampleLong.avsc
new file mode 100644 (file)
index 0000000..91f391a
--- /dev/null
@@ -0,0 +1,3 @@
+{
+       "type": "array", "items": "long"
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/EnumSchema.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/EnumSchema.avsc
new file mode 100644 (file)
index 0000000..ea5c5b7
--- /dev/null
@@ -0,0 +1,5 @@
+{
+       "type": "enum",
+       "name": "Suit",
+       "symbols" : ["SPADES", "HEARTS", "DIAMONDS", "CLUBS"]
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/FixedSchema.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/FixedSchema.avsc
new file mode 100644 (file)
index 0000000..4642ef5
--- /dev/null
@@ -0,0 +1,5 @@
+{
+       "type" : "fixed",
+       "name" : "binaryData",
+       "size" : 64
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/HealthCheckBodyType.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/HealthCheckBodyType.avsc
new file mode 100644 (file)
index 0000000..2db1d69
--- /dev/null
@@ -0,0 +1,76 @@
+{
+       "type"      : "record",
+       "name"      : "HealthCheckBody_Type",
+       "namespace" : "com.ericsson.apex.onap.tlgoal2017",
+       "fields"    : [
+               {
+                       "name": "input",
+                       "type": {
+                               "type" : "record",
+                               "name" : "InputRecord",
+                               "fields" : [
+                                       {
+                                               "name": "action", "type": "string"
+                                       },
+                                       {
+                                               "name": "action_DasH_identifiers",
+                                               "type": {
+                                                       "type" : "record",
+                                                       "name" : "ActionIdentifiersRecord",
+                                                       "fields" : [
+                                                               {
+                                                                       "name": "vnf_DasH_id", "type": "string"
+                                                               }
+                                                               ]
+                                               }
+                                       },
+                                       {
+                                               "name": "common_DasH_header",
+                                               "type": {
+                                                       "type" : "record",
+                                                       "name" : "CommonHeaderRecord",
+                                                       "fields" : [
+                                                               {
+                                                                       "name": "request_DasH_id", "type": "string"
+                                                               },
+                                                               {
+                                                                       "name": "originator_DasH_id", "type": "string"
+                                                               },
+                                                               {
+                                                                       "name": "api_DasH_ver", "type": "string"
+                                                               },
+                                                               {
+                                                                       "name": "sub_DasH_request_DasH_id", "type": "string"
+                                                               },
+                                                               {
+                                                                       "name": "timestamp", "type": "string"
+                                                               },
+                                                               {
+                                                                       "name": "flags",
+                                                                       "type": {
+                                                                               "type" : "record",
+                                                                               "name" : "FlagsRecord",
+                                                                               "fields" : [
+                                                                                       {
+                                                                                               "name": "ttl", "type": "string"
+                                                                                       },
+                                                                                       {
+                                                                                               "name": "force", "type": "string"
+                                                                                       },
+                                                                                       {
+                                                                                               "name": "mode", "type": "string"
+                                                                                       }
+                                                                                       ]
+                                                                       }
+                                                               }
+                                                               ]
+                                               }
+                                       },
+                                       {
+                                               "name": "payload", "type": "string"
+                                       }
+                                       ]
+                       }
+               }
+               ]
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/MapExampleAddress.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/MapExampleAddress.avsc
new file mode 100644 (file)
index 0000000..f8457c6
--- /dev/null
@@ -0,0 +1,10 @@
+{
+       "type": "map", "values": {
+               "type" : "record",
+               "name" : "AddressUSRecord",
+               "fields" : [
+                       {"name": "streetaddress", "type": "string"},
+                       {"name": "city", "type": "string"}
+                       ]
+       }
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/MapExampleAddressInvalidFields.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/MapExampleAddressInvalidFields.avsc
new file mode 100644 (file)
index 0000000..48c4760
--- /dev/null
@@ -0,0 +1,10 @@
+{
+       "type": "map", "values": {
+               "type" : "record",
+               "name" : "AddressUSRecord",
+               "fields" : [
+                       {"name": "street_DasH_address", "type": "string"},
+                       {"name": "the_DoT_city", "type": "string"}
+                       ]
+       }
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/MapExampleLong.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/MapExampleLong.avsc
new file mode 100644 (file)
index 0000000..0bb3729
--- /dev/null
@@ -0,0 +1,3 @@
+{
+       "type": "map", "values": "long"
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/RecordExample.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/RecordExample.avsc
new file mode 100644 (file)
index 0000000..2747355
--- /dev/null
@@ -0,0 +1,172 @@
+{
+       "type": "record",
+       "name": "User",
+       "namespace": "com.example.avro",
+       "doc": "This is a user record in a fictitious to-do-list management app. It supports arbitrary grouping and nesting of items, and allows you to add items by email or by tweeting.\n\nNote this app doesn't actually exist. The schema is just a demo for [Avrodoc](https://github.com/ept/avrodoc)!",
+       "fields": [
+        {"name": "firstname", "type": "string"},
+        {"name": "lastname", "type": "string"},
+               {
+                       "name": "address",
+                       "type": {
+                               "type" : "record",
+                               "name" : "AddressUSRecord",
+                               "fields" : [
+                                       {"name": "streetaddress", "type": "string"},
+                                       {"name": "city", "type": "string"}
+                                       ]
+                       }
+               },
+               {
+                       "name": "id",
+                       "doc": "System-assigned numeric user ID. Cannot be changed by the user.",
+                       "type": "int"
+               },
+               {
+                       "name": "username",
+                       "doc": "The username chosen by the user. Can be changed by the user.",
+                       "type": "string"
+               },
+               {
+                       "name": "passwordHash",
+                       "doc": "The user's password, hashed using [scrypt](http://www.tarsnap.com/scrypt.html).",
+                       "type": "string"
+               },
+               {
+                       "name": "signupDate",
+                       "doc": "Timestamp (milliseconds since epoch) when the user signed up",
+                       "type": "long"
+               },
+               {
+                       "name": "emailAddresses",
+                       "doc": "All email addresses on the user's account",
+                       "type": {
+                               "type": "array",
+                               "items": {
+                                       "type": "record",
+                                       "name": "EmailAddress",
+                                       "doc": "Stores details about an email address that a user has associated with their account.",
+                                       "fields": [
+                                               {
+                                                       "name": "address",
+                                                       "doc": "The email address, e.g. `foo@example.com`",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "verified",
+                                                       "doc": "true if the user has clicked the link in a confirmation email to this address.",
+                                                       "type": "boolean",
+                                                       "default": false
+                                               },
+                                               {
+                                                       "name": "dateAdded",
+                                                       "doc": "Timestamp (milliseconds since epoch) when the email address was added to the account.",
+                                                       "type": "long"
+                                               },
+                                               {
+                                                       "name": "dateBounced",
+                                                       "doc": "Timestamp (milliseconds since epoch) when an email sent to this address last bounced. Reset to null when the address no longer bounces.",
+                                                       "type": ["null", "long"]
+                                               }
+                                               ]
+                               }
+                       }
+               },
+               {
+                       "name": "twitterAccounts",
+                       "doc": "All Twitter accounts that the user has OAuthed",
+                       "type": {
+                               "type": "array",
+                               "items": {
+                                       "type": "record",
+                                       "name": "TwitterAccount",
+                                       "doc": "Stores access credentials for one Twitter account, as granted to us by the user by OAuth.",
+                                       "fields": [
+                                               {
+                                                       "name": "status",
+                                                       "doc": "Indicator of whether this authorization is currently active, or has been revoked",
+                                                       "type": {
+                                                               "type": "enum",
+                                                               "name": "OAuthStatus",
+                                                               "doc": "* `PENDING`: the user has started authorizing, but not yet finished\n* `ACTIVE`: the token should work\n* `DENIED`: the user declined the authorization\n* `EXPIRED`: the token used to work, but now it doesn't\n* `REVOKED`: the user has explicitly revoked the token",
+                                                               "symbols": ["PENDING", "ACTIVE", "DENIED", "EXPIRED", "REVOKED"]
+                                                       }
+                                               },
+                                               {
+                                                       "name": "userId",
+                                                       "doc": "Twitter's numeric ID for this user",
+                                                       "type": "long"
+                                               },
+                                               {
+                                                       "name": "screenName",
+                                                       "doc": "The twitter username for this account (can be changed by the user)",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "oauthToken",
+                                                       "doc": "The OAuth token for this Twitter account",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "oauthTokenSecret",
+                                                       "doc": "The OAuth secret, used for signing requests on behalf of this Twitter account. `null` whilst the OAuth flow is not yet complete.",
+                                                       "type": ["null", "string"]
+                                               },
+                                               {
+                                                       "name": "dateAuthorized",
+                                                       "doc": "Timestamp (milliseconds since epoch) when the user last authorized this Twitter account",
+                                                       "type": "long"
+                                               }
+                                               ]
+                               }
+                       }
+               },
+               {
+                       "name": "toDoItems",
+                       "doc": "The top-level items in the user's to-do list",
+                       "type": {
+                               "type": "array",
+                               "items": {
+                                       "type": "record",
+                                       "name": "ToDoItem",
+                                       "doc": "A record is one node in a To-Do item tree (every record can contain nested sub-records).",
+                                       "fields": [
+                                               {
+                                                       "name": "status",
+                                                       "doc": "User-selected state for this item (e.g. whether or not it is marked as done)",
+                                                       "type": {
+                                                               "type": "enum",
+                                                               "name": "ToDoStatus",
+                                                               "doc": "* `HIDDEN`: not currently visible, e.g. because it becomes actionable in future\n* `ACTIONABLE`: appears in the current to-do list\n* `DONE`: marked as done, but still appears in the list\n* `ARCHIVED`: marked as done and no longer visible\n* `DELETED`: not done and removed from list (preserved for undo purposes)",
+                                                               "symbols": ["HIDDEN", "ACTIONABLE", "DONE", "ARCHIVED", "DELETED"]
+                                                       }
+                                               },
+                                               {
+                                                       "name": "title",
+                                                       "doc": "One-line summary of the item",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "description",
+                                                       "doc": "Detailed description (may contain HTML markup)",
+                                                       "type": ["null", "string"]
+                                               },
+                                               {
+                                                       "name": "snoozeDate",
+                                                       "doc": "Timestamp (milliseconds since epoch) at which the item should go from `HIDDEN` to `ACTIONABLE` status",
+                                                       "type": ["null", "long"]
+                                               },
+                                               {
+                                                       "name": "subItems",
+                                                       "doc": "List of children of this to-do tree node",
+                                                       "type": {
+                                                               "type": "array",
+                                                               "items": "ToDoItem"
+                                                       }
+                                               }
+                                               ]
+                               }
+                       }
+               }
+               ]
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/RecordExampleInvalidFields.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/RecordExampleInvalidFields.avsc
new file mode 100644 (file)
index 0000000..102641b
--- /dev/null
@@ -0,0 +1,172 @@
+{
+       "type": "record",
+       "name": "User",
+       "namespace": "com.example.avro",
+       "doc": "This is a user record in a fictitious to-do-list management app. It supports arbitrary grouping and nesting of items, and allows you to add items by email or by tweeting.\n\nNote this app doesn't actually exist. The schema is just a demo for [Avrodoc](https://github.com/ept/avrodoc)!",
+       "fields": [
+        {"name": "firstname", "type": "string"},
+        {"name": "lastname", "type": "string"},
+               {
+                       "name": "address",
+                       "type": {
+                               "type" : "record",
+                               "name" : "AddressUSRecord",
+                               "fields" : [
+                                       {"name": "streetaddress_DasH_1", "type": "string"},
+                                       {"name": "city", "type": "string"}
+                                       ]
+                       }
+               },
+               {
+                       "name": "id",
+                       "doc": "System-assigned numeric user ID. Cannot be changed by the user.",
+                       "type": "int"
+               },
+               {
+                       "name": "username",
+                       "doc": "The username chosen by the user. Can be changed by the user.",
+                       "type": "string"
+               },
+               {
+                       "name": "passwordHash",
+                       "doc": "The user's password, hashed using [scrypt](http://www.tarsnap.com/scrypt.html).",
+                       "type": "string"
+               },
+               {
+                       "name": "signupDate",
+                       "doc": "Timestamp (milliseconds since epoch) when the user signed up",
+                       "type": "long"
+               },
+               {
+                       "name": "email_DoT_Addresses",
+                       "doc": "All email addresses on the user's account",
+                       "type": {
+                               "type": "array",
+                               "items": {
+                                       "type": "record",
+                                       "name": "EmailAddress",
+                                       "doc": "Stores details about an email address that a user has associated with their account.",
+                                       "fields": [
+                                               {
+                                                       "name": "address",
+                                                       "doc": "The email address, e.g. `foo@example.com`",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "verified",
+                                                       "doc": "true if the user has clicked the link in a confirmation email to this address.",
+                                                       "type": "boolean",
+                                                       "default": false
+                                               },
+                                               {
+                                                       "name": "dateAdded",
+                                                       "doc": "Timestamp (milliseconds since epoch) when the email address was added to the account.",
+                                                       "type": "long"
+                                               },
+                                               {
+                                                       "name": "dateBounced",
+                                                       "doc": "Timestamp (milliseconds since epoch) when an email sent to this address last bounced. Reset to null when the address no longer bounces.",
+                                                       "type": ["null", "long"]
+                                               }
+                                               ]
+                               }
+                       }
+               },
+               {
+                       "name": "twitterAccounts",
+                       "doc": "All Twitter accounts that the user has OAuthed",
+                       "type": {
+                               "type": "array",
+                               "items": {
+                                       "type": "record",
+                                       "name": "TwitterAccount",
+                                       "doc": "Stores access credentials for one Twitter account, as granted to us by the user by OAuth.",
+                                       "fields": [
+                                               {
+                                                       "name": "status",
+                                                       "doc": "Indicator of whether this authorization is currently active, or has been revoked",
+                                                       "type": {
+                                                               "type": "enum",
+                                                               "name": "OAuthStatus",
+                                                               "doc": "* `PENDING`: the user has started authorizing, but not yet finished\n* `ACTIVE`: the token should work\n* `DENIED`: the user declined the authorization\n* `EXPIRED`: the token used to work, but now it doesn't\n* `REVOKED`: the user has explicitly revoked the token",
+                                                               "symbols": ["PENDING", "ACTIVE", "DENIED", "EXPIRED", "REVOKED"]
+                                                       }
+                                               },
+                                               {
+                                                       "name": "userId",
+                                                       "doc": "Twitter's numeric ID for this user",
+                                                       "type": "long"
+                                               },
+                                               {
+                                                       "name": "screenName",
+                                                       "doc": "The twitter username for this account (can be changed by the user)",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "oauthToken",
+                                                       "doc": "The OAuth token for this Twitter account",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "oauthTokenSecret",
+                                                       "doc": "The OAuth secret, used for signing requests on behalf of this Twitter account. `null` whilst the OAuth flow is not yet complete.",
+                                                       "type": ["null", "string"]
+                                               },
+                                               {
+                                                       "name": "dateAuthorized",
+                                                       "doc": "Timestamp (milliseconds since epoch) when the user last authorized this Twitter account",
+                                                       "type": "long"
+                                               }
+                                               ]
+                               }
+                       }
+               },
+               {
+                       "name": "toDoItems",
+                       "doc": "The top-level items in the user's to-do list",
+                       "type": {
+                               "type": "array",
+                               "items": {
+                                       "type": "record",
+                                       "name": "ToDoItem",
+                                       "doc": "A record is one node in a To-Do item tree (every record can contain nested sub-records).",
+                                       "fields": [
+                                               {
+                                                       "name": "status",
+                                                       "doc": "User-selected state for this item (e.g. whether or not it is marked as done)",
+                                                       "type": {
+                                                               "type": "enum",
+                                                               "name": "ToDoStatus",
+                                                               "doc": "* `HIDDEN`: not currently visible, e.g. because it becomes actionable in future\n* `ACTIONABLE`: appears in the current to-do list\n* `DONE`: marked as done, but still appears in the list\n* `ARCHIVED`: marked as done and no longer visible\n* `DELETED`: not done and removed from list (preserved for undo purposes)",
+                                                               "symbols": ["HIDDEN", "ACTIONABLE", "DONE", "ARCHIVED", "DELETED"]
+                                                       }
+                                               },
+                                               {
+                                                       "name": "title_DasH_long",
+                                                       "doc": "One-line summary of the item",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "name": "description",
+                                                       "doc": "Detailed description (may contain HTML markup)",
+                                                       "type": ["null", "string"]
+                                               },
+                                               {
+                                                       "name": "snoozeDate",
+                                                       "doc": "Timestamp (milliseconds since epoch) at which the item should go from `HIDDEN` to `ACTIONABLE` status",
+                                                       "type": ["null", "long"]
+                                               },
+                                               {
+                                                       "name": "subItems",
+                                                       "doc": "List of children of this to-do tree node",
+                                                       "type": {
+                                                               "type": "array",
+                                                               "items": "ToDoItem"
+                                                       }
+                                               }
+                                               ]
+                               }
+                       }
+               }
+               ]
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/RecordExampleVPN.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/RecordExampleVPN.avsc
new file mode 100644 (file)
index 0000000..b9aac36
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "type"      : "record",
+  "name"      : "VPNActEvent",
+  "namespace" : "com.ericsson.apex.domains.vpn.events",
+  "fields"    : [
+    {"name": "nameSpace", "type": "string"},
+    {"name": "name",      "type": "string"},
+    {"name": "version",   "type": "string"},
+    {"name": "source",    "type": "string"},
+    {"name": "target",    "type": "string"},
+    {"name": "LinkMap", "type": {
+        "type" : "record",
+        "name" : "LinkMap",
+        "namespace" : "com.ericsson.apex.domains.vpn",
+        "fields" : [ ]
+      }
+    },
+    {"name": "CustomerMap", "type": {
+        "type" : "record",
+        "name" : "CustomerMap",
+        "namespace" : "com.ericsson.apex.domains.vpn",
+        "fields" : [ ]
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/RecordExampleVPNReuse.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/RecordExampleVPNReuse.avsc
new file mode 100644 (file)
index 0000000..5936bb2
--- /dev/null
@@ -0,0 +1,34 @@
+{
+       "type"      : "record",
+       "name"      : "VPNActEvent",
+       "namespace" : "com.ericsson.apex.domains.vpn.events",
+       "fields"    : [
+               {"name": "nameSpace", "type": "string"},
+               {"name": "name",      "type": "string"},
+               {"name": "version",   "type": "string"},
+               {"name": "source",    "type": "string"},
+               {"name": "target",    "type": "string"},
+               {"name": "LinkMap", "type": {
+                       "type" : "record",
+                       "name" : "LinkMap",
+                       "namespace" : "com.ericsson.apex.domains.vpn",
+                       "fields" : [ ]
+               }
+               },
+               {"name": "CustomerMap", "type": {
+                       "type" : "record",
+                       "name" : "CustomerMap",
+                       "namespace" : "com.ericsson.apex.domains.vpn",
+                       "fields" : [ ]
+               }
+               },
+               {"name": "CustomerMap1", "type": "com.ericsson.apex.domains.vpn.CustomerMap"},
+               {
+                       "name" : "CustomerMapArray",
+                       "type": {
+                               "type": "array",
+                               "items": "com.ericsson.apex.domains.vpn.CustomerMap"
+                       }
+               }
+       ]
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/UnionExample.avsc b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/avsc/UnionExample.avsc
new file mode 100644 (file)
index 0000000..96b6050
--- /dev/null
@@ -0,0 +1,30 @@
+{
+       "namespace": "example.avro",
+       "type": "record",
+       "name": "User",
+       "fields": [
+               {
+                       "name": "name",
+                       "type": "string"
+               },
+               {
+                       "name": "favourite_number",
+                       "type": [
+                               "null",
+                               "int"
+                       ]
+               },
+               {
+                       "name": "favourite_colour",
+                       "type": [
+                               "null",
+                               "string"
+                       ]
+               },
+               {
+                       "name": "favourite_group",
+                       "type": ["null", "string"],
+                       "default": "null"
+               }
+       ]
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/AAIResponse4Policy.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/AAIResponse4Policy.json
new file mode 100644 (file)
index 0000000..25ca3af
--- /dev/null
@@ -0,0 +1,20 @@
+[
+       {
+               "model-name": "service-instance",
+               "generic-vnf": {
+                       "vnf-id": "de7cc3ab-0212-47df-9e64-da1c79234deb",
+                       "vnf-name": "ZRDM2MMEX39",
+                       "vnf-type": "vMME Svc Jul 14/vMME VF Jul 14 1",
+                       "service-id": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb",
+                       "orchestration-status": "active",
+                       "in-maint": false,
+                       "is-closed-loop-disabled": false,
+                       "resource-version": "1503082370097",
+                       "model-invariant-id": "82194af1-3c2c-485a-8f44-420e22a9eaa4",
+                       "model-version-id": "46b92144-923a-4d20-b85a-3cbd847668a9"
+               },
+               "extra-properties": {
+                       
+               }
+       }
+]
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/AAIResponse4VNF.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/AAIResponse4VNF.json
new file mode 100644 (file)
index 0000000..41cfc5c
--- /dev/null
@@ -0,0 +1,302 @@
+[
+       {
+               "model-name": "vFW",
+               "generic-vnf": {
+                       "vnf-id": "vFirewall_demo_app",
+                       "vnf-name": "vFirewall_demo_app",
+                       "vnf-type": "vFW",
+                       "service-id": "vFirewall_demo_app",
+                       "orchestration-status": "running",
+                       "in-maint": false,
+                       "is-closed-loop-disabled": false,
+                       "resource-version": "1509456799110",
+                       "model-invariant-id": "vFirewall",
+                       "model-version-id": "vFW"
+               },
+               "extra-properties": {
+                       
+               },
+               "inventory-response-items": {
+                       "inventory-response-item": [
+                               {
+                                       "vserver": {
+                                               "vserver-id": "5b06cf36-40a0-4bcb-bde9-849aa4702d67",
+                                               "vserver-name": "vFW",
+                                               "vserver-name2": "vFW",
+                                               "prov-status": "Running",
+                                               "vserver-selflink": "http://10.12.25.2:8774/v2.1/466979b815b5415ba14ada713e6e1846/servers/5b06cf36-40a0-4bcb-bde9-849aa4702d67",
+                                               "in-maint": false,
+                                               "is-closed-loop-disabled": false,
+                                               "resource-version": "1509047869791"
+                                       },
+                                       "extra-properties": {
+                                               
+                                       },
+                                       "inventory-response-items": {
+                                               "inventory-response-item": [
+                                                       {
+                                                               "vnfc": {
+                                                                       "vnfc-name": "VNFC_vGMUX_demo_app2",
+                                                                       "nfc-naming-code": "vGMUXCODE2",
+                                                                       "nfc-function": "vGMUX",
+                                                                       "prov-status": "Running",
+                                                                       "orchestration-status": "Error",
+                                                                       "in-maint": false,
+                                                                       "is-closed-loop-disabled": false,
+                                                                       "resource-version": "1509407048855"
+                                                               },
+                                                               "extra-properties": {
+                                                                       
+                                                               }
+                                                       },
+                                                       {
+                                                               "tenant": {
+                                                                       "tenant-id": "466979b815b5415ba14ada713e6e1846",
+                                                                       "tenant-name": "Integration",
+                                                                       "resource-version": "1508920100541"
+                                                               },
+                                                               "extra-properties": {
+                                                                       
+                                                               },
+                                                               "inventory-response-items": {
+                                                                       "inventory-response-item": [
+                                                                               {
+                                                                                       "cloud-region": {
+                                                                                               "cloud-owner": "pod25",
+                                                                                               "cloud-region-id": "RegionOne",
+                                                                                               "identity-url": "http://10.12.25.2:5000/v3",
+                                                                                               "sriov-automation": false,
+                                                                                               "resource-version": "1509048416263"
+                                                                                       },
+                                                                                       "extra-properties": {
+                                                                                               
+                                                                                       },
+                                                                                       "inventory-response-items": {
+                                                                                               "inventory-response-item": [
+                                                                                                       {
+                                                                                                               "esr-system-info": {
+                                                                                                                       "esr-system-info-id": "432ac032-e996-41f2-84ed-9c7a1766eb29",
+                                                                                                                       "system-name": "example-system-name-val-29070",
+                                                                                                                       "type": "example-type-val-85254",
+                                                                                                                       "vendor": "example-vendor-val-94515",
+                                                                                                                       "version": "example-version-val-71880",
+                                                                                                                       "service-url": "http://10.12.25.2:5000/v3",
+                                                                                                                       "user-name": "demo",
+                                                                                                                       "password": "onapdemo",
+                                                                                                                       "system-type": "VIM",
+                                                                                                                       "ssl-cacert": "example-ssl-cacert-val-75021",
+                                                                                                                       "ssl-insecure": true,
+                                                                                                                       "ip-address": "example-ip-address-val-44431",
+                                                                                                                       "port": "example-port-val-93234",
+                                                                                                                       "cloud-domain": "Default",
+                                                                                                                       "default-tenant": "Integration",
+                                                                                                                       "resource-version": "1508920101033"
+                                                                                                               },
+                                                                                                               "extra-properties": {
+                                                                                                                       
+                                                                                                               }
+                                                                                                       }
+                                                                                               ]
+                                                                                       }
+                                                                               }
+                                                                       ]
+                                                               }
+                                                       }
+                                               ]
+                                       }
+                               },
+                               {
+                                       "vserver": {
+                                               "vserver-id": "0c52905c-f682-42cf-bd52-e7f8953e80e3",
+                                               "vserver-name": "vFW",
+                                               "vserver-name2": "vFW",
+                                               "prov-status": "Running",
+                                               "vserver-selflink": "http://10.12.25.2:8774/v2.1/466979b815b5415ba14ada713e6e1846/servers/0c52905c-f682-42cf-bd52-e7f8953e80e3",
+                                               "in-maint": false,
+                                               "is-closed-loop-disabled": false,
+                                               "resource-version": "1509047548567"
+                                       },
+                                       "extra-properties": {
+                                               
+                                       },
+                                       "inventory-response-items": {
+                                               "inventory-response-item": [
+                                                       {
+                                                               "vnfc": {
+                                                                       "vnfc-name": "VNFC_vGMUX_demo_app3",
+                                                                       "nfc-naming-code": "vGMUXCODE3",
+                                                                       "nfc-function": "vGMUX",
+                                                                       "prov-status": "Running",
+                                                                       "orchestration-status": "Running",
+                                                                       "in-maint": false,
+                                                                       "is-closed-loop-disabled": false,
+                                                                       "resource-version": "1509041912808"
+                                                               },
+                                                               "extra-properties": {
+                                                                       
+                                                               }
+                                                       },
+                                                       {
+                                                               "tenant": {
+                                                                       "tenant-id": "466979b815b5415ba14ada713e6e1846",
+                                                                       "tenant-name": "Integration",
+                                                                       "resource-version": "1508920100541"
+                                                               },
+                                                               "extra-properties": {
+                                                                       
+                                                               },
+                                                               "inventory-response-items": {
+                                                                       "inventory-response-item": [
+                                                                               {
+                                                                                       "cloud-region": {
+                                                                                               "cloud-owner": "pod25",
+                                                                                               "cloud-region-id": "RegionOne",
+                                                                                               "identity-url": "http://10.12.25.2:5000/v3",
+                                                                                               "sriov-automation": false,
+                                                                                               "resource-version": "1509048416263"
+                                                                                       },
+                                                                                       "extra-properties": {
+                                                                                               
+                                                                                       },
+                                                                                       "inventory-response-items": {
+                                                                                               "inventory-response-item": [
+                                                                                                       {
+                                                                                                               "esr-system-info": {
+                                                                                                                       "esr-system-info-id": "432ac032-e996-41f2-84ed-9c7a1766eb29",
+                                                                                                                       "system-name": "example-system-name-val-29070",
+                                                                                                                       "type": "example-type-val-85254",
+                                                                                                                       "vendor": "example-vendor-val-94515",
+                                                                                                                       "version": "example-version-val-71880",
+                                                                                                                       "service-url": "http://10.12.25.2:5000/v3",
+                                                                                                                       "user-name": "demo",
+                                                                                                                       "password": "onapdemo",
+                                                                                                                       "system-type": "VIM",
+                                                                                                                       "ssl-cacert": "example-ssl-cacert-val-75021",
+                                                                                                                       "ssl-insecure": true,
+                                                                                                                       "ip-address": "example-ip-address-val-44431",
+                                                                                                                       "port": "example-port-val-93234",
+                                                                                                                       "cloud-domain": "Default",
+                                                                                                                       "default-tenant": "Integration",
+                                                                                                                       "resource-version": "1508920101033"
+                                                                                                               },
+                                                                                                               "extra-properties": {
+                                                                                                                       
+                                                                                                               }
+                                                                                                       }
+                                                                                               ]
+                                                                                       }
+                                                                               }
+                                                                       ]
+                                                               }
+                                                       }
+                                               ]
+                                       }
+                               },
+                               {
+                                       "vserver": {
+                                               "vserver-id": "33e16e02-098a-4f4e-a37f-b4e0307596c0",
+                                               "vserver-name": "vFW",
+                                               "vserver-name2": "vFW",
+                                               "prov-status": "Running",
+                                               "vserver-selflink": "http://10.12.25.2:8774/v2.1/466979b815b5415ba14ada713e6e1846/servers/33e16e02-098a-4f4e-a37f-b4e0307596c0",
+                                               "in-maint": false,
+                                               "is-closed-loop-disabled": false,
+                                               "resource-version": "1509047285114"
+                                       },
+                                       "extra-properties": {
+                                               
+                                       },
+                                       "inventory-response-items": {
+                                               "inventory-response-item": [
+                                                       {
+                                                               "vnfc": {
+                                                                       "vnfc-name": "vnfc-related-to-vserver-example",
+                                                                       "nfc-naming-code": "example-nfc-naming-code-val-78172",
+                                                                       "nfc-function": "example-nfc-function-val-56352",
+                                                                       "prov-status": "example-prov-status-val-10699",
+                                                                       "orchestration-status": "example-orchestration-status-val-68896",
+                                                                       "ipaddress-v4-oam-vip": "example-ipaddress-v4-oam-vip-val-71483",
+                                                                       "in-maint": true,
+                                                                       "is-closed-loop-disabled": true,
+                                                                       "group-notation": "example-group-notation-val-31912",
+                                                                       "resource-version": "1508800709772"
+                                                               },
+                                                               "extra-properties": {
+                                                                       
+                                                               }
+                                                       },
+                                                       {
+                                                               "vnfc": {
+                                                                       "vnfc-name": "VNFC_vGMUX_demo_app",
+                                                                       "nfc-naming-code": "vGMUXCODE",
+                                                                       "nfc-function": "vGMUX",
+                                                                       "prov-status": "Running",
+                                                                       "orchestration-status": "Running",
+                                                                       "in-maint": false,
+                                                                       "is-closed-loop-disabled": false,
+                                                                       "resource-version": "1509041573965"
+                                                               },
+                                                               "extra-properties": {
+                                                                       
+                                                               }
+                                                       },
+                                                       {
+                                                               "tenant": {
+                                                                       "tenant-id": "466979b815b5415ba14ada713e6e1846",
+                                                                       "tenant-name": "Integration",
+                                                                       "resource-version": "1508920100541"
+                                                               },
+                                                               "extra-properties": {
+                                                                       
+                                                               },
+                                                               "inventory-response-items": {
+                                                                       "inventory-response-item": [
+                                                                               {
+                                                                                       "cloud-region": {
+                                                                                               "cloud-owner": "pod25",
+                                                                                               "cloud-region-id": "RegionOne",
+                                                                                               "identity-url": "http://10.12.25.2:5000/v3",
+                                                                                               "sriov-automation": false,
+                                                                                               "resource-version": "1509048416263"
+                                                                                       },
+                                                                                       "extra-properties": {
+                                                                                               
+                                                                                       },
+                                                                                       "inventory-response-items": {
+                                                                                               "inventory-response-item": [
+                                                                                                       {
+                                                                                                               "esr-system-info": {
+                                                                                                                       "esr-system-info-id": "432ac032-e996-41f2-84ed-9c7a1766eb29",
+                                                                                                                       "system-name": "example-system-name-val-29070",
+                                                                                                                       "type": "example-type-val-85254",
+                                                                                                                       "vendor": "example-vendor-val-94515",
+                                                                                                                       "version": "example-version-val-71880",
+                                                                                                                       "service-url": "http://10.12.25.2:5000/v3",
+                                                                                                                       "user-name": "demo",
+                                                                                                                       "password": "onapdemo",
+                                                                                                                       "system-type": "VIM",
+                                                                                                                       "ssl-cacert": "example-ssl-cacert-val-75021",
+                                                                                                                       "ssl-insecure": true,
+                                                                                                                       "ip-address": "example-ip-address-val-44431",
+                                                                                                                       "port": "example-port-val-93234",
+                                                                                                                       "cloud-domain": "Default",
+                                                                                                                       "default-tenant": "Integration",
+                                                                                                                       "resource-version": "1508920101033"
+                                                                                                               },
+                                                                                                               "extra-properties": {
+                                                                                                                       
+                                                                                                               }
+                                                                                                       }
+                                                                                               ]
+                                                                                       }
+                                                                               }
+                                                                       ]
+                                                               }
+                                                       }
+                                               ]
+                                       }
+                               }
+                       ]
+               }
+       }
+]
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/AAIResponseExample.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/AAIResponseExample.json
new file mode 100644 (file)
index 0000000..a1a1e19
--- /dev/null
@@ -0,0 +1,209 @@
+{
+       "inventory-response-item": [
+               {
+                       "vserver": {
+                               "vserver-id": "6ed3642c-f7a1-4a7c-9290-3d51fe1531eb",
+                               "vserver-name": "zdfw1lb01lb02",
+                               "vserver-name2": "zdfw1lb01lb02",
+                               "prov-status": "ACTIVE",
+                               "vserver-selflink": "http://10.12.25.2:8774/v2.1/41d6d38489bd40b09ea8a6b6b852dcbd/servers/6ed3642c-f7a1-4a7c-9290-3d51fe1531eb",
+                               "in-maint": false,
+                               "is-closed-loop-disabled": false,
+                               "resource-version": "1510606403522"
+                       },
+                       "extra-properties": {
+                               
+                       },
+                       "inventory-response-items": {
+                               "inventory-response-item": [
+                                       {
+                                               "model-name": "vLoadBalancer",
+                                               "generic-vnf": {
+                                                       "vnf-id": "db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+                                                       "vnf-name": "Vfmodule_vLB1113",
+                                                       "vnf-type": "vLoadBalancer-1106/vLoadBalancer 0",
+                                                       "service-id": "66f157fc-4148-4880-95f5-e120677e98d1",
+                                                       "prov-status": "PREPROV",
+                                                       "orchestration-status": "Created",
+                                                       "in-maint": false,
+                                                       "is-closed-loop-disabled": false,
+                                                       "resource-version": "1510604011851",
+                                                       "model-invariant-id": "cee050ed-92a5-494f-ab04-234307a846dc",
+                                                       "model-version-id": "fd65becc-6b2c-4fe8-ace9-cc29db9a3da2",
+                                                       "model-customization-id": "1983c783-444f-4e79-af3a-85e5d49628f3",
+                                                       "nf-type": "",
+                                                       "nf-function": "",
+                                                       "nf-role": "",
+                                                       "nf-naming-code": ""
+                                               },
+                                               "extra-properties": {
+                                                       "extra-property": [
+                                                               {
+                                                                       "property-name": "model-ver.model-version-id",
+                                                                       "property-value": "fd65becc-6b2c-4fe8-ace9-cc29db9a3da2"
+                                                               },
+                                                               {
+                                                                       "property-name": "model-ver.model-name",
+                                                                       "property-value": "vLoadBalancer"
+                                                               },
+                                                               {
+                                                                       "property-name": "model.model-type",
+                                                                       "property-value": "resource"
+                                                               },
+                                                               {
+                                                                       "property-name": "model.model-invariant-id",
+                                                                       "property-value": "cee050ed-92a5-494f-ab04-234307a846dc"
+                                                               },
+                                                               {
+                                                                       "property-name": "model-ver.model-version",
+                                                                       "property-value": "1.0"
+                                                               }
+                                                       ]
+                                               },
+                                               "inventory-response-items": {
+                                                       "inventory-response-item": [
+                                                               {
+                                                                       "model-name": "vLoadBalancer-1106",
+                                                                       "service-instance": {
+                                                                               "service-instance-id": "3b12f31f-8f2d-4f5c-b875-61ff1194b941",
+                                                                               "service-instance-name": "vLoadBalancer-1113",
+                                                                               "model-invariant-id": "1321d60d-f7ff-4300-96c2-6bf0b3268b7a",
+                                                                               "model-version-id": "732d4692-4b97-46f9-a996-0b3339e88c50",
+                                                                               "resource-version": "1510603936425"
+                                                                       },
+                                                                       "extra-properties": {
+                                                                               "extra-property": [
+                                                                                       {
+                                                                                               "property-name": "model-ver.model-version-id",
+                                                                                               "property-value": "732d4692-4b97-46f9-a996-0b3339e88c50"
+                                                                                       },
+                                                                                       {
+                                                                                               "property-name": "model-ver.model-name",
+                                                                                               "property-value": "vLoadBalancer-1106"
+                                                                                       },
+                                                                                       {
+                                                                                               "property-name": "model.model-type",
+                                                                                               "property-value": "service"
+                                                                                       },
+                                                                                       {
+                                                                                               "property-name": "model.model-invariant-id",
+                                                                                               "property-value": "1321d60d-f7ff-4300-96c2-6bf0b3268b7a"
+                                                                                       },
+                                                                                       {
+                                                                                               "property-name": "model-ver.model-version",
+                                                                                               "property-value": "1.0"
+                                                                                       }
+                                                                               ]
+                                                                       }
+                                                               },
+                                                               {
+                                                                       "model-name": "Vloadbalancer..base_vlb..module-0",
+                                                                       "vf-module": {
+                                                                               "vf-module-id": "e6b3e3eb-34e1-4c00-b8c1-2a4fbe479b12",
+                                                                               "vf-module-name": "Vfmodule_vLB1113-1",
+                                                                               "heat-stack-id": "Vfmodule_vLB1113-1/3dd6d900-772f-4fcc-a0cb-e250ab2bb4db",
+                                                                               "orchestration-status": "active",
+                                                                               "is-base-vf-module": true,
+                                                                               "resource-version": "1510604612557",
+                                                                               "model-invariant-id": "6d760188-9a24-451a-b05b-e08b86cb94f2",
+                                                                               "model-version-id": "93facad9-55f2-4fe0-9574-814c2bc2d071",
+                                                                               "model-customization-id": "93fd5bd4-8051-4074-8530-c0c504604df5",
+                                                                               "module-index": 0
+                                                                       },
+                                                                       "extra-properties": {
+                                                                               "extra-property": [
+                                                                                       {
+                                                                                               "property-name": "model-ver.model-version-id",
+                                                                                               "property-value": "93facad9-55f2-4fe0-9574-814c2bc2d071"
+                                                                                       },
+                                                                                       {
+                                                                                               "property-name": "model-ver.model-name",
+                                                                                               "property-value": "Vloadbalancer..base_vlb..module-0"
+                                                                                       },
+                                                                                       {
+                                                                                               "property-name": "model.model-type",
+                                                                                               "property-value": "resource"
+                                                                                       },
+                                                                                       {
+                                                                                               "property-name": "model.model-invariant-id",
+                                                                                               "property-value": "6d760188-9a24-451a-b05b-e08b86cb94f2"
+                                                                                       },
+                                                                                       {
+                                                                                               "property-name": "model-ver.model-version",
+                                                                                               "property-value": "1"
+                                                                                       }
+                                                                               ]
+                                                                       }
+                                                               },
+                                                               {
+                                                                       "model-name": "Vloadbalancer..dnsscaling..module-1",
+                                                                       "vf-module": {
+                                                                               "vf-module-id": "dummy_db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+                                                                               "vf-module-name": "dummy_db373a8d-f7be-4d02-8ac8-6ca4c305d144",
+                                                                               "is-base-vf-module": false,
+                                                                               "resource-version": "1510610079687",
+                                                                               "model-invariant-id": "356a1cff-71f2-4086-9980-a2927ce11c1c",
+                                                                               "model-version-id": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+                                                                       },
+                                                                       "extra-properties": {
+                                                                               "extra-property": [
+                                                                                       {
+                                                                                               "property-name": "model-ver.model-version-id",
+                                                                                               "property-value": "6b93d804-cfc8-4be3-92cc-9336d135859a"
+                                                                                       },
+                                                                                       {
+                                                                                               "property-name": "model-ver.model-name",
+                                                                                               "property-value": "Vloadbalancer..dnsscaling..module-1"
+                                                                                       },
+                                                                                       {
+                                                                                               "property-name": "model.model-type",
+                                                                                               "property-value": "resource"
+                                                                                       },
+                                                                                       {
+                                                                                               "property-name": "model.model-invariant-id",
+                                                                                               "property-value": "356a1cff-71f2-4086-9980-a2927ce11c1c"
+                                                                                       },
+                                                                                       {
+                                                                                               "property-name": "model-ver.model-version",
+                                                                                               "property-value": "1"
+                                                                                       }
+                                                                               ]
+                                                                       }
+                                                               }
+                                                       ]
+                                               }
+                                       },
+                                       {
+                                               "tenant": {
+                                                       "tenant-id": "41d6d38489bd40b09ea8a6b6b852dcbd",
+                                                       "tenant-name": "Integration-SB-00",
+                                                       "resource-version": "1509587770200"
+                                               },
+                                               "extra-properties": {
+                                                       
+                                               },
+                                               "inventory-response-items": {
+                                                       "inventory-response-item": [
+                                                               {
+                                                                       "cloud-region": {
+                                                                               "cloud-owner": "CloudOwner",
+                                                                               "cloud-region-id": "RegionOne",
+                                                                               "cloud-type": "SharedNode",
+                                                                               "owner-defined-type": "OwnerType",
+                                                                               "cloud-region-version": "v1",
+                                                                               "cloud-zone": "CloudZone",
+                                                                               "sriov-automation": false,
+                                                                               "resource-version": "1509587770092"
+                                                                       },
+                                                                       "extra-properties": {
+                                                                               
+                                                                       }
+                                                               }
+                                                       ]
+                                               }
+                                       }
+                               ]
+                       }
+               }
+       ]
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/ArrayExampleAddressFull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/ArrayExampleAddressFull.json
new file mode 100644 (file)
index 0000000..9ad632a
--- /dev/null
@@ -0,0 +1,13 @@
+[ {
+  "streetaddress" : "1600 Pennsylvania Avenue",
+  "city" : "Washington DC"
+}, {
+  "streetaddress" : "Somewhere",
+  "city" : "Over the rainbow"
+}, {
+  "streetaddress" : "221 B Baker St.",
+  "city" : "London"
+}, {
+  "streetaddress" : "Wayne Manor",
+  "city" : "Gotham City"
+} ]
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/ArrayExampleAddressNull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/ArrayExampleAddressNull.json
new file mode 100644 (file)
index 0000000..8878e54
--- /dev/null
@@ -0,0 +1 @@
+[ ]
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/ArrayExampleLongFull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/ArrayExampleLongFull.json
new file mode 100644 (file)
index 0000000..ca12244
--- /dev/null
@@ -0,0 +1 @@
+[ 9223372036854775807, -3, -2, 1, -9223372036854775808, -67890, 5, 0 ]
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/ArrayExampleLongNull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/ArrayExampleLongNull.json
new file mode 100644 (file)
index 0000000..8878e54
--- /dev/null
@@ -0,0 +1 @@
+[ ]
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/EnumExampleBad0.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/EnumExampleBad0.json
new file mode 100644 (file)
index 0000000..d1218ca
--- /dev/null
@@ -0,0 +1 @@
+"TWEED"
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/EnumExampleBad1.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/EnumExampleBad1.json
new file mode 100644 (file)
index 0000000..67b3fe5
--- /dev/null
@@ -0,0 +1 @@
+"Hearts"
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/EnumExampleHearts.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/EnumExampleHearts.json
new file mode 100644 (file)
index 0000000..92bd68a
--- /dev/null
@@ -0,0 +1 @@
+"HEARTS"
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/EnumExampleNull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/EnumExampleNull.json
new file mode 100644 (file)
index 0000000..ec747fa
--- /dev/null
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/FixedExampleBad0.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/FixedExampleBad0.json
new file mode 100644 (file)
index 0000000..f0251f1
--- /dev/null
@@ -0,0 +1 @@
+"BADBAD"
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/FixedExampleBad1.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/FixedExampleBad1.json
new file mode 100644 (file)
index 0000000..687d142
--- /dev/null
@@ -0,0 +1 @@
+"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0"
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/FixedExampleGood.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/FixedExampleGood.json
new file mode 100644 (file)
index 0000000..846002e
--- /dev/null
@@ -0,0 +1 @@
+"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/FixedExampleNull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/FixedExampleNull.json
new file mode 100644 (file)
index 0000000..ec747fa
--- /dev/null
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/HealthCheckEvent.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/HealthCheckEvent.json
new file mode 100644 (file)
index 0000000..4233f3b
--- /dev/null
@@ -0,0 +1,22 @@
+{
+       "input": {
+               "action": "HealthCheck",
+               "action-identifiers": {
+                       "vnf-id": "49414df5-3482-4fd8-9952-c463dff2770b"
+               },
+               "common-header": {
+                       "request-id": "afr-request3",
+                       "originator-id": "AFR",
+                       "api-ver": "2.15",
+                       "sub-request-id": "AFR-subrequest",
+                       "timestamp": "2017-11-06T15:15:18.97Z",
+                       "flags": {
+                               "ttl": "10000",
+                               "force": "TRUE",
+                               "mode": "EXCLUSIVE"
+                       }
+               },
+               "payload": "{\"host-ip-address\":\"131.160.203.125\",\"input.url\":\"131.160.203.125/afr\",\"request-action-type\":\"GET\",\"request-action\":\"AFR\"}"
+       }
+}
+
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleAddressFull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleAddressFull.json
new file mode 100644 (file)
index 0000000..2a19114
--- /dev/null
@@ -0,0 +1,18 @@
+{
+       "address0" : {
+               "streetaddress" : "1600 Pennsylvania Avenue",
+               "city" : "Washington DC"
+       },
+       "address1" : {
+               "streetaddress" : "Somewhere",
+               "city" : "Over the rainbow"
+       },
+       "address2" : {
+               "streetaddress" : "221 B Baker St.",
+               "city" : "London"
+       },
+       "address3" : {
+               "streetaddress" : "Wayne Manor",
+               "city" : "Gotham City"
+       }
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleAddressInvalidFields.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleAddressInvalidFields.json
new file mode 100644 (file)
index 0000000..fa23c83
--- /dev/null
@@ -0,0 +1,18 @@
+{
+       "address.0" : {
+               "street-address" : "1600 Pennsylvania Avenue",
+               "the.city" : "Washington DC"
+       },
+       "address.1" : {
+               "street-address" : "Somewhere",
+               "the.city" : "Over the rainbow"
+       },
+       "address.2" : {
+               "street-address" : "221 B Baker St.",
+               "the.city" : "London"
+       },
+       "address.3" : {
+               "street-address" : "Wayne Manor",
+               "the.city" : "Gotham City"
+       }
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleAddressNull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleAddressNull.json
new file mode 100644 (file)
index 0000000..9e26dfe
--- /dev/null
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleLongFull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleLongFull.json
new file mode 100644 (file)
index 0000000..f94a4f6
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "key04" : 9223372036854775807,
+  "key03" : -3,
+  "key02" : -2,
+  "key01" : 1,
+  "key07" : -9223372036854775808,
+  "key06" : -67890,
+  "key05" : 5,
+  "key00" : 0
+}
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleLongNull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/MapExampleLongNull.json
new file mode 100644 (file)
index 0000000..9e26dfe
--- /dev/null
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/RecordExampleFull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/RecordExampleFull.json
new file mode 100644 (file)
index 0000000..d4fbf10
--- /dev/null
@@ -0,0 +1,41 @@
+{
+  "firstname" : "Liam",
+  "lastname" : "Fallon",
+  "address" : {
+    "streetaddress" : "Somewhere",
+    "city" : "Over the rainbow"
+  },
+  "id" : 1497,
+  "username" : "eeilfn",
+  "passwordHash" : "gobbledygook",
+  "signupDate" : 894614400,
+  "emailAddresses" : [ {
+    "address" : "sean@citizen.ie",
+    "verified" : true,
+    "dateAdded" : 1495805460,
+    "dateBounced" : {
+      "long" : 1495805460
+    }
+  } ],
+  "twitterAccounts" : [ {
+    "status" : "ACTIVE",
+    "userId" : 12345,
+    "screenName" : "Zooby",
+    "oauthToken" : "ZoobyOToken",
+    "oauthTokenSecret" : {
+      "string" : "ZoobyOTokenSecret"
+    },
+    "dateAuthorized" : 149580546
+  } ],
+  "toDoItems" : [ {
+    "status" : "DONE",
+    "title" : "fierce important thing",
+    "description" : {
+      "string" : "Description of fierce important thing"
+    },
+    "snoozeDate" : {
+      "long" : 149580567
+    },
+    "subItems" : [ ]
+  } ]
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/RecordExampleInvalidFields.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/RecordExampleInvalidFields.json
new file mode 100644 (file)
index 0000000..f40075e
--- /dev/null
@@ -0,0 +1,41 @@
+{
+  "firstname" : "Liam",
+  "lastname" : "Fallon",
+  "address" : {
+    "streetaddress-1" : "Somewhere",
+    "city" : "Over the rainbow"
+  },
+  "id" : 1497,
+  "username" : "eeilfn",
+  "passwordHash" : "gobbledygook",
+  "signupDate" : 894614400,
+  "email.Addresses" : [ {
+    "address" : "sean@citizenie",
+    "verified" : true,
+    "dateAdded" : 1495805460,
+    "dateBounced" : {
+      "long" : 1495805460
+    }
+  } ],
+  "twitterAccounts" : [ {
+    "status" : "ACTIVE",
+    "userId" : 12345,
+    "screenName" : "Zooby",
+    "oauthToken" : "ZoobyOToken",
+    "oauthTokenSecret" : {
+      "string" : "ZoobyOTokenSecret"
+    },
+    "dateAuthorized" : 149580546
+  } ],
+  "toDoItems" : [ {
+    "status" : "DONE",
+    "title-long" : "fierce important thing",
+    "description" : {
+      "string" : "Description of fierce important thing"
+    },
+    "snoozeDate" : {
+      "long" : 149580567
+    },
+    "subItems" : [ ]
+  } ]
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/RecordExampleNull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/RecordExampleNull.json
new file mode 100644 (file)
index 0000000..03eef6c
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "firstname" : "",
+  "lastname" : "",
+  "address" : {
+    "streetaddress" : "",
+    "city" : ""
+  },
+  "id" : 0,
+  "username" : "",
+  "passwordHash" : "",
+  "signupDate" : 0,
+  "emailAddresses" : [ ],
+  "twitterAccounts" : [ ],
+  "toDoItems" : [ ]
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/RecordExampleVPNFull.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/RecordExampleVPNFull.json
new file mode 100644 (file)
index 0000000..7e4da33
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "nameSpace" : "com.ericsson.apex.domains.vpn.events",
+  "name" : "VPNTriggerEvent",
+  "version" : "0.0.1",
+  "source" : "VPNSLA",
+  "target" : "Apex",
+  "LinkMap" : { },
+  "CustomerMap" : { }
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/UnionExampleAllFields.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/UnionExampleAllFields.json
new file mode 100644 (file)
index 0000000..88299e3
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "name" : "Ben",
+  "favourite_number" : 7,
+  "favourite_colour" : "red",
+  "favourite_group" : "Zooby"
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/UnionExampleNullField.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/UnionExampleNullField.json
new file mode 100644 (file)
index 0000000..4fd33a6
--- /dev/null
@@ -0,0 +1,6 @@
+{
+       "name": "Alyssa",
+       "favourite_number": 256,
+       "favourite_colour": null,
+       "favourite_group": "U2"
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/UnionExampleOptionalField.json b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/data/UnionExampleOptionalField.json
new file mode 100644 (file)
index 0000000..f62d25b
--- /dev/null
@@ -0,0 +1,5 @@
+{
+       "name": "Claire",
+       "favourite_number": 123,
+       "favourite_colour": null
+}
\ No newline at end of file
diff --git a/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/logback-test.xml b/plugins/plugins-context/context-schema/context-schema-avro/src/test/resources/logback-test.xml
new file mode 100644 (file)
index 0000000..3dd11e9
--- /dev/null
@@ -0,0 +1,74 @@
+<?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>
+
+    <logger name="org.infinispan" level="INFO" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="org.apache.zookeeper.ClientCnxn" level="OFF" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+        <file>${LOG_DIR}/apex.log</file>
+        <encoder>
+            <pattern>%d %-5relative [procId=${processId}] [%thread] %-5level
+                %logger{26} - %msg %n %ex{full}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="CTXT_FILE" class="ch.qos.logback.core.FileAppender">
+        <file>${LOG_DIR}/apex_ctxt.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.core.context.impl.monitoring" level="TRACE" additivity="false">
+        <appender-ref ref="CTXT_FILE" />
+    </logger>
+
+    <logger name="org.onap.policy.apex.executionlogging.TaskExecutionLogging" level="TRACE" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="org.onap.policy.apex" level="TRACE" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+</configuration>
diff --git a/plugins/plugins-context/context-schema/pom.xml b/plugins/plugins-context/context-schema/pom.xml
new file mode 100644 (file)
index 0000000..f72ec15
--- /dev/null
@@ -0,0 +1,38 @@
+<!--
+  ============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=========================================================
+-->
+<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.plugins.plugins-context</groupId>
+        <artifactId>plugins-context</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-schema</groupId>
+    <artifactId>context-schema</artifactId>
+    <packaging>pom</packaging>
+
+    <name>${project.artifactId}</name>
+    <description>Plugins for 3pps that handle context schemas</description>
+    <modules>
+        <module>context-schema-avro</module>
+    </modules>
+</project>
\ No newline at end of file
diff --git a/plugins/plugins-context/plugins-context-test/pom.xml b/plugins/plugins-context/plugins-context-test/pom.xml
new file mode 100644 (file)
index 0000000..7239abe
--- /dev/null
@@ -0,0 +1,99 @@
+<!--
+  ============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.plugins.plugins-context</groupId>
+        <artifactId>plugins-context</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>plugins-context-test</artifactId>
+    <name>${project.artifactId}</name>
+    <description>[${project.parent.artifactId}] module to run context tests using various plugins</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.core</groupId>
+            <artifactId>core-infrastructure</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-distribution</groupId>
+            <artifactId>context-distribution-hazelcast</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-distribution</groupId>
+            <artifactId>context-distribution-infinispan</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-locking</groupId>
+            <artifactId>context-locking-curator</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.context-locking</groupId>
+            <artifactId>context-locking-hazelcast</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>org.apache.curator</groupId>
+            <artifactId>curator-test</artifactId>
+            <version>4.0.0</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-site-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                    <skipDeploy>true</skipDeploy>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <forkMode>always</forkMode>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/plugins/plugins-context/plugins-context-test/src/main/java/org/onap/policy/apex/plugins/context/test/HazelcastContextInjection.java b/plugins/plugins-context/plugins-context-test/src/main/java/org/onap/policy/apex/plugins/context/test/HazelcastContextInjection.java
new file mode 100644 (file)
index 0000000..4c21103
--- /dev/null
@@ -0,0 +1,162 @@
+/*-
+ * ============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.plugins.context.test;
+
+import java.util.Map.Entry;
+import java.util.Random;
+
+import org.onap.policy.apex.context.ContextAlbum;
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.context.Distributor;
+import org.onap.policy.apex.context.impl.distribution.DistributorFactory;
+import org.onap.policy.apex.context.parameters.ContextParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxKeyInformation;
+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.contextmodel.concepts.AxContextModel;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+
+/**
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public final class HazelcastContextInjection {
+    private static final int ONE_SECOND = 1000;
+    private static final int SIXTY_SECONDS = 60;
+    private static final int MAX_INT_10000 = 10000;
+
+    /**
+     * Default constructor is private to avoid subclassing.
+     */
+    private HazelcastContextInjection() {}
+
+    /**
+     * The main method.
+     * 
+     * @param args the arguments to the method
+     * @throws ContextException exceptions thrown on context injection
+     */
+    public static void main(final String[] args) throws ContextException {
+        // For convenience, I created model programmatically, it can of course be read in from a
+        // policy model
+        final AxContextModel contextModel = createContextModel();
+
+        // The model must be registered in the model service.
+        ModelService.registerModel(AxContextSchemas.class, contextModel.getSchemas());
+        ModelService.registerModel(AxContextAlbums.class, contextModel.getAlbums());
+
+        // Configure APex to use Hazelcast distribution and locking
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters()
+                .setPluginClass("com.ericsson.apex.plugins.context.distribution.hazelcast.HazelcastContextDistributor");
+        contextParameters.getLockManagerParameters()
+                .setPluginClass("com.ericsson.apex.plugins.context.locking.hazelcast.HazelcastLockManager");
+
+        // Fire up our distribution
+        final AxArtifactKey distributorKey = new AxArtifactKey("ApexDistributor", "0.0.1");
+        final Distributor contextDistributor = new DistributorFactory().getDistributor(distributorKey);
+        contextDistributor.init(distributorKey);
+
+        // Now, get a handle on the album
+        final ContextAlbum myContextAlbum =
+                contextDistributor.createContextAlbum(new AxArtifactKey("LongContextAlbum", "0.0.1"));
+
+        final int jvmID = new Random().nextInt(MAX_INT_10000);
+        final String myLongKey = "MyLong_" + jvmID;
+        final String commonLongKey = "CommonLong";
+
+        // Put the long value for this JVM into the map
+        myContextAlbum.put(myLongKey, new Long(0L));
+
+        // Put the common long value to be used across JVMS in the map if its not htere already
+        myContextAlbum.lockForWriting(commonLongKey);
+        if (myContextAlbum.get(commonLongKey) == null) {
+            myContextAlbum.put(commonLongKey, new Long(0L));
+        }
+        myContextAlbum.unlockForWriting(commonLongKey);
+
+        // Run for 60 seconds to show multi JVM
+        for (int i = 0; i < SIXTY_SECONDS; i++) {
+            System.out.println("JVM " + jvmID + " iteration " + i);
+
+            for (final Entry<String, Object> albumEntry : myContextAlbum.entrySet()) {
+                myContextAlbum.lockForReading(albumEntry.getKey());
+                System.out.println(albumEntry.getKey() + "-->" + albumEntry.getValue());
+                myContextAlbum.unlockForReading(albumEntry.getKey());
+            }
+            System.out.println("old " + myLongKey + ": " + myContextAlbum.get(myLongKey));
+
+            myContextAlbum.lockForReading(commonLongKey);
+            System.out.println("old CommonLong: " + myContextAlbum.get(commonLongKey));
+            myContextAlbum.unlockForReading(commonLongKey);
+
+            Long myLong = (Long) myContextAlbum.get(myLongKey);
+            myLong++;
+            myContextAlbum.put(myLongKey, myLong);
+
+            myContextAlbum.lockForWriting(commonLongKey);
+            Long commonLong = (Long) myContextAlbum.get(commonLongKey);
+            commonLong++;
+            myContextAlbum.put(commonLongKey, commonLong);
+            myContextAlbum.unlockForWriting(commonLongKey);
+
+            System.out.println("new myLong: " + myContextAlbum.get(myLongKey));
+            System.out.println("new commonLong: " + myContextAlbum.get(commonLongKey));
+
+            try {
+                Thread.sleep(ONE_SECOND);
+            } catch (final Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        contextDistributor.clear();
+    }
+
+    /**
+     * This method just creates a simple context model programatically.
+     * 
+     * @return a context model
+     */
+    public static AxContextModel createContextModel() {
+        final AxContextSchema longSchema =
+                new AxContextSchema(new AxArtifactKey("LongSchema", "0.0.1"), "Java", "java.lang.Long");
+
+        final AxContextSchemas schemas = new AxContextSchemas(new AxArtifactKey("Schemas", "0.0.1"));
+        schemas.getSchemasMap().put(longSchema.getKey(), longSchema);
+
+        final AxContextAlbum longAlbumDefinition = new AxContextAlbum(new AxArtifactKey("LongContextAlbum", "0.0.1"),
+                "APPLICATION", true, longSchema.getKey());
+
+        final AxContextAlbums albums = new AxContextAlbums(new AxArtifactKey("context", "0.0.1"));
+        albums.getAlbumsMap().put(longAlbumDefinition.getKey(), longAlbumDefinition);
+
+        final AxKeyInformation keyInformation = new AxKeyInformation(new AxArtifactKey("KeyInfoMapKey", "0.0.1"));
+        final AxContextModel contextModel =
+                new AxContextModel(new AxArtifactKey("LongContextModel", "0.0.1"), schemas, albums, keyInformation);
+        contextModel.setKeyInformation(keyInformation);
+        keyInformation.generateKeyInfo(contextModel);
+
+        return contextModel;
+    }
+}
diff --git a/plugins/plugins-context/plugins-context-test/src/main/java/org/onap/policy/apex/plugins/context/test/package-info.java b/plugins/plugins-context/plugins-context-test/src/main/java/org/onap/policy/apex/plugins/context/test/package-info.java
new file mode 100644 (file)
index 0000000..eab3618
--- /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=========================================================
+ */
+
+/**
+ * Is used to inject context into context maps for test purposes.
+ * 
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+package org.onap.policy.apex.plugins.context.test;
diff --git a/plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/distribution/TestContextAlbumUpdate.java b/plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/distribution/TestContextAlbumUpdate.java
new file mode 100644 (file)
index 0000000..c24ef40
--- /dev/null
@@ -0,0 +1,94 @@
+/*-
+ * ============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.plugins.context.test.distribution;
+
+import java.io.IOException;
+
+import org.junit.After;
+import org.junit.Test;
+import org.onap.policy.apex.context.parameters.ContextParameters;
+import org.onap.policy.apex.context.parameters.DistributorParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.handling.ApexModelException;
+import org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanDistributorParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import org.onap.policy.apex.context.test.distribution.ContextAlbumUpdate;
+
+public class TestContextAlbumUpdate {
+    // Logger for this class
+    private static final XLogger logger = XLoggerFactory.getXLogger(TestContextAlbumUpdate.class);
+
+    @Test
+    public void testContextAlbumUpdateJVMLocalVarSet() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testContextAlbumUpdateJVMLocalVarSet test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters()
+                .setPluginClass(DistributorParameters.DEFAULT_DISTRIBUTOR_PLUGIN_CLASS);
+        new ContextAlbumUpdate().testContextAlbumUpdate();
+
+        logger.debug("Ran testContextAlbumUpdateJVMLocalVarSet test");
+    }
+
+    @Test
+    public void testContextAlbumUpdateHazelcast() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testContextAlbumUpdateHazelcast test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.hazelcast.HazelcastContextDistributor");
+        new ContextAlbumUpdate().testContextAlbumUpdate();
+
+        logger.debug("Ran testContextAlbumUpdateHazelcast test");
+    }
+
+    @Test
+    public void testContextAlbumUpdateInfinispan() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testContextAlbumUpdateInfinispan test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanContextDistributor");
+        new InfinispanDistributorParameters();
+
+        new ContextAlbumUpdate().testContextAlbumUpdate();
+
+        logger.debug("Ran testContextAlbumUpdateInfinispan test");
+    }
+
+    @Test
+    public void testContextAlbumUpdateJVMLocalVarNotSet() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testContextAlbumUpdateJVMLocalVarNotSet test . . .");
+
+        new ContextParameters();
+        new ContextAlbumUpdate().testContextAlbumUpdate();
+
+        logger.debug("Ran testContextAlbumUpdateJVMLocalVarNotSet test");
+    }
+
+    /**
+     * Test context update cleardown.
+     */
+    @After
+    public void testContextAlbumUpdateCleardown() {}
+}
diff --git a/plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/distribution/TestContextInstantiation.java b/plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/distribution/TestContextInstantiation.java
new file mode 100644 (file)
index 0000000..a13b798
--- /dev/null
@@ -0,0 +1,86 @@
+/*-
+ * ============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.plugins.context.test.distribution;
+
+import java.io.IOException;
+
+import org.junit.Test;
+import org.onap.policy.apex.context.parameters.ContextParameters;
+import org.onap.policy.apex.context.parameters.DistributorParameters;
+import org.onap.policy.apex.context.test.distribution.ContextInstantiation;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.handling.ApexModelException;
+import org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanDistributorParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+public class TestContextInstantiation {
+    // Logger for this class
+    private static final XLogger logger = XLoggerFactory.getXLogger(TestContextInstantiation.class);
+
+    @Test
+    public void testContextInstantiationJVMLocalVarSet() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testContextInstantiationJVMLocalVarSet test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters()
+                .setPluginClass(DistributorParameters.DEFAULT_DISTRIBUTOR_PLUGIN_CLASS);
+        new ContextInstantiation().testContextInstantiation();
+
+        logger.debug("Ran testContextInstantiationJVMLocalVarSet test");
+    }
+
+    @Test
+    public void testContextInstantiationHazelcast() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testContextInstantiationHazelcast test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.hazelcast.HazelcastContextDistributor");
+        new ContextInstantiation().testContextInstantiation();
+
+        logger.debug("Ran testContextInstantiationHazelcast test");
+    }
+
+    @Test
+    public void testContextInstantiationInfinispan() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testContextInstantiationInfinispan test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanContextDistributor");
+        new InfinispanDistributorParameters();
+
+        new ContextInstantiation().testContextInstantiation();
+
+        logger.debug("Ran testContextInstantiationInfinispan test");
+    }
+
+    @Test
+    public void testContextInstantiationJVMLocalVarNotSet() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testContextInstantiationJVMLocalVarNotSet test . . .");
+
+        new ContextParameters();
+        new ContextInstantiation().testContextInstantiation();
+
+        logger.debug("Ran testContextInstantiationJVMLocalVarNotSet test");
+    }
+}
diff --git a/plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/distribution/TestContextUpdate.java b/plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/distribution/TestContextUpdate.java
new file mode 100644 (file)
index 0000000..3abfd18
--- /dev/null
@@ -0,0 +1,94 @@
+/*-
+ * ============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.plugins.context.test.distribution;
+
+import java.io.IOException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.parameters.ContextParameters;
+import org.onap.policy.apex.context.parameters.DistributorParameters;
+import org.onap.policy.apex.context.test.distribution.ContextUpdate;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.handling.ApexModelException;
+import org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanDistributorParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+public class TestContextUpdate {
+    // Logger for this class
+    private static final XLogger logger = XLoggerFactory.getXLogger(TestContextUpdate.class);
+
+    @Before
+    public void beforeTest() {}
+
+    @After
+    public void afterTest() {}
+
+    @Test
+    public void testContextUpdateJVMLocalVarSet() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testContextUpdateJVMLocalVarSet test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters()
+                .setPluginClass(DistributorParameters.DEFAULT_DISTRIBUTOR_PLUGIN_CLASS);
+        new ContextUpdate().testContextUpdate();
+
+        logger.debug("Ran testContextUpdateJVMLocalVarSet test");
+    }
+
+    @Test
+    public void testContextUpdateHazelcast() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testContextUpdateHazelcast test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.hazelcast.HazelcastContextDistributor");
+        new ContextUpdate().testContextUpdate();
+
+        logger.debug("Ran testContextUpdateHazelcast test");
+    }
+
+    @Test
+    public void testContextUpdateInfinispan() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testContextUpdateInfinispan test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanContextDistributor");
+        new InfinispanDistributorParameters();
+
+        new ContextUpdate().testContextUpdate();
+
+        logger.debug("Ran testContextUpdateInfinispan test");
+    }
+
+    @Test
+    public void testContextUpdateJVMLocalVarNotSet() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testContextUpdateJVMLocalVarNotSet test . . .");
+
+        new ContextParameters();
+        new ContextUpdate().testContextUpdate();
+
+        logger.debug("Ran testContextUpdateJVMLocalVarNotSet test");
+    }
+}
diff --git a/plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/distribution/TestSequentialContextInstantiation.java b/plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/distribution/TestSequentialContextInstantiation.java
new file mode 100644 (file)
index 0000000..cc3f520
--- /dev/null
@@ -0,0 +1,101 @@
+/*-
+ * ============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.plugins.context.test.distribution;
+
+import java.io.IOException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.parameters.ContextParameters;
+import org.onap.policy.apex.context.parameters.DistributorParameters;
+import org.onap.policy.apex.context.test.distribution.SequentialContextInstantiation;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.handling.ApexModelException;
+import org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanDistributorParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * The Class TestContextInstantiation.
+ *
+ * @author Sergey Sachkov (sergey.sachkov@ericsson.com)
+ */
+public class TestSequentialContextInstantiation {
+    // Logger for this class
+    private static final XLogger logger = XLoggerFactory.getXLogger(TestSequentialContextInstantiation.class);
+
+    @Before
+    public void beforeTest() {}
+
+    @After
+    public void afterTest() {}
+
+    @Test
+    public void testSequentialContextInstantiationJVMLocalVarSet()
+            throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testSequentialContextInstantiationJVMLocalVarSet test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters()
+                .setPluginClass(DistributorParameters.DEFAULT_DISTRIBUTOR_PLUGIN_CLASS);
+        new SequentialContextInstantiation().testSequentialContextInstantiation();
+
+        logger.debug("Ran testSequentialContextInstantiationJVMLocalVarSet test");
+    }
+
+    @Test
+    public void testSequentialContextInstantiationHazelcast() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testSequentialContextInstantiationHazelcast test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.hazelcast.HazelcastContextDistributor");
+        new SequentialContextInstantiation().testSequentialContextInstantiation();
+
+        logger.debug("Ran testSequentialContextInstantiationHazelcast test");
+    }
+
+    @Test
+    public void testSequentialContextInstantiationInfinispan() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testSequentialContextInstantiationInfinispan test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanContextDistributor");
+        new InfinispanDistributorParameters();
+
+        new SequentialContextInstantiation().testSequentialContextInstantiation();
+
+        logger.debug("Ran testSequentialContextInstantiationInfinispan test");
+    }
+
+    @Test
+    public void testSequentialContextInstantiationJVMLocalVarNotSet()
+            throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testSequentialContextInstantiationJVMLocalVarNotSet test . . .");
+
+        new ContextParameters();
+        new SequentialContextInstantiation().testSequentialContextInstantiation();
+
+        logger.debug("Ran testSequentialContextInstantiationJVMLocalVarNotSet test");
+    }
+}
diff --git a/plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/locking/CuratorManagerTest.java b/plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/locking/CuratorManagerTest.java
new file mode 100644 (file)
index 0000000..0b9d606
--- /dev/null
@@ -0,0 +1,99 @@
+/*-
+ * ============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.plugins.context.test.locking;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+
+import org.apache.curator.test.TestingServer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.context.parameters.ContextParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.plugins.context.locking.curator.CuratorLockManager;
+import org.onap.policy.apex.plugins.context.locking.curator.CuratorLockManagerParameters;
+
+public class CuratorManagerTest {
+    // Zookeeper test server
+    TestingServer zkTestServer;
+
+    @Before
+    public void beforeTest() throws Exception {
+        zkTestServer = new TestingServer(62181);
+    }
+
+    @After
+    public void afterTest() throws IOException {
+        zkTestServer.stop();
+    }
+
+    @Test
+    public void testCuratorManagerConfigProperty() {
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.setLockManagerParameters(new CuratorLockManagerParameters());
+
+        ((CuratorLockManagerParameters) contextParameters.getLockManagerParameters()).setZookeeperAddress(null);
+
+        try {
+            final CuratorLockManager curatorManager = new CuratorLockManager();
+            curatorManager.init(new AxArtifactKey());
+            assertNull(curatorManager);
+        } catch (final ContextException e) {
+            assertEquals(e.getMessage(),
+                    "could not set up Curator locking, check if the curator Zookeeper address parameter is set correctly");
+        }
+
+        ((CuratorLockManagerParameters) contextParameters.getLockManagerParameters()).setZookeeperAddress("zooby");
+
+        try {
+            final CuratorLockManager curatorManager = new CuratorLockManager();
+            curatorManager.init(new AxArtifactKey());
+            fail("Curator manager test should fail");
+        } catch (final ContextException e) {
+            assertEquals(e.getMessage(),
+                    "could not connect to Zookeeper server at \"zooby\", see error log for details");
+        }
+
+        ((CuratorLockManagerParameters) contextParameters.getLockManagerParameters())
+                .setZookeeperAddress("localhost:62181");
+
+        try {
+            final CuratorLockManager curatorManager0 = new CuratorLockManager();
+            curatorManager0.init(new AxArtifactKey());
+            assertNotNull(curatorManager0);
+
+            final CuratorLockManager curatorManager1 = new CuratorLockManager();
+            curatorManager1.init(new AxArtifactKey());
+            assertNotNull(curatorManager1);
+
+            curatorManager0.shutdown();
+            curatorManager1.shutdown();
+        } catch (final ContextException e) {
+            assertNull(e);
+        }
+    }
+}
diff --git a/plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/locking/TestConcurrentContext.java b/plugins/plugins-context/plugins-context-test/src/test/java/org/onap/policy/apex/plugins/context/test/locking/TestConcurrentContext.java
new file mode 100644 (file)
index 0000000..e02009a
--- /dev/null
@@ -0,0 +1,313 @@
+/*-
+ * ============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.plugins.context.test.locking;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.NetworkInterface;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.TreeSet;
+
+import org.apache.curator.shaded.com.google.common.io.Files;
+import org.apache.zookeeper.server.NIOServerCnxnFactory;
+import org.apache.zookeeper.server.ZooKeeperServer;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+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.test.locking.ConcurrentContext;
+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.service.ParameterService;
+import org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanDistributorParameters;
+import org.onap.policy.apex.plugins.context.locking.curator.CuratorLockManagerParameters;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+import com.hazelcast.config.Config;
+
+/**
+ * The Class TestConcurrentContext tests concurrent use of context.
+ *
+ * @author Liam Fallon (liam.fallon@ericsson.com)
+ */
+public class TestConcurrentContext {
+    // Logger for this class
+    private static final XLogger logger = XLoggerFactory.getXLogger(TestConcurrentContext.class);
+
+    // Test parameters
+    private static final int ZOOKEEPER_START_PORT = 62181;
+    private static final int TEST_JVM_COUNT_SINGLE_JVM = 1;
+    private static final int TEST_JVM_COUNT_MULTI_JVM = 3;
+    private static final int TEST_THREAD_COUNT_SINGLE_JVM = 64;
+    private static final int TEST_THREAD_COUNT_MULTI_JVM = 20;
+    private static final int TEST_THREAD_LOOPS = 100;
+
+    private NIOServerCnxnFactory zookeeperFactory;
+
+    // We need to increment the Zookeeper port because sometimes the port is not released at the end
+    // of the test for a few seconds.
+    private static int nextZookeeperPort = ZOOKEEPER_START_PORT;
+    private int zookeeperPort;
+
+    @BeforeClass
+    public static void configure() throws Exception {
+        System.setProperty("java.net.preferIPv4Stack", "true");
+        System.setProperty("hazelcast.config", "src/test/resources/hazelcast/hazelcast.xml");
+
+        // The JGroups IP address must be set to a real (not loopback) IP address for Infinispan to
+        // work. IN order to ensure that all
+        // the JVMs in a test pick up the same IP address, this function sets the address to be the
+        // first non-loopback IPv4 address
+        // on a host
+        final TreeSet<String> ipAddressSet = new TreeSet<String>();
+
+        final Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
+        for (final NetworkInterface netint : Collections.list(nets)) {
+            final Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
+            for (final InetAddress inetAddress : Collections.list(inetAddresses)) {
+                // Look for real IPv4 internet addresses
+                if (!inetAddress.isLoopbackAddress() && inetAddress.getAddress().length == 4) {
+                    ipAddressSet.add(inetAddress.getHostAddress());
+                }
+            }
+        }
+
+        if (ipAddressSet.size() == 0) {
+            throw new Exception("cound not find real IP address for test");
+        }
+        System.out.println("For Infinispan, setting jgroups.tcp.address to: " + ipAddressSet.first());
+        System.setProperty("jgroups.tcp.address", ipAddressSet.first());
+
+        final Config config = new Config();
+        config.getNetworkConfig().setPublicAddress(ipAddressSet.first());
+        config.getNetworkConfig().getInterfaces().addInterface(ipAddressSet.first());
+    }
+
+    @AfterClass
+    public static void teardown() throws IOException {}
+
+    private void startZookeeperServer() throws IOException, InterruptedException {
+        final File zookeeperDirectory = Files.createTempDir();
+
+        zookeeperPort = nextZookeeperPort++;
+
+        final ZooKeeperServer server = new ZooKeeperServer(zookeeperDirectory, zookeeperDirectory, 5000);
+        zookeeperFactory = new NIOServerCnxnFactory();
+        zookeeperFactory.configure(new InetSocketAddress(zookeeperPort), 100);
+
+        zookeeperFactory.startup(server);
+    }
+
+    private void stopZookeeperServer() {
+        zookeeperFactory.shutdown();
+    }
+
+    @Test
+    public void testConcurrentContextJVMLocalVarSet() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testConcurrentContextJVMLocalVarSet test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getLockManagerParameters()
+                .setPluginClass("org.onap.policy.apex.context.impl.locking.jvmlocal.JVMLocalLockManager");
+        final long result = new ConcurrentContext().testConcurrentContext("JVMLocalVarSet", TEST_JVM_COUNT_SINGLE_JVM,
+                TEST_THREAD_COUNT_SINGLE_JVM, TEST_THREAD_LOOPS);
+
+        assertEquals(TEST_JVM_COUNT_SINGLE_JVM * TEST_THREAD_COUNT_SINGLE_JVM * TEST_THREAD_LOOPS, result);
+
+        logger.debug("Ran testConcurrentContextJVMLocalVarSet test");
+    }
+
+    @Test
+    public void testConcurrentContextJVMLocalNoVarSet() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testConcurrentContextJVMLocalNoVarSet test . . .");
+
+        new ContextParameters();
+        final long result = new ConcurrentContext().testConcurrentContext("JVMLocalNoVarSet", TEST_JVM_COUNT_SINGLE_JVM,
+                TEST_THREAD_COUNT_SINGLE_JVM, TEST_THREAD_LOOPS);
+
+        assertEquals(TEST_JVM_COUNT_SINGLE_JVM * TEST_THREAD_COUNT_SINGLE_JVM * TEST_THREAD_LOOPS, result);
+
+        logger.debug("Ran testConcurrentContextJVMLocalNoVarSet test");
+    }
+
+    @Test
+    public void testConcurrentContextMultiJVMNoLock() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testConcurrentContextMultiJVMNoLock test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters()
+                .setPluginClass("org.onap.policy.apex.context.impl.distribution.jvmlocal.JVMLocalDistributor");
+        contextParameters.getLockManagerParameters()
+                .setPluginClass("org.onap.policy.apex.context.impl.locking.jvmlocal.JVMLocalLockManager");
+
+        final long result = new ConcurrentContext().testConcurrentContext("testConcurrentContextMultiJVMNoLock",
+                TEST_JVM_COUNT_MULTI_JVM, TEST_THREAD_COUNT_MULTI_JVM, TEST_THREAD_LOOPS);
+
+        // No concurrent map so result will be zero
+        assertEquals(0, result);
+
+        logger.debug("Ran testConcurrentContextMultiJVMNoLock test");
+    }
+
+    @Test
+    public void testConcurrentContextHazelcastLock() throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testConcurrentContextHazelcastLock test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters()
+                .setPluginClass(DistributorParameters.DEFAULT_DISTRIBUTOR_PLUGIN_CLASS);
+        contextParameters.getLockManagerParameters()
+                .setPluginClass("org.onap.policy.apex.plugins.context.locking.hazelcast.HazelcastLockManager");
+        final long result = new ConcurrentContext().testConcurrentContext("HazelcastLock", TEST_JVM_COUNT_SINGLE_JVM,
+                TEST_THREAD_COUNT_SINGLE_JVM, TEST_THREAD_LOOPS);
+
+        assertEquals(TEST_JVM_COUNT_SINGLE_JVM * TEST_THREAD_COUNT_SINGLE_JVM * TEST_THREAD_LOOPS, result);
+        logger.debug("Ran testConcurrentContextHazelcastLock test");
+    }
+
+    @Test
+    public void testConcurrentContextCuratorLock()
+            throws ApexModelException, IOException, ApexException, InterruptedException {
+        logger.debug("Running testConcurrentContextCuratorLock test . . .");
+
+        startZookeeperServer();
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters()
+                .setPluginClass(DistributorParameters.DEFAULT_DISTRIBUTOR_PLUGIN_CLASS);
+
+        final CuratorLockManagerParameters curatorParameters = new CuratorLockManagerParameters();
+        curatorParameters.setPluginClass("org.onap.policy.apex.plugins.context.locking.curator.CuratorLockManager");
+        curatorParameters.setZookeeperAddress("127.0.0.1:" + zookeeperPort);
+        contextParameters.setLockManagerParameters(curatorParameters);
+        ParameterService.registerParameters(LockManagerParameters.class, curatorParameters);
+
+        final long result = new ConcurrentContext().testConcurrentContext("CuratorLock", TEST_JVM_COUNT_SINGLE_JVM,
+                TEST_THREAD_COUNT_SINGLE_JVM, TEST_THREAD_LOOPS);
+
+        assertEquals(TEST_JVM_COUNT_SINGLE_JVM * TEST_THREAD_COUNT_SINGLE_JVM * TEST_THREAD_LOOPS, result);
+
+        stopZookeeperServer();
+        logger.debug("Ran testConcurrentContextCuratorLock test");
+    }
+
+    @Test
+    public void testConcurrentContextHazelcastMultiJVMHazelcastLock()
+            throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testConcurrentContextHazelcastMultiJVMHazelcastLock test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.hazelcast.HazelcastContextDistributor");
+        contextParameters.getLockManagerParameters()
+                .setPluginClass("org.onap.policy.apex.plugins.context.locking.hazelcast.HazelcastLockManager");
+        final long result = new ConcurrentContext().testConcurrentContext("HazelcastMultiHazelcastlock",
+                TEST_JVM_COUNT_MULTI_JVM, TEST_THREAD_COUNT_MULTI_JVM, TEST_THREAD_LOOPS);
+
+        assertEquals(TEST_JVM_COUNT_MULTI_JVM * TEST_THREAD_COUNT_MULTI_JVM * TEST_THREAD_LOOPS, result);
+        logger.debug("Ran testConcurrentContextHazelcastMultiJVMHazelcastLock test");
+    }
+
+    @Test
+    public void testConcurrentContextInfinispanMultiJVMHazelcastlock()
+            throws ApexModelException, IOException, ApexException {
+        logger.debug("Running testConcurrentContextInfinispanMultiJVMHazelcastlock test . . .");
+
+        final ContextParameters contextParameters = new ContextParameters();
+        final InfinispanDistributorParameters infinispanParameters = new InfinispanDistributorParameters();
+        infinispanParameters.setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanContextDistributor");
+        infinispanParameters.setConfigFile("infinispan/infinispan-context-test.xml");
+        contextParameters.setDistributorParameters(infinispanParameters);
+        contextParameters.getLockManagerParameters()
+                .setPluginClass("org.onap.policy.apex.plugins.context.locking.hazelcast.HazelcastLockManager");
+
+        final long result = new ConcurrentContext().testConcurrentContext("InfinispanMultiHazelcastlock",
+                TEST_JVM_COUNT_MULTI_JVM, TEST_THREAD_COUNT_MULTI_JVM, TEST_THREAD_LOOPS);
+
+        assertEquals(TEST_JVM_COUNT_MULTI_JVM * TEST_THREAD_COUNT_MULTI_JVM * TEST_THREAD_LOOPS, result);
+        logger.debug("Ran testConcurrentContextInfinispanMultiJVMHazelcastlock test");
+    }
+
+    @Test
+    public void testConcurrentContextInfinispanMultiJVMCuratorLock()
+            throws ApexModelException, IOException, ApexException, InterruptedException {
+        logger.debug("Running testConcurrentContextInfinispanMultiJVMCuratorLock test . . .");
+
+        startZookeeperServer();
+
+        final ContextParameters contextParameters = new ContextParameters();
+        final InfinispanDistributorParameters infinispanParameters = new InfinispanDistributorParameters();
+        infinispanParameters.setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.infinispan.InfinispanContextDistributor");
+        infinispanParameters.setConfigFile("infinispan/infinispan-context-test.xml");
+        contextParameters.setDistributorParameters(infinispanParameters);
+
+        final CuratorLockManagerParameters curatorParameters = new CuratorLockManagerParameters();
+        curatorParameters.setPluginClass("org.onap.policy.apex.plugins.context.locking.curator.CuratorLockManager");
+        curatorParameters.setZookeeperAddress("127.0.0.1:" + zookeeperPort);
+        contextParameters.setLockManagerParameters(curatorParameters);
+        ParameterService.registerParameters(LockManagerParameters.class, curatorParameters);
+
+        final long result = new ConcurrentContext().testConcurrentContext("InfinispanMultiCuratorLock",
+                TEST_JVM_COUNT_MULTI_JVM, TEST_THREAD_COUNT_MULTI_JVM, TEST_THREAD_LOOPS);
+
+        assertEquals(TEST_JVM_COUNT_MULTI_JVM * TEST_THREAD_COUNT_MULTI_JVM * TEST_THREAD_LOOPS, result);
+
+        stopZookeeperServer();
+
+        logger.debug("Ran testConcurrentContextInfinispanMultiJVMCuratorLock test");
+    }
+
+    @Test
+    public void testConcurrentContextHazelcastMultiJVMCuratorLock()
+            throws ApexModelException, IOException, ApexException, InterruptedException {
+        logger.debug("Running testConcurrentContextHazelcastMultiJVMCuratorLock test . . .");
+
+        startZookeeperServer();
+
+        final ContextParameters contextParameters = new ContextParameters();
+        contextParameters.getDistributorParameters().setPluginClass(
+                "org.onap.policy.apex.plugins.context.distribution.hazelcast.HazelcastContextDistributor");
+
+        final CuratorLockManagerParameters curatorParameters = new CuratorLockManagerParameters();
+        curatorParameters.setPluginClass("org.onap.policy.apex.plugins.context.locking.curator.CuratorLockManager");
+        curatorParameters.setZookeeperAddress("127.0.0.1:" + zookeeperPort);
+        contextParameters.setLockManagerParameters(curatorParameters);
+        ParameterService.registerParameters(LockManagerParameters.class, curatorParameters);
+
+        final long result = new ConcurrentContext().testConcurrentContext("HazelcastMultiCuratorLock",
+                TEST_JVM_COUNT_MULTI_JVM, TEST_THREAD_COUNT_MULTI_JVM, TEST_THREAD_LOOPS);
+
+        assertEquals(TEST_JVM_COUNT_MULTI_JVM * TEST_THREAD_COUNT_MULTI_JVM * TEST_THREAD_LOOPS, result);
+
+        stopZookeeperServer();
+        logger.debug("Ran testConcurrentContextHazelcastMultiJVMCuratorLock test");
+    }
+}
diff --git a/plugins/plugins-context/pom.xml b/plugins/plugins-context/pom.xml
new file mode 100644 (file)
index 0000000..7be7843
--- /dev/null
@@ -0,0 +1,104 @@
+<!--
+  ============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.plugins</groupId>
+        <artifactId>plugins</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.onap.policy.apex-pdp.plugins.plugins-context</groupId>
+    <artifactId>plugins-context</artifactId>
+    <packaging>pom</packaging>
+
+    <name>${project.artifactId}</name>
+    <description>Plugins for 3pps that distribute context</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onap.policy.apex-pdp.context</groupId>
+            <artifactId>context-management</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <profiles>
+        <profile>
+            <id>apexDefault</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <modules>
+                <module>context-schema</module>
+                <module>context-distribution</module>
+                <module>context-locking</module>
+                <module>context-persistence</module>
+            </modules>
+        </profile>
+        <profile>
+            <id>apexTests</id>
+            <activation>
+                <property>
+                    <name>apexTests</name>
+                </property>
+            </activation>
+            <modules>
+                <module>context-schema</module>
+                <module>context-distribution</module>
+                <module>context-locking</module>
+                <module>context-persistence</module>
+                <module>plugins-context-test</module>
+            </modules>
+        </profile>
+        <profile>
+            <id>apexMetrics</id>
+            <activation>
+                <property>
+                    <name>apexMetrics</name>
+                </property>
+            </activation>
+            <modules>
+                <module>context-schema</module>
+                <module>context-distribution</module>
+                <module>context-locking</module>
+                <module>context-persistence</module>
+                <module>context-metrics</module>
+            </modules>
+        </profile>
+        <profile>
+            <id>apexAll</id>
+            <activation>
+                <property>
+                    <name>apexAll</name>
+                </property>
+            </activation>
+            <modules>
+                <module>context-schema</module>
+                <module>context-distribution</module>
+                <module>context-locking</module>
+                <module>context-persistence</module>
+                <module>plugins-context-test</module>
+                <module>context-metrics</module>
+            </modules>
+        </profile>
+    </profiles>
+</project>
\ No newline at end of file
diff --git a/plugins/pom.xml b/plugins/pom.xml
new file mode 100644 (file)
index 0000000..f9afef8
--- /dev/null
@@ -0,0 +1,44 @@
+<!--
+  ============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.plugins</groupId>
+    <artifactId>plugins</artifactId>
+    <packaging>pom</packaging>
+
+    <name>${project.artifactId}</name>
+    <description>Plugins for Apex that can be implemented with various 3PPs are implemented here.</description>
+
+    <properties>
+        <version.hazelcast>3.8.3</version.hazelcast>
+    </properties>
+
+    <modules>
+        <module>plugins-context</module>
+    </modules>
+</project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index d066e09..2fd8a0a 100644 (file)
--- a/pom.xml
+++ b/pom.xml
         <module>context</module>
         <module>core</module>
         <module>auth</module>
+        <module>plugins</module>
     </modules>
 </project>
\ No newline at end of file