44993ef1ebac2844b40ed4e25f4d44be1cc8bb42
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 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.client.editor.rest.handling;
22
23 import com.google.gson.Gson;
24 import com.google.gson.GsonBuilder;
25 import com.google.gson.JsonObject;
26
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import org.onap.policy.apex.client.editor.rest.handling.bean.BeanModel;
31 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
32 import org.onap.policy.apex.model.basicmodel.concepts.AxKeyInfo;
33 import org.onap.policy.apex.model.modelapi.ApexApiResult;
34 import org.onap.policy.apex.model.modelapi.ApexApiResult.Result;
35 import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
36 import org.slf4j.ext.XLogger;
37 import org.slf4j.ext.XLoggerFactory;
38
39 /**
40  * This class handles commands on Apex models.
41  */
42 public class ModelHandler implements RestCommandHandler {
43
44     // Get a reference to the logger
45     private static final XLogger LOGGER = XLoggerFactory.getXLogger(ModelHandler.class);
46
47     // Recurring string constants
48     private static final String OK = ": OK";
49     private static final String NOT_OK = ": Not OK";
50     private static final String KEY = "key";
51     private static final String NAME = "name";
52     private static final String VERSION = "version";
53     private static final String UUID = "uuid";
54     private static final String DESCRIPTION = "description";
55     private static final String POLICY_KEY = "policyKey";
56     private static final String APEX_KEY_INFO = "apexKeyInfo";
57
58     /**
59      * {@inheritDoc}.
60      */
61     @Override
62     public ApexApiResult executeRestCommand(final RestSession session, final RestCommandType commandType,
63                     final RestCommand command) {
64         if (!RestCommandType.MODEL.equals(commandType)) {
65             return getUnsupportedCommandResultMessage(session, commandType, command);
66         }
67
68         switch (command) {
69             case ANALYSE:
70                 return analyse(session);
71             case VALIDATE:
72                 return validate(session);
73             case GET_KEY:
74                 return getModelKey(session);
75             case LIST:
76                 return listModel(session);
77             case DOWNLOAD:
78                 return downloadModel(session);
79             case DELETE:
80                 return deleteModel(session);
81             default:
82                 return getUnsupportedCommandResultMessage(session, commandType, command);
83         }
84     }
85
86     /**
87      * {@inheritDoc}.
88      */
89     @Override
90     public ApexApiResult executeRestCommand(final RestSession session, final RestCommandType commandType,
91                     final RestCommand command, final String jsonString) {
92         if (!RestCommandType.MODEL.equals(commandType)) {
93             return getUnsupportedCommandResultMessage(session, commandType, command);
94         }
95
96         switch (command) {
97             case LOAD:
98                 return loadFromString(session, jsonString);
99             case CREATE:
100                 return createModel(session, jsonString);
101             case UPDATE:
102                 return updateModel(session, jsonString);
103             default:
104                 return getUnsupportedCommandResultMessage(session, commandType, command);
105         }
106     }
107
108     /**
109      * {@inheritDoc}.
110      */
111     @Override
112     public ApexApiResult executeRestCommand(final RestSession session, final RestCommandType commandType,
113                     final RestCommand command, final String name, final String version) {
114         return getUnsupportedCommandResultMessage(session, commandType, command);
115     }
116
117     /**
118      * Load the model from a JSON string for this session.
119      *
120      * @param session the Apex model editing session
121      * @param jsonString the JSON string to be parsed. The returned value(s) will be similar to {@link AxPolicyModel},
122      *        with merged {@linkplain AxKeyInfo} for the root object.
123      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
124      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
125      */
126     private ApexApiResult loadFromString(final RestSession session, final String jsonString) {
127         LOGGER.entry(jsonString);
128
129         session.editModel();
130
131         ApexApiResult result = session.getApexModelEdited().loadFromString(jsonString);
132
133         session.finishSession(result.isOk());
134
135         LOGGER.exit("Model/Load" + (result != null && result.isOk() ? OK : NOT_OK));
136         return result;
137     }
138
139     /**
140      * Analyse the model and return analysis results. If successful the analysis results will be available in the
141      * messages in the result.
142      *
143      * @param session the Apex model editing session
144      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
145      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
146      */
147     private ApexApiResult analyse(final RestSession session) {
148         LOGGER.entry();
149
150         ApexApiResult result = session.getApexModel().analyse();
151
152         LOGGER.exit("Model/Analyse" + (result != null && result.isOk() ? OK : NOT_OK));
153         return result;
154     }
155
156     /**
157      * Validate the model and return validation results. If successful the validation results will be available in the
158      * messages in the result.
159      *
160      * @param session the Apex model editing session
161      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
162      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
163      */
164     private ApexApiResult validate(final RestSession session) {
165         LOGGER.entry();
166
167         ApexApiResult result = session.getApexModel().validate();
168
169         LOGGER.exit("Model/Validate" + (result != null && result.isOk() ? OK : NOT_OK));
170         return result;
171     }
172
173     /**
174      * Creates the new model model for this session.
175      *
176      * @param session the Apex model editing session
177      * @param jsonString the JSON string to be parsed containing the new model. See {@linkplain BeanModel}
178      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
179      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
180      */
181     private ApexApiResult createModel(final RestSession session, final String jsonString) {
182         LOGGER.entry(jsonString);
183
184         final BeanModel jsonbean = RestUtils.getJsonParameters(jsonString, BeanModel.class);
185
186         session.editModel();
187
188         ApexApiResult result = session.getApexModelEdited().createModel(jsonbean.getName(), jsonbean.getVersion(),
189                         jsonbean.getUuid(), jsonbean.getDescription());
190
191         session.finishSession(result.isOk());
192
193         LOGGER.exit("Model/Create" + (result != null && result.isOk() ? OK : NOT_OK));
194         return result;
195     }
196
197     /**
198      * Update the model for this session.
199      *
200      * @param session the Apex model editing session
201      * @param jsonString the JSON string to be parsed containing the updated model. See {@linkplain BeanModel}
202      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
203      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
204      */
205     private ApexApiResult updateModel(final RestSession session, final String jsonString) {
206         LOGGER.entry(jsonString);
207
208         final BeanModel jsonbean = RestUtils.getJsonParameters(jsonString, BeanModel.class);
209
210         session.editModel();
211
212         ApexApiResult result = session.getApexModelEdited().updateModel(jsonbean.getName(), jsonbean.getVersion(),
213                         jsonbean.getUuid(), jsonbean.getDescription());
214
215         session.finishSession(result.isOk());
216
217         LOGGER.exit("Model/Update" + (result != null && result.isOk() ? OK : NOT_OK));
218         return result;
219     }
220
221     /**
222      * Gets the key for the model for this session. If successful the model key will be available in the first message
223      * in the result. See {@linkplain AxKey}
224      *
225      * @param session the Apex model editing session
226      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
227      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
228      */
229     private ApexApiResult getModelKey(final RestSession session) {
230         LOGGER.entry();
231
232         ApexApiResult result = session.getApexModel().getModelKey();
233
234         LOGGER.exit("Model/GetKey" + (result != null && result.isOk() ? OK : NOT_OK));
235         return result;
236     }
237
238     /**
239      * Retrieve the model for this session. If successful the model will be available in the first message in the
240      * result. The returned value will be similar to a {@link AxPolicyModel}, with merged {@linkplain AxKeyInfo} for the
241      * root object.
242      *
243      * @param session the Apex model editing session
244      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
245      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
246      */
247     private ApexApiResult listModel(final RestSession session) {
248         LOGGER.entry();
249
250         ApexApiResult result = session.getApexModel().listModel();
251
252         result = addKeyInfo2Messages(session, result);
253
254         LOGGER.exit("Model/Get" + (result != null && result.isOk() ? OK : NOT_OK));
255         return result;
256     }
257
258     /**
259      * Download the model for this session as a String.
260      *
261      * @param session the Apex model editing session
262      * @return the model represented as a JSON string. See {@linkplain AxPolicyModel}
263      */
264     private ApexApiResult downloadModel(final RestSession session) {
265         LOGGER.entry();
266
267         ApexApiResult result = session.getApexModel().listModel();
268
269         LOGGER.exit("Model/Download" + (result != null && result.isOk() ? OK : NOT_OK));
270         return result;
271     }
272
273     /**
274      * Delete the model for this session.
275      *
276      * @param session the Apex model editing session
277      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
278      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
279      */
280     private ApexApiResult deleteModel(final RestSession session) {
281         LOGGER.entry();
282
283         session.editModel();
284
285         ApexApiResult result = session.getApexModel().deleteModel();
286
287         session.finishSession(result.isOk());
288
289         LOGGER.exit("Model/Delete" + (result != null && result.isOk() ? OK : NOT_OK));
290         return result;
291     }
292
293     /**
294      * The json strings representing the objects listed, stored in result.messages[], does not contain the
295      * AxKeyInformation for that object. This utility method retrieves the AxKeyInfo for each object and adds it to the
296      * json for the object.
297      *
298      * @param session the Apex model editing session
299      * @param incomingResult The list result, containing JSON representations of objects stored in its "messages" array
300      * @return The list result, containing JSON augmented representations of objects stored in its "messages" array
301      */
302     private ApexApiResult addKeyInfo2Messages(final RestSession session, final ApexApiResult incomingResult) {
303         final ApexApiResult result = new ApexApiResult(incomingResult.getResult());
304         result.setMessages(incomingResult.getMessages());
305
306         final List<String> messages = incomingResult.getMessages();
307         final List<String> augmentedMessages = new ArrayList<>(messages.size());
308
309         for (final String message : messages) {
310             augmentedMessages.add(addKeyInfo2Message(session, message));
311         }
312         result.setMessages(augmentedMessages);
313
314         if (messages.size() != augmentedMessages.size()) {
315             result.setResult(Result.OTHER_ERROR);
316             result.addMessage("Failed to add KeyInfo to all results. Results are not complete");
317         }
318
319         return result;
320     }
321
322     /**
323      * Augment a message with key information.
324      * 
325      * @param session the Apex model editing session
326      * @param message The message to augment
327      * @return the augmented message
328      */
329     private String addKeyInfo2Message(final RestSession session, final String message) {
330         final Gson gson = new GsonBuilder().serializeNulls().enableComplexMapKeySerialization().create();
331
332         JsonObject jsonObject = gson.fromJson(message, JsonObject.class);
333         if (jsonObject == null) {
334             return message;
335         }
336
337         String name = readFieldFromJsonObject(jsonObject, NAME, null);
338         String version = readFieldFromJsonObject(jsonObject, VERSION, null);
339
340         if (name == null && version == null) {
341             JsonObject newJsonObject = getSubJsonObject(jsonObject);
342
343             if (newJsonObject != null) {
344                 jsonObject = newJsonObject;
345                 name = readFieldFromJsonObject(jsonObject, NAME, name);
346                 version = readFieldFromJsonObject(jsonObject, VERSION, version);
347             }
348         }
349
350         if (name == null || version == null || !setUuidAndDescription(session, jsonObject, name, version)) {
351             jsonObject.addProperty(UUID, (String) null);
352             jsonObject.addProperty(DESCRIPTION, (String) null);
353         }
354
355         return gson.toJson(jsonObject);
356     }
357
358     /**
359      * Get an embedded JSON object for the given JSON object.
360      * 
361      * @param jsonObject the input JSON object
362      * @return the embedded JSON object
363      */
364     private JsonObject getSubJsonObject(JsonObject jsonObject) {
365         if (jsonObject.entrySet() != null && !jsonObject.entrySet().isEmpty()) {
366             return (JsonObject) jsonObject.entrySet().iterator().next().getValue();
367         } else {
368             return null;
369         }
370     }
371
372     /**
373      * Condition a field so its key information can be looked up.
374      * 
375      * @param jsonObject the object to query
376      * @param fieldTag the tag of the field to condition
377      * @param fieldValue the value of the field to condition
378      * @return
379      */
380     private String readFieldFromJsonObject(final JsonObject jsonObject, final String fieldTag, final String value) {
381         String lookedupValue = value;
382
383         if (jsonObject != null && jsonObject.get(KEY) != null && jsonObject.get(KEY).isJsonObject()
384                         && jsonObject.getAsJsonObject(KEY).get(fieldTag) != null) {
385             lookedupValue = jsonObject.getAsJsonObject(KEY).get(fieldTag).getAsString();
386         } else if (jsonObject != null && jsonObject.get(POLICY_KEY) != null && jsonObject.get(POLICY_KEY).isJsonObject()
387                         && jsonObject.getAsJsonObject(POLICY_KEY).get(fieldTag) != null) {
388             lookedupValue = jsonObject.getAsJsonObject(POLICY_KEY).get(fieldTag).getAsString();
389         }
390         return lookedupValue;
391     }
392
393     /**
394      * Look up the UUID and description in the key information for a concept.
395      * 
396      * @param session the Apex editor session
397      * @param jsonObject the JSON object to place the fields in
398      * @param name the concept name to look up
399      * @param version the concept version to look up
400      */
401     private boolean setUuidAndDescription(final RestSession session, JsonObject jsonObject, String name,
402                     String version) {
403         // Look up the key information for the name and version
404         JsonObject keyInfoJsonObject = lookupKeyInfo(session, name, version);
405         if (keyInfoJsonObject == null || keyInfoJsonObject.get(APEX_KEY_INFO) != null) {
406             return false;
407         }
408
409         if (keyInfoJsonObject.get(APEX_KEY_INFO).getAsJsonObject().get("UUID") != null) {
410             jsonObject.addProperty(UUID,
411                             keyInfoJsonObject.get(APEX_KEY_INFO).getAsJsonObject().get("UUID").getAsString());
412         } else {
413             jsonObject.addProperty(UUID, (String) null);
414         }
415
416         if (keyInfoJsonObject.get(APEX_KEY_INFO).getAsJsonObject().get(DESCRIPTION) != null) {
417             jsonObject.addProperty(DESCRIPTION,
418                             keyInfoJsonObject.get(APEX_KEY_INFO).getAsJsonObject().get(DESCRIPTION).getAsString());
419         } else {
420             jsonObject.addProperty(DESCRIPTION, (String) null);
421         }
422
423         return true;
424     }
425
426     /**
427      * Look up the key information for the given concept name and value.
428      * 
429      * @param session the Apex editor session
430      * @param name the concept name to look up
431      * @param version the concept version to look up
432      * @return a JSON version of the concept key information
433      */
434     private JsonObject lookupKeyInfo(final RestSession session, final String name, final String version) {
435         final ApexApiResult keyInfoResult = session.getApexModel().listKeyInformation(name, version);
436         final List<String> keyInfoMessages = keyInfoResult.getMessages();
437
438         if (keyInfoResult.isNok() || keyInfoMessages == null || keyInfoMessages.isEmpty()) {
439             return null;
440         }
441
442         final Gson gson = new GsonBuilder().serializeNulls().enableComplexMapKeySerialization().create();
443         final String keyInfoJson = keyInfoMessages.get(0);
444         return gson.fromJson(keyInfoJson, JsonObject.class);
445     }
446 }