1b8dacad4b7bdd3cefa2f53ed8c657e1afe46c48
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2019 Nordix Foundation.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.apex.service.parameters.engineservice;
23
24 import com.google.gson.JsonDeserializationContext;
25 import com.google.gson.JsonDeserializer;
26 import com.google.gson.JsonElement;
27 import com.google.gson.JsonObject;
28 import com.google.gson.JsonParseException;
29 import com.google.gson.JsonSerializationContext;
30 import com.google.gson.JsonSerializer;
31
32 import java.lang.reflect.Type;
33 import java.util.Map.Entry;
34
35 import org.onap.policy.apex.context.impl.schema.java.JavaSchemaHelperParameters;
36 import org.onap.policy.apex.context.parameters.ContextParameters;
37 import org.onap.policy.apex.context.parameters.DistributorParameters;
38 import org.onap.policy.apex.context.parameters.LockManagerParameters;
39 import org.onap.policy.apex.context.parameters.PersistorParameters;
40 import org.onap.policy.apex.context.parameters.SchemaHelperParameters;
41 import org.onap.policy.apex.context.parameters.SchemaParameters;
42 import org.onap.policy.apex.core.engine.EngineParameters;
43 import org.onap.policy.apex.core.engine.ExecutorParameters;
44 import org.onap.policy.common.parameters.ParameterGroup;
45 import org.onap.policy.common.parameters.ParameterRuntimeException;
46 import org.slf4j.ext.XLogger;
47 import org.slf4j.ext.XLoggerFactory;
48
49 /**
50  * This class deserializes engine service parameters from JSON format. The class produces an
51  * {@link EngineServiceParameters} instance from incoming JSON read from a configuration file in JSON format.
52  *
53  * @author Liam Fallon (liam.fallon@ericsson.com)
54  */
55 public class EngineServiceParametersJsonAdapter
56                 implements JsonSerializer<EngineParameters>, JsonDeserializer<EngineParameters> {
57     private static final XLogger LOGGER = XLoggerFactory.getXLogger(EngineServiceParametersJsonAdapter.class);
58
59     private static final String PARAMETER_CLASS_NAME = "parameterClassName";
60
61     // @formatter:off
62     private static final String CONTEXT_PARAMETERS      = "contextParameters";
63     private static final String DISTRIBUTOR_PARAMETERS  = "distributorParameters";
64     private static final String LOCK_MANAGER_PARAMETERS = "lockManagerParameters";
65     private static final String PERSISTOR_PARAMETERS    = "persistorParameters";
66     private static final String SCHEMA_PARAMETERS       = "schemaParameters";
67     private static final String EXECUTOR_PARAMETERS     = "executorParameters";
68     // @formatter:on
69
70     /**
71      * {@inheritDoc}.
72      */
73     @Override
74     public JsonElement serialize(final EngineParameters src, final Type typeOfSrc,
75                     final JsonSerializationContext context) {
76         final String returnMessage = "serialization of Apex parameters to Json is not supported";
77         LOGGER.error(returnMessage);
78         throw new ParameterRuntimeException(returnMessage);
79     }
80
81     /**
82      * {@inheritDoc}.
83      */
84     @Override
85     public EngineParameters deserialize(final JsonElement json, final Type typeOfT,
86                     final JsonDeserializationContext context) {
87         final JsonObject engineParametersJsonObject = json.getAsJsonObject();
88
89         final EngineParameters engineParameters = new EngineParameters();
90
91         // Deserialise context parameters, they may be a subclass of the ContextParameters class
92         engineParameters.setContextParameters(
93                         (ContextParameters) context.deserialize(engineParametersJsonObject, ContextParameters.class));
94
95         // Context parameter wrangling
96         getContextParameters(engineParametersJsonObject, engineParameters, context);
97
98         // Executor parameter wrangling
99         getExecutorParameters(engineParametersJsonObject, engineParameters, context);
100
101         return engineParameters;
102     }
103
104     /**
105      * Get the context parameters for Apex.
106      *
107      * @param engineParametersJsonObject The input JSON
108      * @param engineParameters The output parameters
109      * @param context the JSON context
110      */
111     private void getContextParameters(final JsonObject engineParametersJsonObject,
112                     final EngineParameters engineParameters, final JsonDeserializationContext context) {
113         final JsonElement contextParametersElement = engineParametersJsonObject.get(CONTEXT_PARAMETERS);
114
115         // Context parameters are optional so if the element does not exist, just return
116         if (contextParametersElement == null) {
117             return;
118         }
119
120         // We do this because the JSON parameters may be for a subclass of ContextParameters
121         final ContextParameters contextParameters = (ContextParameters) deserializeParameters(CONTEXT_PARAMETERS,
122                         contextParametersElement, context);
123
124         // We know this will work because if the context parameters was not a Json object, the
125         // previous deserializeParameters() call would not have worked
126         final JsonObject contextParametersObject = engineParametersJsonObject.get(CONTEXT_PARAMETERS).getAsJsonObject();
127
128         // Now get the distributor, lock manager, and persistence parameters
129         final JsonElement distributorParametersElement = contextParametersObject.get(DISTRIBUTOR_PARAMETERS);
130         if (distributorParametersElement != null) {
131             contextParameters.setDistributorParameters((DistributorParameters) deserializeParameters(
132                             DISTRIBUTOR_PARAMETERS, distributorParametersElement, context));
133         }
134
135         final JsonElement lockManagerParametersElement = contextParametersObject.get(LOCK_MANAGER_PARAMETERS);
136         if (lockManagerParametersElement != null) {
137             contextParameters.setLockManagerParameters((LockManagerParameters) deserializeParameters(
138                             LOCK_MANAGER_PARAMETERS, lockManagerParametersElement, context));
139         }
140
141         final JsonElement persistorParametersElement = contextParametersObject.get(PERSISTOR_PARAMETERS);
142         if (persistorParametersElement != null) {
143             contextParameters.setPersistorParameters((PersistorParameters) deserializeParameters(PERSISTOR_PARAMETERS,
144                             persistorParametersElement, context));
145         }
146
147         // Schema Handler parameter wrangling
148         getSchemaHandlerParameters(contextParametersObject, contextParameters, context);
149
150         // Get the engine plugin parameters
151         engineParameters.setContextParameters(contextParameters);
152     }
153
154     /**
155      * Get the executor parameters for Apex.
156      *
157      * @param engineParametersJsonObject The input JSON
158      * @param engineParameters The output parameters
159      * @param context the JSON context
160      */
161     private void getExecutorParameters(final JsonObject engineParametersJsonObject,
162                     final EngineParameters engineParameters, final JsonDeserializationContext context) {
163         final JsonElement executorParametersElement = engineParametersJsonObject.get(EXECUTOR_PARAMETERS);
164
165         // Executor parameters are mandatory so if the element does not exist throw an exception
166         if (executorParametersElement == null) {
167             final String returnMessage = "no \"" + EXECUTOR_PARAMETERS
168                             + "\" entry found in parameters, at least one executor parameter entry must be specified";
169             LOGGER.error(returnMessage);
170             throw new ParameterRuntimeException(returnMessage);
171         }
172
173         // Deserialize the executor parameters
174         final JsonObject executorParametersJsonObject = engineParametersJsonObject.get(EXECUTOR_PARAMETERS)
175                         .getAsJsonObject();
176
177         for (final Entry<String, JsonElement> executorEntries : executorParametersJsonObject.entrySet()) {
178             final ExecutorParameters executorParameters = (ExecutorParameters) deserializeParameters(
179                             EXECUTOR_PARAMETERS + ':' + executorEntries.getKey(), executorEntries.getValue(), context);
180             engineParameters.getExecutorParameterMap().put(executorEntries.getKey(), executorParameters);
181         }
182     }
183
184     /**
185      * Get the schema parameters for Apex.
186      *
187      * @param contextParametersJsonObject The input JSON
188      * @param contextParameters The output parameters
189      * @param context the JSON context
190      */
191     private void getSchemaHandlerParameters(final JsonObject contextParametersJsonObject,
192                     final ContextParameters contextParameters, final JsonDeserializationContext context) {
193         final JsonElement schemaParametersElement = contextParametersJsonObject.get(SCHEMA_PARAMETERS);
194
195         // Insert the default Java schema helper
196         contextParameters.getSchemaParameters().getSchemaHelperParameterMap()
197                         .put(SchemaParameters.DEFAULT_SCHEMA_FLAVOUR, new JavaSchemaHelperParameters());
198
199         // Context parameters are optional so if the element does not exist, just return
200         if (schemaParametersElement == null) {
201             return;
202         }
203
204         // Deserialize the executor parameters
205         final JsonObject schemaHelperParametersJsonObject = contextParametersJsonObject.get(SCHEMA_PARAMETERS)
206                         .getAsJsonObject();
207
208         for (final Entry<String, JsonElement> schemaHelperEntries : schemaHelperParametersJsonObject.entrySet()) {
209             contextParameters.getSchemaParameters().getSchemaHelperParameterMap().put(schemaHelperEntries.getKey(),
210                             (SchemaHelperParameters) deserializeParameters(
211                                             SCHEMA_PARAMETERS + ':' + schemaHelperEntries.getKey(),
212                                             schemaHelperEntries.getValue(), context));
213         }
214     }
215
216     /**
217      * Deserialize a parameter object that's a superclass of the AbstractParameters class.
218      *
219      * @param parametersLabel Label to use for error messages
220      * @param parametersElement The JSON object holding the parameters
221      * @param context The GSON context
222      * @return the parameters
223      * @throws ParameterRuntimeException on errors reading the parameters
224      */
225     private ParameterGroup deserializeParameters(final String parametersLabel, final JsonElement parametersElement,
226                     final JsonDeserializationContext context) {
227         JsonObject parametersObject = null;
228
229         // Check that the JSON element is a JSON object
230         if (parametersElement.isJsonObject()) {
231             parametersObject = parametersElement.getAsJsonObject();
232         } else {
233             final String returnMessage = "value of \"" + parametersLabel + "\" entry is not a parameter JSON object";
234             LOGGER.error(returnMessage);
235             throw new ParameterRuntimeException(returnMessage);
236         }
237
238         // Get the parameter class name for instantiation in deserialization
239         final JsonElement parameterClassNameElement = parametersObject.get(PARAMETER_CLASS_NAME);
240         if (parameterClassNameElement == null) {
241             final String returnMessage = "could not find field \"" + PARAMETER_CLASS_NAME + "\" in \"" + parametersLabel
242                             + "\" entry";
243             LOGGER.error(returnMessage);
244             throw new ParameterRuntimeException(returnMessage);
245         }
246
247         // Check the parameter is a JSON primitive
248         if (!parameterClassNameElement.isJsonPrimitive()) {
249             final String returnMessage = "value for field \"" + PARAMETER_CLASS_NAME + "\" of \"" + parametersLabel
250                             + "\" entry is not a plain string";
251             LOGGER.error(returnMessage);
252             throw new ParameterRuntimeException(returnMessage);
253         }
254
255         // Check the parameter has a value
256         final String parameterClassName = parameterClassNameElement.getAsString();
257         if (parameterClassName == null || parameterClassName.trim().length() == 0) {
258             final String returnMessage = "value for field \"" + PARAMETER_CLASS_NAME + "\" in \"" + parametersLabel
259                             + "\" entry is not specified or is blank";
260             LOGGER.error(returnMessage);
261             throw new ParameterRuntimeException(returnMessage);
262         }
263
264         // Deserialize the parameters using GSON
265         ParameterGroup parameters = null;
266         try {
267             parameters = context.deserialize(parametersObject, Class.forName(parameterClassName));
268         } catch (JsonParseException | ClassNotFoundException e) {
269             final String returnMessage = "failed to deserialize the parameters for \"" + parametersLabel + "\" "
270                             + "to parameter class \"" + parameterClassName + "\"\n" + e.getClass().getName() + ": "
271                             + e.getMessage();
272             LOGGER.error(returnMessage, e);
273             throw new ParameterRuntimeException(returnMessage, e);
274         }
275
276         return parameters;
277     }
278 }