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