aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json
diff options
context:
space:
mode:
authora.sreekumar <ajith.sreekumar@bell.ca>2022-07-19 11:49:57 +0100
committerRam Krishna Verma <ram_krishna.verma@bell.ca>2022-08-01 15:14:31 +0000
commitf3f82982bb09ba650e4eaa1214dae35dbab71d55 (patch)
tree43ab3ccb3e8d73de43a3f6805432981f9272a92b /plugins/plugins-context/plugins-context-schema/plugins-context-schema-json
parentc6c3fed415006c2ea5c5af21fe9a53936fc8800b (diff)
Adding JSON Schema support in APEX-PDP
More details can be found here: https://wiki.onap.org/display/DW/JSON+Schema+support+in+APEX-PDP A separate review will be raised as part of POLICY-4292 with a reference example on how to use the JSON Schema. Change-Id: I903d48969c6c5a24c63b8465b2412ed0b75b9351 Issue-ID: POLICY-4291 Signed-off-by: a.sreekumar <ajith.sreekumar@bell.ca> (cherry picked from commit c354fba3fb87ebe21a7fbb2a15268ccc9d033fbd)
Diffstat (limited to 'plugins/plugins-context/plugins-context-schema/plugins-context-schema-json')
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/pom.xml44
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/main/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelper.java122
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/main/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperParameters.java30
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/CommonTestData.java115
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperMarshalTest.java133
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperUnmarshalTest.java166
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/data/commonHeader.json6
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/data/measurementGroups.json34
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/commonHeaderTypeWithOptional.json23
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/commonHeaderType_draft04.json24
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/commonHeaderType_draft07.json52
-rw-r--r--plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/measurementGroupsType.json61
12 files changed, 810 insertions, 0 deletions
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/pom.xml b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/pom.xml
new file mode 100644
index 000000000..979ab49cf
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/pom.xml
@@ -0,0 +1,44 @@
+<!--
+ ============LICENSE_START=======================================================
+ Copyright (C) 2022 Bell Canada. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.policy.apex-pdp.plugins.plugins-context.plugins-context-schema</groupId>
+ <artifactId>plugins-context-schema</artifactId>
+ <version>2.5.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>plugins-context-schema-json</artifactId>
+ <name>${project.artifactId}</name>
+ <description>[${project.parent.artifactId}] Plugin for schemas using JSON</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.worldturner.medeia</groupId>
+ <artifactId>medeia-validator-gson</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/main/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelper.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/main/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelper.java
new file mode 100644
index 000000000..4896e5d4a
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/main/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelper.java
@@ -0,0 +1,122 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Bell Canada. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.json;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import com.worldturner.medeia.api.SchemaSource;
+import com.worldturner.medeia.api.StringInputSource;
+import com.worldturner.medeia.api.StringSchemaSource;
+import com.worldturner.medeia.api.gson.MedeiaGsonApi;
+import com.worldturner.medeia.schema.validation.SchemaValidator;
+import java.io.StringWriter;
+import java.util.List;
+import java.util.Map;
+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;
+
+/**
+ * This class is the implementation of the {@link org.onap.policy.apex.context.SchemaHelper} interface for JSON schema.
+ */
+public class JsonSchemaHelper extends AbstractSchemaHelper {
+
+ private static final Gson gson = new Gson();
+
+ private MedeiaGsonApi api = new MedeiaGsonApi();
+ private SchemaValidator validator;
+
+ @Override
+ public void init(final AxKey userKey, final AxContextSchema schema) {
+ super.init(userKey, schema);
+
+ try {
+ SchemaSource source = new StringSchemaSource(schema.getSchema());
+ validator = api.loadSchema(source);
+ } catch (final Exception e) {
+ final String resultSting = userKey.getId() + ": json context schema \"" + schema.getId()
+ + "\" schema is invalid, schema: " + schema.getSchema();
+ throw new ContextRuntimeException(resultSting, e);
+ }
+ }
+
+ @Override
+ public Object createNewInstance(final String stringValue) {
+ return unmarshal(stringValue);
+ }
+
+ @Override
+ public Object createNewInstance(final Object incomingObject) {
+ if (incomingObject instanceof JsonElement) {
+ final var elementJsonString = gson.toJson((JsonElement) incomingObject);
+
+ return createNewInstance(elementJsonString);
+ } else {
+ final var returnString =
+ getUserKey().getId() + ": the object \"" + incomingObject + "\" is not an instance of JsonObject";
+ throw new ContextRuntimeException(returnString);
+ }
+ }
+
+ @Override
+ public Object unmarshal(Object object) {
+ // If an object is already in the correct format, just carry on
+ if (passThroughObject(object)) {
+ return object;
+ }
+ var objectString = (String) object;
+ JsonReader reader = api.createJsonReader(validator, new StringInputSource(objectString));
+ return gson.fromJson(reader, Object.class);
+ }
+
+ @Override
+ public String marshal2String(Object schemaObject) {
+ StringWriter stringWriter = new StringWriter();
+ validateAndDecode(schemaObject, stringWriter);
+ return stringWriter.toString();
+ }
+
+ @Override
+ public Object marshal2Object(Object schemaObject) {
+ return validateAndDecode(schemaObject, new StringWriter());
+ }
+
+ private JsonElement validateAndDecode(Object schemaObject, StringWriter stringWriter) {
+ JsonWriter jsonWriter = api.createJsonWriter(validator, stringWriter);
+ jsonWriter.setIndent(" "); // to enable pretty print
+ JsonElement jsonObj = gson.toJsonTree(schemaObject);
+ gson.toJson(jsonObj, jsonWriter);
+ return jsonObj;
+ }
+
+ /**
+ * Check if we can pass this object straight through encoding or decoding.
+ *
+ * @param object the object to check
+ * @return true if it's a straight pass through
+ */
+ private boolean passThroughObject(final Object object) {
+ return (object instanceof JsonElement || object instanceof Map || object instanceof List);
+ }
+}
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/main/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperParameters.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/main/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperParameters.java
new file mode 100644
index 000000000..0e275130d
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/main/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperParameters.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Bell Canada. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.json;
+
+import org.onap.policy.apex.context.parameters.SchemaHelperParameters;
+
+public class JsonSchemaHelperParameters extends SchemaHelperParameters {
+
+ public JsonSchemaHelperParameters() {
+ this.setSchemaHelperPluginClass(JsonSchemaHelper.class.getName());
+ }
+}
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/CommonTestData.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/CommonTestData.java
new file mode 100644
index 000000000..ce03678c9
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/CommonTestData.java
@@ -0,0 +1,115 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Bell Canada. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.json;
+
+import java.io.IOException;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
+import org.onap.policy.apex.context.parameters.ContextParameterConstants;
+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.common.parameters.ParameterService;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.resources.TextFileUtils;
+
+public class CommonTestData {
+
+ protected static final String VERSION = "0.0.1";
+ protected static final String JSON = "JSON";
+ protected static final String TEST_ID = "testId";
+ protected final AxKey testKey = new AxArtifactKey("JsonTest", VERSION);
+ protected AxContextSchemas schemas;
+ protected final StandardCoder coder = new StandardCoder();
+
+ protected static final String BOOLEAN_SCHEMA =
+ "{\"$schema\": \"http://json-schema.org/draft-07/schema#\",\"type\": \"boolean\"}";
+ protected static final String BOOLEAN_DATA = "true";
+ protected static final String NULL_SCHEMA =
+ "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"null\"}";
+ protected static final String NULL_DATA = "null";
+ protected static String COMMONHEADERTYPE_DRAFT04;
+ protected static String COMMONHEADERTYPE_DRAFT07;
+ protected static String COMMONHEADERTYPE_WITH_OPTIONAL;
+ protected static String COMMONHEADER;
+ protected static String MEASUREMENTGROUPS_TYPE;
+ protected static String MEASUREMENTGROUPS;
+
+ /**
+ * Setup before all tests.
+ */
+ @BeforeClass
+ public static void setUpBeforeClass() throws IOException {
+ COMMONHEADERTYPE_DRAFT04 =
+ TextFileUtils.getTextFileAsString("src/test/resources/schema/commonHeaderType_draft04.json");
+ COMMONHEADERTYPE_DRAFT07 =
+ TextFileUtils.getTextFileAsString("src/test/resources/schema/commonHeaderType_draft07.json");
+ COMMONHEADERTYPE_WITH_OPTIONAL =
+ TextFileUtils.getTextFileAsString("src/test/resources/schema/commonHeaderTypeWithOptional.json");
+ COMMONHEADER =
+ TextFileUtils.getTextFileAsString("src/test/resources/data/commonHeader.json").replaceAll("\r", "").trim();
+ MEASUREMENTGROUPS_TYPE =
+ TextFileUtils.getTextFileAsString("src/test/resources/schema/measurementGroupsType.json");
+ MEASUREMENTGROUPS = TextFileUtils.getTextFileAsString("src/test/resources/data/measurementGroups.json")
+ .replaceAll("\r", "").trim();
+ }
+
+ /**
+ * Setup before test.
+ */
+ @Before
+ public void setUp() {
+ schemas = new AxContextSchemas(new AxArtifactKey("JsonSchema", VERSION));
+ ModelService.registerModel(AxContextSchemas.class, schemas);
+
+ SchemaParameters schemaParameters = new SchemaParameters();
+ schemaParameters.setName(ContextParameterConstants.SCHEMA_GROUP_NAME);
+ schemaParameters.getSchemaHelperParameterMap().put(JSON, new JsonSchemaHelperParameters());
+ ParameterService.register(schemaParameters);
+ }
+
+ /**
+ * Teardown after test.
+ */
+ @After
+ public void tearDown() {
+ ParameterService.deregister(ContextParameterConstants.SCHEMA_GROUP_NAME);
+ ModelService.clear();
+ }
+
+ /**
+ * Method to create JsonSchemaHelper instance from schema content.
+ *
+ * @param schema the schema content as string
+ * @return schemaHelper instance
+ */
+ protected SchemaHelper createSchema(String schema) {
+ final AxContextSchema jsonSchema = new AxContextSchema(new AxArtifactKey("SchemaTest", VERSION), JSON, schema);
+ schemas.getSchemasMap().put(jsonSchema.getKey(), jsonSchema);
+ return new SchemaHelperFactory().createSchemaHelper(testKey, jsonSchema.getKey());
+ }
+}
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperMarshalTest.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperMarshalTest.java
new file mode 100644
index 000000000..15458199a
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperMarshalTest.java
@@ -0,0 +1,133 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Bell Canada. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.json;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.worldturner.medeia.api.ValidationFailedException;
+import java.util.ArrayList;
+import java.util.Map;
+import org.junit.Test;
+import org.onap.policy.common.utils.coder.CoderException;
+
+public class JsonSchemaHelperMarshalTest extends CommonTestData {
+
+ /**
+ * Test Boolean.
+ */
+ @Test
+ public void testBooleanMarshal() {
+ var schemaHelper = createSchema(BOOLEAN_SCHEMA);
+ assertThat(schemaHelper.marshal2String(Boolean.TRUE)).isEqualTo("true");
+ }
+
+ /**
+ * Test null.
+ */
+ @Test
+ public void testNullMarshal() {
+ var schemaHelper = createSchema(NULL_SCHEMA);
+ assertThat(schemaHelper.marshal2String(null)).isEqualTo("null");
+ }
+
+ /**
+ * Test Array.
+ *
+ * @throws CoderException the coder exception
+ */
+ @Test
+ public void testArrayMarshal() throws CoderException {
+ var schemaHelper = createSchema(MEASUREMENTGROUPS_TYPE);
+ var object = coder.decode(MEASUREMENTGROUPS, Object.class);
+ assertThat(object).isInstanceOf(ArrayList.class);
+ var marshalledString = schemaHelper.marshal2String(object);
+ assertThat(marshalledString).isEqualTo(MEASUREMENTGROUPS);
+ var marshalledObject = schemaHelper.marshal2Object(object);
+ assertThat(marshalledObject).isInstanceOf(JsonArray.class);
+ }
+
+ /**
+ * Test Object marshal valid scenario using JSON Schema draft 04.
+ *
+ * @throws CoderException the coderException
+ */
+ @Test
+ public void testObjectSchemaDraft04_valid() throws CoderException {
+ var dataAsObject = coder.decode(COMMONHEADER, Map.class);
+ var dataReturned = validateAndMarshal(COMMONHEADERTYPE_DRAFT04, dataAsObject, true);
+ assertThat(dataReturned).isEqualTo(COMMONHEADER);
+ }
+
+ /**
+ * Test Object marshal valid scenario using JSON Schema draft 07.
+ *
+ * @throws CoderException the coderException
+ */
+ @Test
+ public void testObjectSchemaDraft07_valid() throws CoderException {
+ var dataAsObject = coder.decode(COMMONHEADER, Map.class);
+ var dataReturned = validateAndMarshal(COMMONHEADERTYPE_DRAFT07, dataAsObject, true);
+ assertThat(dataReturned).isEqualTo(COMMONHEADER);
+ assertThat(validateAndMarshal(COMMONHEADERTYPE_DRAFT07, dataAsObject, false)).isInstanceOf(JsonObject.class);
+ }
+
+ /**
+ * Test Object marshal invalid - required field missing scenario.
+ *
+ * @throws CoderException the coderException
+ */
+ @Test
+ public void testObjectSchema_fieldMissing() throws CoderException {
+ var dataAsObject = coder.decode(COMMONHEADER, Map.class);
+ dataAsObject.remove(TEST_ID);
+ assertThatThrownBy(() -> validateAndMarshal(COMMONHEADERTYPE_DRAFT07, dataAsObject, true))
+ .isInstanceOf(ValidationFailedException.class)
+ .hasMessageContaining("Required property testId is missing from object");
+ }
+
+ /**
+ * Test Object marshal with optional field.
+ *
+ * @throws CoderException the coderException
+ */
+ @Test
+ public void testObjectSchema_OptionalField() throws CoderException {
+ var dataAsObject = coder.decode(COMMONHEADER, Map.class);
+ var dataAsjsonObject = coder.decode(COMMONHEADER, JsonObject.class);
+ dataAsObject.remove(TEST_ID);
+ dataAsjsonObject.remove(TEST_ID);
+ var dataReturned = validateAndMarshal(COMMONHEADERTYPE_WITH_OPTIONAL, dataAsObject, false);
+ assertThat(dataReturned).isEqualTo(dataAsjsonObject);
+ }
+
+ private Object validateAndMarshal(String schemaDef, Object obj, boolean marshalAsString) {
+ var schemaHelper = createSchema(schemaDef);
+ if (marshalAsString) {
+ return schemaHelper.marshal2String(obj);
+ } else {
+ return schemaHelper.marshal2Object(obj);
+ }
+ }
+
+}
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperUnmarshalTest.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperUnmarshalTest.java
new file mode 100644
index 000000000..11c8638de
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperUnmarshalTest.java
@@ -0,0 +1,166 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Bell Canada. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.json;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import com.google.gson.JsonObject;
+import com.worldturner.medeia.api.ValidationFailedException;
+import java.util.ArrayList;
+import java.util.Map;
+import org.junit.Test;
+import org.onap.policy.apex.context.ContextRuntimeException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.common.utils.coder.CoderException;
+
+public class JsonSchemaHelperUnmarshalTest extends CommonTestData {
+
+ /**
+ * Test Boolean.
+ */
+ @Test
+ public void testBooleanUnmarshal() {
+ var schemaHelper = createSchema(BOOLEAN_SCHEMA);
+ assertThat(schemaHelper.createNewInstance(BOOLEAN_DATA)).isInstanceOf(Boolean.class).isEqualTo(Boolean.TRUE);
+ }
+
+ /**
+ * Test null.
+ */
+ @Test
+ public void testNullUnmarshal() {
+ var schemaHelper = createSchema(NULL_SCHEMA);
+ assertThat(schemaHelper.createNewInstance(NULL_DATA)).isEqualTo(null);
+ }
+
+ /**
+ * Test Array.
+ */
+ @Test
+ public void testArrayUnmarshal() {
+ var schemaHelper = createSchema(MEASUREMENTGROUPS_TYPE);
+ var obj = schemaHelper.createNewInstance(MEASUREMENTGROUPS);
+ assertThat(obj).isInstanceOf(ArrayList.class);
+ }
+
+ /**
+ * Test invlaid schema.
+ */
+ @Test
+ public void testSchemaInvalid() {
+ String schemaDef = "{\"type\": \"object\"}";
+ final AxContextSchema jsonSchema =
+ new AxContextSchema(new AxArtifactKey("JsonObject", VERSION), JSON, schemaDef);
+ assertThatThrownBy(() -> new JsonSchemaHelper().init(testKey, jsonSchema))
+ .isInstanceOf(ContextRuntimeException.class).hasMessageContaining("schema is invalid");
+ }
+
+ /**
+ * Test Object unmarshal valid scenario using JSON Schema draft 04.
+ *
+ * @throws CoderException the coderException
+ */
+ @Test
+ public void testObjectSchemaDraft04_valid() throws CoderException {
+ var dataAsObject = coder.decode(COMMONHEADER, Map.class);
+ var dataReturned = validateAndUnmarshal(COMMONHEADERTYPE_DRAFT04, COMMONHEADER);
+ assertThat(dataReturned).isEqualTo(dataAsObject);
+ }
+
+ /**
+ * Test Object unmarshal valid scenario using JSON Schema draft 07.
+ *
+ * @throws CoderException the coderException
+ */
+ @Test
+ public void testObjectSchemaDraft07_valid() throws CoderException {
+ var dataAsObject = coder.decode(COMMONHEADER, Map.class);
+ var dataReturned = validateAndUnmarshal(COMMONHEADERTYPE_DRAFT07, COMMONHEADER);
+ assertThat(dataReturned).isEqualTo(dataAsObject);
+ }
+
+ /**
+ * Test Object unmarshal invalid scenario using JSON Schema draft 07.
+ *
+ * @throws CoderException the coderException
+ */
+ @Test
+ public void testObjectSchemaDraft07_invalid() throws CoderException {
+ var dataAsObject = coder.decode(COMMONHEADER, JsonObject.class);
+ dataAsObject.addProperty("requestId", "abcd");
+ assertThatThrownBy(() -> validateAndUnmarshal(COMMONHEADERTYPE_DRAFT07, dataAsObject))
+ .isInstanceOf(ValidationFailedException.class)
+ .hasMessageContaining("Pattern ^[0-9]*-[0-9]*$ is not contained in text");
+ }
+
+ /**
+ * Test createInstance using invalid format data.
+ *
+ * @throws CoderException the coderException
+ */
+ @Test
+ public void testCreateNewInstanceInvalid() throws CoderException {
+ var dataAsObject = coder.decode(COMMONHEADER, Map.class);
+ assertThatThrownBy(() -> validateAndUnmarshal(COMMONHEADERTYPE_DRAFT07, dataAsObject))
+ .isInstanceOf(ContextRuntimeException.class).hasMessageContaining("not an instance of JsonObject");
+ }
+
+ /**
+ * Test Object unmarshal invalid - required field missing scenario.
+ *
+ * @throws CoderException the coderException
+ */
+ @Test
+ public void testObjectSchema_fieldMissing() throws CoderException {
+ var dataAsObject = coder.decode(COMMONHEADER, JsonObject.class);
+ dataAsObject.remove(TEST_ID);
+ assertThatThrownBy(() -> validateAndUnmarshal(COMMONHEADERTYPE_DRAFT07, dataAsObject))
+ .isInstanceOf(ValidationFailedException.class)
+ .hasMessageContaining("Required property testId is missing from object");
+ }
+
+ /**
+ * Test Object unmarshal with optional field.
+ *
+ * @throws CoderException the coderException
+ */
+ @Test
+ public void testObjectSchema_OptionalField() throws CoderException {
+ var dataAsObject = coder.decode(COMMONHEADER, Map.class);
+ var dataAsjsonObject = coder.decode(COMMONHEADER, JsonObject.class);
+ dataAsObject.remove(TEST_ID);
+ dataAsjsonObject.remove(TEST_ID);
+ var dataReturned = validateAndUnmarshal(COMMONHEADERTYPE_WITH_OPTIONAL, dataAsjsonObject);
+ assertThat(dataReturned).isEqualTo(dataAsObject);
+ }
+
+ private Object validateAndUnmarshal(String schemaDef, Object data) {
+ var schemaHelper = createSchema(schemaDef);
+ if (data instanceof String) {
+ return schemaHelper.createNewInstance((String) data);
+ } else {
+ return schemaHelper.createNewInstance(data);
+ }
+ }
+
+}
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/data/commonHeader.json b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/data/commonHeader.json
new file mode 100644
index 000000000..d3393cc63
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/data/commonHeader.json
@@ -0,0 +1,6 @@
+{
+ "requestId": "123456-1000",
+ "subRequestId": "sub-123456-1000",
+ "originatorId": "sdnc",
+ "testId": 212.2
+}
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/data/measurementGroups.json b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/data/measurementGroups.json
new file mode 100644
index 000000000..e615968ac
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/data/measurementGroups.json
@@ -0,0 +1,34 @@
+[
+ {
+ "measurementGroup": {
+ "measurementTypes": [
+ {
+ "measurementType": "countera"
+ },
+ {
+ "measurementType": "counterb"
+ }
+ ],
+ "managedObjectDNsBasic": [
+ {
+ "DN": "dna"
+ },
+ {
+ "DN": "dnb"
+ }
+ ]
+ }
+ },
+ {
+ "measurementGroup": {
+ "measurementTypes": [
+ {
+ "measurementType": "counterc"
+ },
+ {
+ "measurementType": "counterd"
+ }
+ ]
+ }
+ }
+]
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/commonHeaderTypeWithOptional.json b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/commonHeaderTypeWithOptional.json
new file mode 100644
index 000000000..d8d994fda
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/commonHeaderTypeWithOptional.json
@@ -0,0 +1,23 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "type": "object",
+ "properties": {
+ "requestId": {
+ "type": "string"
+ },
+ "subRequestId": {
+ "type": "string"
+ },
+ "originatorId": {
+ "type": "string"
+ },
+ "testId": {
+ "type": "integer"
+ }
+ },
+ "required": [
+ "requestId",
+ "subRequestId",
+ "originatorId"
+ ]
+}
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/commonHeaderType_draft04.json b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/commonHeaderType_draft04.json
new file mode 100644
index 000000000..de1c05b6f
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/commonHeaderType_draft04.json
@@ -0,0 +1,24 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "type": "object",
+ "properties": {
+ "requestId": {
+ "type": "string"
+ },
+ "subRequestId": {
+ "type": "string"
+ },
+ "originatorId": {
+ "type": "string"
+ },
+ "testId": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "requestId",
+ "subRequestId",
+ "originatorId",
+ "testId"
+ ]
+}
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/commonHeaderType_draft07.json b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/commonHeaderType_draft07.json
new file mode 100644
index 000000000..94558ffe5
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/commonHeaderType_draft07.json
@@ -0,0 +1,52 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Root",
+ "type": "object",
+ "required": [
+ "requestId",
+ "subRequestId",
+ "originatorId",
+ "testId"
+ ],
+ "properties": {
+ "requestId": {
+ "$id": "#root/requestId",
+ "title": "Requestid",
+ "type": "string",
+ "default": "",
+ "examples": [
+ "123456-1000"
+ ],
+ "pattern": "^[0-9]*-[0-9]*$"
+ },
+ "subRequestId": {
+ "$id": "#root/subRequestId",
+ "title": "Subrequestid",
+ "type": "string",
+ "default": "",
+ "examples": [
+ "sub-123456-1000"
+ ],
+ "pattern": "^.*$"
+ },
+ "originatorId": {
+ "$id": "#root/originatorId",
+ "title": "Originatorid",
+ "type": "string",
+ "default": "",
+ "examples": [
+ "sdnc"
+ ],
+ "pattern": "^.*$"
+ },
+ "testId": {
+ "$id": "#root/testId",
+ "title": "Testid",
+ "type": "number",
+ "examples": [
+ 212.2
+ ],
+ "default": 0
+ }
+ }
+}
diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/measurementGroupsType.json b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/measurementGroupsType.json
new file mode 100644
index 000000000..41e598f93
--- /dev/null
+++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/resources/schema/measurementGroupsType.json
@@ -0,0 +1,61 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "type": "array",
+ "default": [],
+ "items": {
+ "type": "object",
+ "required": [
+ "measurementGroup"
+ ],
+ "properties": {
+ "measurementGroup": {
+ "type": "object",
+ "required": [
+ "measurementTypes"
+ ],
+ "properties": {
+ "measurementTypes": {
+ "type": "array",
+ "default": [],
+ "items": {
+ "type": "object",
+ "required": [
+ "measurementType"
+ ],
+ "properties": {
+ "measurementType": {
+ "type": "string",
+ "default": "",
+ "examples": [
+ "countera"
+ ],
+ "pattern": "^.*$"
+ }
+ }
+ }
+ },
+ "managedObjectDNsBasic": {
+ "type": "array",
+ "default": [],
+ "items": {
+ "type": "object",
+ "required": [
+ "DN"
+ ],
+ "properties": {
+ "DN": {
+ "type": "string",
+ "default": "",
+ "examples": [
+ "dna"
+ ],
+ "pattern": "^.*$"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}