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