2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2018 Ericsson. All rights reserved.
4 * Modifications Copyright (C) 2019-2022 Nordix Foundation.
5 * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2021 Bell Canada. All rights reserved.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
20 * SPDX-License-Identifier: Apache-2.0
21 * ============LICENSE_END=========================================================
24 package org.onap.policy.gui.editors.apex.rest.handling;
26 import com.google.gson.GsonBuilder;
27 import com.google.gson.JsonObject;
28 import java.util.ArrayList;
29 import java.util.List;
30 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
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.modelapi.ApexModel;
36 import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
37 import org.onap.policy.gui.editors.apex.rest.handling.bean.BeanModel;
38 import org.onap.policy.gui.editors.apex.rest.handling.plugin.upload.PolicyUploadHandler;
39 import org.slf4j.ext.XLogger;
40 import org.slf4j.ext.XLoggerFactory;
41 import org.springframework.beans.factory.annotation.Autowired;
42 import org.springframework.stereotype.Service;
45 * This class handles commands on Apex models.
48 public class ModelHandler implements RestCommandHandler {
50 // Get a reference to the logger
51 private static final XLogger LOGGER = XLoggerFactory.getXLogger(ModelHandler.class);
53 private final PolicyUploadHandler policyUploadHandler;
55 // Recurring string constants
56 private static final String OK = ": OK";
57 private static final String NOT_OK = ": Not OK";
58 private static final String KEY = "key";
59 private static final String NAME = "name";
60 private static final String VERSION = "version";
61 private static final String UUID = "uuid";
62 private static final String DESCRIPTION = "description";
63 private static final String POLICY_KEY = "policyKey";
64 private static final String APEX_KEY_INFO = "apexKeyInfo";
67 public ModelHandler(PolicyUploadHandler policyUploadHandler) {
68 this.policyUploadHandler = policyUploadHandler;
75 public ApexApiResult executeRestCommand(final RestSession session, final RestCommandType commandType,
76 final RestCommand command) {
77 if (!RestCommandType.MODEL.equals(commandType)) {
78 return getUnsupportedCommandResultMessage(session, commandType, command);
83 return analyse(session);
85 return validate(session);
87 return getModelKey(session);
89 return listModel(session);
91 return downloadModel(session);
93 return deleteModel(session);
95 return getUnsupportedCommandResultMessage(session, commandType, command);
103 public ApexApiResult executeRestCommand(final RestSession session, final RestCommandType commandType,
104 final RestCommand command, final String jsonString) {
105 if (!RestCommandType.MODEL.equals(commandType)) {
106 return getUnsupportedCommandResultMessage(session, commandType, command);
111 return loadFromString(session, jsonString);
113 return createModel(session, jsonString);
115 return updateModel(session, jsonString);
117 return uploadModel(session, jsonString);
119 return getUnsupportedCommandResultMessage(session, commandType, command);
127 public ApexApiResult executeRestCommand(final RestSession session, final RestCommandType commandType,
128 final RestCommand command, final String name, final String version) {
129 return getUnsupportedCommandResultMessage(session, commandType, command);
133 * Load the model from a JSON string for this session.
135 * @param session the Apex model editing session
136 * @param jsonString the JSON string to be parsed. The returned value(s) will be similar to {@link AxPolicyModel},
137 * with merged {@linkplain AxKeyInfo} for the root object.
138 * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
139 * messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
141 private ApexApiResult loadFromString(final RestSession session, final String jsonString) {
142 LOGGER.entry(jsonString);
146 ApexApiResult result = session.loadFromString(jsonString);
148 session.finishSession(result.isOk());
150 LOGGER.exit("Model/Load" + (result.isOk() ? OK : NOT_OK));
155 * Analyse the model and return analysis results. If successful the analysis results will be available in the
156 * messages in the result.
158 * @param session the Apex model editing session
159 * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
160 * messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
162 private ApexApiResult analyse(final RestSession session) {
165 ApexApiResult result = session.getApexModel().analyse();
167 LOGGER.exit("Model/Analyse" + (result != null && result.isOk() ? OK : NOT_OK));
172 * Validate the model and return validation results. If successful the validation results will be available in the
173 * messages in the result.
175 * @param session the Apex model editing session
176 * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
177 * messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
179 private ApexApiResult validate(final RestSession session) {
182 ApexApiResult result = session.getApexModel().validate();
184 LOGGER.exit("Model/Validate" + (result != null && result.isOk() ? OK : NOT_OK));
189 * Creates the new model model for this session.
191 * @param session the Apex model editing session
192 * @param jsonString the JSON string to be parsed containing the new model. See {@linkplain BeanModel}
193 * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
194 * messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
196 private ApexApiResult createModel(final RestSession session, final String jsonString) {
197 LOGGER.entry(jsonString);
199 final var jsonbean = RestUtils.getJsonParameters(jsonString, BeanModel.class);
203 ApexApiResult result = session.getApexModelEdited().createModel(jsonbean.getName(), jsonbean.getVersion(),
204 jsonbean.getUuid(), jsonbean.getDescription());
206 session.finishSession(result.isOk());
208 LOGGER.exit("Model/Create" + (result.isOk() ? OK : NOT_OK));
213 * Update the model for this session.
215 * @param session the Apex model editing session
216 * @param jsonString the JSON string to be parsed containing the updated model. See {@linkplain BeanModel}
217 * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
218 * messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
220 private ApexApiResult updateModel(final RestSession session, final String jsonString) {
221 LOGGER.entry(jsonString);
223 final var jsonbean = RestUtils.getJsonParameters(jsonString, BeanModel.class);
227 ApexApiResult result = session.getApexModelEdited().updateModel(jsonbean.getName(), jsonbean.getVersion(),
228 jsonbean.getUuid(), jsonbean.getDescription());
230 session.finishSession(result.isOk());
232 LOGGER.exit("Model/Update" + (result.isOk() ? OK : NOT_OK));
237 * Gets the key for the model for this session. If successful the model key will be available in the first message
238 * in the result. See {@linkplain AxKey}
240 * @param session the Apex model editing session
241 * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
242 * messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
244 private ApexApiResult getModelKey(final RestSession session) {
247 ApexApiResult result = session.getApexModel().getModelKey();
249 LOGGER.exit("Model/GetKey" + (result != null && result.isOk() ? OK : NOT_OK));
254 * Retrieve the model for this session. If successful the model will be available in the first message in the
255 * result. The returned value will be similar to a {@link AxPolicyModel}, with merged {@linkplain AxKeyInfo} for the
258 * @param session the Apex model editing session
259 * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
260 * messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
262 private ApexApiResult listModel(final RestSession session) {
265 ApexApiResult result = session.getApexModel().listModel();
267 result = addKeyInfo2Messages(session, result);
269 LOGGER.exit("Model/Get" + (result.isOk() ? OK : NOT_OK));
274 * Download the model for this session as a String.
276 * @param session the Apex model editing session
277 * @return the model represented as a JSON string. See {@linkplain AxPolicyModel}
279 private ApexApiResult downloadModel(final RestSession session) {
282 ApexApiResult result = session.downloadModel();
284 LOGGER.exit("Model/Download" + (result.isOk() ? OK : NOT_OK));
289 * Upload the model for this session as a TOSCA service template YAML string to the configured URL.
291 * @param session the Apex model editing session
292 * @param userId the userId to use for upload. If blank, the Spring
293 * config parameter "apex-editor.upload-userid" is used.
294 * @return a result indicating if the upload was successful or not
296 private ApexApiResult uploadModel(final RestSession session, String userId) {
299 // Get the model in TOSCA format
300 ApexApiResult downloadResult = downloadModel(session);
301 if (downloadResult.isNok()) {
302 LOGGER.exit("Model/Upload" + NOT_OK);
303 return downloadResult;
305 String toscaServiceTemplate = downloadResult.getMessage();
307 ApexModel apexModel = session.getApexModel();
308 ApexModel apexModelEdited = session.getApexModelEdited();
309 ApexModel apexModelBeingUploaded = (apexModelEdited == null ? apexModel : apexModelEdited);
311 AxArtifactKey policyModelKey = apexModelBeingUploaded.getPolicyModel().getKey();
313 String policyModelUUid = apexModelBeingUploaded.getPolicyModel().getKeyInformation().get(policyModelKey)
314 .getUuid().toString();
316 var result = policyUploadHandler.doUpload(toscaServiceTemplate, policyModelKey, policyModelUUid, userId);
318 LOGGER.exit("Model/Upload" + (result != null && result.isOk() ? OK : NOT_OK));
323 * Delete the model for this session.
325 * @param session the Apex model editing session
326 * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
327 * messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
329 private ApexApiResult deleteModel(final RestSession session) {
334 ApexApiResult result = session.getApexModel().deleteModel();
336 session.finishSession(result.isOk());
338 LOGGER.exit("Model/Delete" + (result.isOk() ? OK : NOT_OK));
343 * The json strings representing the objects listed, stored in result.messages[], does not contain the
344 * AxKeyInformation for that object. This utility method retrieves the AxKeyInfo for each object and adds it to the
345 * json for the object.
347 * @param session the Apex model editing session
348 * @param incomingResult The list result, containing JSON representations of objects stored in its "messages" array
349 * @return The list result, containing JSON augmented representations of objects stored in its "messages" array
351 private ApexApiResult addKeyInfo2Messages(final RestSession session, final ApexApiResult incomingResult) {
352 final var result = new ApexApiResult(incomingResult.getResult());
353 result.setMessages(incomingResult.getMessages());
355 final List<String> messages = incomingResult.getMessages();
356 final List<String> augmentedMessages = new ArrayList<>(messages.size());
358 for (final String message : messages) {
359 augmentedMessages.add(addKeyInfo2Message(session, message));
361 result.setMessages(augmentedMessages);
363 if (messages.size() != augmentedMessages.size()) {
364 result.setResult(Result.OTHER_ERROR);
365 result.addMessage("Failed to add KeyInfo to all results. Results are not complete");
372 * Augment a message with key information.
374 * @param session the Apex model editing session
375 * @param message The message to augment
376 * @return the augmented message
378 private String addKeyInfo2Message(final RestSession session, final String message) {
379 final var gson = new GsonBuilder().serializeNulls().enableComplexMapKeySerialization().create();
381 var jsonObject = gson.fromJson(message, JsonObject.class);
382 if (jsonObject == null) {
386 String name = readFieldFromJsonObject(jsonObject, NAME, null);
387 String version = readFieldFromJsonObject(jsonObject, VERSION, null);
389 if (name == null && version == null) {
390 var newJsonObject = getSubJsonObject(jsonObject);
392 if (newJsonObject != null) {
393 jsonObject = newJsonObject;
394 name = readFieldFromJsonObject(jsonObject, NAME, name);
395 version = readFieldFromJsonObject(jsonObject, VERSION, version);
399 if (name == null || version == null || !setUuidAndDescription(session, jsonObject, name, version)) {
400 jsonObject.addProperty(UUID, (String) null);
401 jsonObject.addProperty(DESCRIPTION, (String) null);
404 return gson.toJson(jsonObject);
408 * Get an embedded JSON object for the given JSON object.
410 * @param jsonObject the input JSON object
411 * @return the embedded JSON object
413 private JsonObject getSubJsonObject(JsonObject jsonObject) {
414 if (jsonObject.entrySet() != null && !jsonObject.entrySet().isEmpty()) {
415 return (JsonObject) jsonObject.entrySet().iterator().next().getValue();
422 * Condition a field so its key information can be looked up.
424 * @param jsonObject the object to query
425 * @param fieldTag the tag of the field to condition
426 * @param value the default value of the field to condition
427 * @return field read from the json
429 private String readFieldFromJsonObject(final JsonObject jsonObject, final String fieldTag, final String value) {
430 String lookedupValue = value;
432 if (jsonObject != null && jsonObject.get(KEY) != null && jsonObject.get(KEY).isJsonObject()
433 && jsonObject.getAsJsonObject(KEY).get(fieldTag) != null) {
434 lookedupValue = jsonObject.getAsJsonObject(KEY).get(fieldTag).getAsString();
435 } else if (jsonObject != null && jsonObject.get(POLICY_KEY) != null && jsonObject.get(POLICY_KEY).isJsonObject()
436 && jsonObject.getAsJsonObject(POLICY_KEY).get(fieldTag) != null) {
437 lookedupValue = jsonObject.getAsJsonObject(POLICY_KEY).get(fieldTag).getAsString();
439 return lookedupValue;
443 * Look up the UUID and description in the key information for a concept.
445 * @param session the Apex editor session
446 * @param jsonObject the JSON object to place the fields in
447 * @param name the concept name to look up
448 * @param version the concept version to look up
450 private boolean setUuidAndDescription(final RestSession session, JsonObject jsonObject, String name,
452 // Look up the key information for the name and version
453 var keyInfoJsonObject = lookupKeyInfo(session, name, version);
454 if (keyInfoJsonObject == null || keyInfoJsonObject.get(APEX_KEY_INFO) != null) {
458 if (keyInfoJsonObject.get(APEX_KEY_INFO).getAsJsonObject().get("UUID") != null) {
459 jsonObject.addProperty(UUID,
460 keyInfoJsonObject.get(APEX_KEY_INFO).getAsJsonObject().get("UUID").getAsString());
462 jsonObject.addProperty(UUID, (String) null);
465 if (keyInfoJsonObject.get(APEX_KEY_INFO).getAsJsonObject().get(DESCRIPTION) != null) {
466 jsonObject.addProperty(DESCRIPTION,
467 keyInfoJsonObject.get(APEX_KEY_INFO).getAsJsonObject().get(DESCRIPTION).getAsString());
469 jsonObject.addProperty(DESCRIPTION, (String) null);
476 * Look up the key information for the given concept name and value.
478 * @param session the Apex editor session
479 * @param name the concept name to look up
480 * @param version the concept version to look up
481 * @return a JSON version of the concept key information
483 private JsonObject lookupKeyInfo(final RestSession session, final String name, final String version) {
484 final ApexApiResult keyInfoResult = session.getApexModel().listKeyInformation(name, version);
485 final List<String> keyInfoMessages = keyInfoResult.getMessages();
487 if (keyInfoResult.isNok() || keyInfoMessages == null || keyInfoMessages.isEmpty()) {
491 final var gson = new GsonBuilder().serializeNulls().enableComplexMapKeySerialization().create();
492 final String keyInfoJson = keyInfoMessages.get(0);
493 return gson.fromJson(keyInfoJson, JsonObject.class);