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