aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main
diff options
context:
space:
mode:
authorliamfallon <liam.fallon@ericsson.com>2018-07-18 11:23:20 +0100
committerliamfallon <liam.fallon@ericsson.com>2018-07-18 11:23:34 +0100
commitb109c218ab7db28fd1cbe62c808496dfdedad809 (patch)
treeaeb65f55c9cb138830e849d276cfd4ad3b861512 /plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main
parent1eb5198939bd1d60665ff49e49763d0067c1bcb5 (diff)
Fix incorrect naming on context plugins
This change fixes inconsistent naming on the context plugins in APEX. All plugins should fillow the naming convention of plugin-A.plugin-A.B.plugin.A.B.C and so on. Not following this convention breaks the APEX documentation build. Issue-ID: POLICY-954 Change-Id: I8aad4a28d143427e60017eaa119ee4f7ce9f5b3d Signed-off-by: liamfallon <liam.fallon@ericsson.com>
Diffstat (limited to 'plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main')
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroArrayObjectMapper.java44
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroBytesObjectMapper.java149
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroDirectObjectMapper.java165
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroEnumObjectMapper.java53
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroNullableMapper.java124
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapper.java78
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapperFactory.java131
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroRecordObjectMapper.java43
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelper.java261
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelperParameters.java38
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaKeyTranslationUtilities.java140
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroStringObjectMapper.java130
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/package-info.java27
13 files changed, 1383 insertions, 0 deletions
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroArrayObjectMapper.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroArrayObjectMapper.java
new file mode 100644
index 000000000..56d84251f
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroArrayObjectMapper.java
@@ -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/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroBytesObjectMapper.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroBytesObjectMapper.java
new file mode 100644
index 000000000..dc281a52b
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroBytesObjectMapper.java
@@ -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/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroDirectObjectMapper.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroDirectObjectMapper.java
new file mode 100644
index 000000000..acf64c3c9
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroDirectObjectMapper.java
@@ -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/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroEnumObjectMapper.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroEnumObjectMapper.java
new file mode 100644
index 000000000..ec84450d5
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroEnumObjectMapper.java
@@ -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/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroNullableMapper.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroNullableMapper.java
new file mode 100644
index 000000000..ff8806c86
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroNullableMapper.java
@@ -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/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapper.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapper.java
new file mode 100644
index 000000000..77de5928e
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapper.java
@@ -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/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapperFactory.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapperFactory.java
new file mode 100644
index 000000000..22152a8da
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroObjectMapperFactory.java
@@ -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())) {
+ 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/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroRecordObjectMapper.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroRecordObjectMapper.java
new file mode 100644
index 000000000..9d24a9a86
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroRecordObjectMapper.java
@@ -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/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelper.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelper.java
new file mode 100644
index 000000000..5fba274ce
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelper.java
@@ -0,0 +1,261 @@
+/*-
+ * ============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 Object incomingObject) {
+ if (incomingObject instanceof JsonElement) {
+ final Gson gson = new GsonBuilder().serializeNulls().create();
+ final String elementJsonString = gson.toJson((JsonElement) incomingObject);
+
+ return createNewInstance(elementJsonString);
+ }
+ else {
+ final String returnString = getUserKey().getID() + ": the object \"" + incomingObject
+ + "\" is not an instance of JsonObject";
+ LOGGER.warn(returnString);
+ throw new ContextRuntimeException(returnString);
+ }
+ }
+
+ @Override
+ public Object unmarshal(final Object object) {
+ // If an object is already in the correct format, just carry on
+ if (passThroughObject(object)) {
+ return object;
+ }
+
+ String objectString = getStringObject(object);
+
+ // 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);
+ }
+
+ /**
+ * Check that the incoming object is a string, the incoming object must be a string containing
+ * Json
+ *
+ * @param object incoming object
+ * @return object as String
+ */
+ private String getStringObject(final Object object) {
+ try {
+ if (isObjectString(object)) {
+ String objectString = object.toString().trim();
+ if (objectString.length() == 0) {
+ return "\"\"";
+ } else if (objectString.length() == 1) {
+ return "\"" + objectString + "\"";
+ } else {
+ // All strings must be quoted for decoding
+ if (objectString.charAt(0) != '"') {
+ objectString = '"' + objectString;
+ }
+ if (objectString.charAt(objectString.length() - 1) != '"') {
+ objectString += '"';
+ }
+ }
+ return objectString;
+ } else {
+ return (String) object;
+ }
+ } catch (final ClassCastException e) {
+ final String returnString = getUserKey().getID() + ": object \"" + object + "\" of type \""
+ + (object != null ? object.getClass().getCanonicalName() : "null") + "\" must be assignable to \""
+ + getSchemaClass().getCanonicalName()
+ + "\" or be a Json string representation of it for Avro unmarshalling";
+ LOGGER.warn(returnString);
+ throw new ContextRuntimeException(returnString);
+ }
+ }
+
+ private boolean isObjectString(final Object object) {
+ return object != null && avroSchema.getType().equals(Schema.Type.STRING);
+ }
+
+ @Override
+ public String marshal2String(final Object object) {
+ // Condition the object for Avro encoding
+ final Object conditionedObject = avroObjectMapper.mapToAvro(object);
+
+ final String jsonString = getJsonString(object, conditionedObject);
+
+ return AvroSchemaKeyTranslationUtilities.translateIllegalKeys(jsonString, true);
+ }
+
+ private String getJsonString(final Object object, final Object conditionedObject) {
+
+ try (final ByteArrayOutputStream output = new ByteArrayOutputStream();) {
+ final DatumWriter<Object> writer = new GenericDatumWriter<>(avroSchema);
+ final JsonEncoder jsonEncoder = EncoderFactory.get().jsonEncoder(avroSchema, output, true);
+ writer.write(conditionedObject, jsonEncoder);
+ jsonEncoder.flush();
+ return new String(output.toByteArray());
+ } catch (final Exception e) {
+ final String returnString =
+ getUserKey().getID() + ": object \"" + object + "\" Avro marshalling failed: " + e.getMessage();
+ LOGGER.warn(returnString);
+ throw new ContextRuntimeException(returnString, e);
+ }
+ }
+
+ @Override
+ public JsonElement marshal2Object(final Object schemaObject) {
+ // Get the object as a Json string
+ final String schemaObjectAsString = marshal2String(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/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelperParameters.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelperParameters.java
new file mode 100644
index 000000000..5a8fac404
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaHelperParameters.java
@@ -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/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaKeyTranslationUtilities.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaKeyTranslationUtilities.java
new file mode 100644
index 000000000..dc3770a43
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroSchemaKeyTranslationUtilities.java
@@ -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/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroStringObjectMapper.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroStringObjectMapper.java
new file mode 100644
index 000000000..cb3625f31
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/AvroStringObjectMapper.java
@@ -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/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/package-info.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/package-info.java
new file mode 100644
index 000000000..93f4943d5
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-avro/src/main/java/org/onap/policy/apex/plugins/context/schema/avro/package-info.java
@@ -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;