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