02aea150c2498f256bda6ec196926128e559c5c0
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2022 Bell Canada. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.apex.plugins.context.schema.json;
22
23 import com.google.gson.Gson;
24 import com.google.gson.JsonElement;
25 import com.google.gson.stream.JsonReader;
26 import com.google.gson.stream.JsonWriter;
27 import com.worldturner.medeia.api.SchemaSource;
28 import com.worldturner.medeia.api.StringInputSource;
29 import com.worldturner.medeia.api.StringSchemaSource;
30 import com.worldturner.medeia.api.gson.MedeiaGsonApi;
31 import com.worldturner.medeia.schema.validation.SchemaValidator;
32 import java.io.StringWriter;
33 import java.util.List;
34 import java.util.Map;
35 import org.onap.policy.apex.context.ContextRuntimeException;
36 import org.onap.policy.apex.context.impl.schema.AbstractSchemaHelper;
37 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
38 import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
39
40 /**
41  * This class is the implementation of the {@link org.onap.policy.apex.context.SchemaHelper} interface for JSON schema.
42  */
43 public class JsonSchemaHelper extends AbstractSchemaHelper {
44
45     private static final Gson gson = new Gson();
46
47     private MedeiaGsonApi api = new MedeiaGsonApi();
48     private SchemaValidator validator;
49
50     @Override
51     public void init(final AxKey userKey, final AxContextSchema schema) {
52         super.init(userKey, schema);
53
54         try {
55             SchemaSource source = new StringSchemaSource(schema.getSchema());
56             validator = api.loadSchema(source);
57         } catch (final Exception e) {
58             final String resultSting = userKey.getId() + ": json context schema \"" + schema.getId()
59                 + "\" schema is invalid, schema: " + schema.getSchema();
60             throw new ContextRuntimeException(resultSting, e);
61         }
62     }
63
64     @Override
65     public Object createNewInstance(final String stringValue) {
66         return unmarshal(stringValue);
67     }
68
69     @Override
70     public Object createNewInstance(final Object incomingObject) {
71         if (incomingObject instanceof JsonElement) {
72             final var elementJsonString = gson.toJson((JsonElement) incomingObject);
73
74             return createNewInstance(elementJsonString);
75         } else {
76             final var returnString =
77                 getUserKey().getId() + ": the object \"" + incomingObject + "\" is not an instance of JsonObject";
78             throw new ContextRuntimeException(returnString);
79         }
80     }
81
82     @Override
83     public Object unmarshal(Object object) {
84         // If an object is already in the correct format, just carry on
85         if (passThroughObject(object)) {
86             return object;
87         }
88         var objectString = (String) object;
89         JsonReader reader = api.createJsonReader(validator, new StringInputSource(objectString));
90         return gson.fromJson(reader, Object.class);
91     }
92
93     @Override
94     public String marshal2String(Object schemaObject) {
95         StringWriter stringWriter = new StringWriter();
96         validateAndDecode(schemaObject, stringWriter);
97         return stringWriter.toString();
98     }
99
100     @Override
101     public Object marshal2Object(Object schemaObject) {
102         return validateAndDecode(schemaObject, new StringWriter());
103     }
104
105     private JsonElement validateAndDecode(Object schemaObject, StringWriter stringWriter) {
106         JsonWriter jsonWriter = api.createJsonWriter(validator, stringWriter);
107         jsonWriter.setIndent("  "); // to enable pretty print
108         JsonElement jsonObj = gson.toJsonTree(schemaObject);
109         gson.toJson(jsonObj, jsonWriter);
110         return jsonObj;
111     }
112
113     /**
114      * Check if we can pass this object straight through encoding or decoding.
115      *
116      * @param object the object to check
117      * @return true if it's a straight pass through
118      */
119     private boolean passThroughObject(final Object object) {
120         return (object instanceof Map || object instanceof List);
121     }
122 }