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