2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2016-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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.apex.model.modelapi.impl;
24 import java.io.ByteArrayInputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.net.MalformedURLException;
30 import java.net.URLConnection;
31 import java.nio.file.Files;
32 import java.util.LinkedHashSet;
33 import java.util.List;
34 import java.util.Properties;
36 import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
37 import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException;
38 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
39 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult;
40 import org.onap.policy.apex.model.basicmodel.dao.ApexDao;
41 import org.onap.policy.apex.model.basicmodel.dao.ApexDaoFactory;
42 import org.onap.policy.apex.model.basicmodel.dao.DaoParameters;
43 import org.onap.policy.apex.model.basicmodel.handling.ApexModelException;
44 import org.onap.policy.apex.model.basicmodel.handling.ApexModelFileWriter;
45 import org.onap.policy.apex.model.basicmodel.handling.ApexModelReader;
46 import org.onap.policy.apex.model.basicmodel.handling.ApexModelStringWriter;
47 import org.onap.policy.apex.model.basicmodel.handling.ApexModelWriter;
48 import org.onap.policy.apex.model.modelapi.ApexApiResult;
49 import org.onap.policy.apex.model.modelapi.ApexModel;
50 import org.onap.policy.apex.model.policymodel.concepts.AxPolicy;
51 import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
52 import org.onap.policy.apex.model.policymodel.handling.PolicyAnalyser;
53 import org.onap.policy.apex.model.policymodel.handling.PolicyAnalysisResult;
54 import org.onap.policy.apex.model.policymodel.handling.PolicyModelComparer;
55 import org.onap.policy.apex.model.policymodel.handling.PolicyModelMerger;
56 import org.onap.policy.apex.model.policymodel.handling.PolicyModelSplitter;
57 import org.onap.policy.common.utils.resources.ResourceUtils;
58 import org.onap.policy.common.utils.resources.TextFileUtils;
59 import org.onap.policy.common.utils.validation.Assertions;
60 import org.slf4j.ext.XLogger;
61 import org.slf4j.ext.XLoggerFactory;
64 * This class acts as a facade for model handling for the Apex Model API.
66 * @author Liam Fallon (liam.fallon@ericsson.com)
68 public class ModelHandlerFacade {
69 private static final String FOUND_IN_DATABASE = " found in database";
70 private static final String FILE_NAME_MAY_NOT_BE_NULL = "fileName may not be null";
71 private static final String MODEL = "model ";
72 private static final String ALREADY_LOADED = " already loaded";
74 private static final XLogger LOGGER = XLoggerFactory.getXLogger(ModelHandlerFacade.class);
76 // Apex model we're working towards
77 private final ApexModel apexModel;
79 // JSON output on list/delete if set
80 private final boolean jsonMode;
83 * This Constructor creates a model handling facade for the given {@link ApexModel}.
85 * @param apexModel the apex model to manipulate
86 * @param apexProperties properties for the model
87 * @param jsonMode set to true to return JSON strings in list and delete operations, otherwise set to false
89 public ModelHandlerFacade(final ApexModel apexModel, final Properties apexProperties, final boolean jsonMode) {
90 Assertions.argumentNotNull(apexModel, "apexModel may not be null");
91 Assertions.argumentNotNull(apexProperties, "apexProperties may not be null");
93 this.apexModel = apexModel;
94 this.jsonMode = jsonMode;
98 * Load an Apex model from a string.
100 * @param modelString the string with the model
101 * @return the result of the operation
103 public ApexApiResult loadFromString(final String modelString) {
104 Assertions.argumentNotNull(modelString, "modelString may not be null");
106 if (!apexModel.getPolicyModel().getKey().equals(AxArtifactKey.getNullKey())) {
107 return new ApexApiResult(ApexApiResult.Result.CONCEPT_EXISTS,
108 MODEL + apexModel.getPolicyModel().getKey().getId() + ALREADY_LOADED);
111 ApexApiResult result = new ApexApiResult();
112 AxPolicyModel newPolicyModel = loadModelFromString(modelString, result);
113 apexModel.setPolicyModel(newPolicyModel != null ? newPolicyModel : new AxPolicyModel());
119 * Load an Apex model from a file.
121 * @param fileName the file name of the file with the model
122 * @return the result of the operation
124 public ApexApiResult loadFromFile(final String fileName) {
125 Assertions.argumentNotNull(fileName, FILE_NAME_MAY_NOT_BE_NULL);
127 if (!apexModel.getPolicyModel().getKey().equals(AxArtifactKey.getNullKey())) {
128 return new ApexApiResult(ApexApiResult.Result.CONCEPT_EXISTS,
129 MODEL + apexModel.getPolicyModel().getKey().getId() + ALREADY_LOADED);
132 ApexApiResult result = new ApexApiResult();
133 AxPolicyModel newPolicyModel = loadModelFromFile(fileName, result);
134 apexModel.setPolicyModel(newPolicyModel != null ? newPolicyModel : new AxPolicyModel());
140 * Save an Apex model to a file.
142 * @param fileName the file name
143 * @param xmlFlag if true, save the file in XML format, otherwise save the file in the default JSON format
144 * @return the result of the operation
146 public ApexApiResult saveToFile(final String fileName, final boolean xmlFlag) {
147 Assertions.argumentNotNull(fileName, FILE_NAME_MAY_NOT_BE_NULL);
149 ApexModelFileWriter<AxPolicyModel> apexModelFileWriter = new ApexModelFileWriter<>(false);
153 apexModelFileWriter.apexModelWriteXmlFile(apexModel.getPolicyModel(), AxPolicyModel.class, fileName);
155 apexModelFileWriter.apexModelWriteJsonFile(apexModel.getPolicyModel(), AxPolicyModel.class, fileName);
157 return new ApexApiResult();
158 } catch (ApexException e) {
159 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
164 * Load an Apex model from a database.
166 * @param modelName the name of the model to load
167 * @param modelVersion the version of the model to load, loads the policy model from the database with this name, if
168 * more than one exist, an exception is thrown
169 * @param daoParameters the parameters to use to access the database over JDBC
170 * @return the result of the operation
172 public ApexApiResult loadFromDatabase(final String modelName, final String modelVersion,
173 final DaoParameters daoParameters) {
174 Assertions.argumentNotNull(modelName, "modelName may not be null");
175 Assertions.argumentNotNull(daoParameters, "DaoParameters may not be null");
177 if (!apexModel.getPolicyModel().getKey().equals(AxArtifactKey.getNullKey())) {
178 return new ApexApiResult(ApexApiResult.Result.CONCEPT_EXISTS,
179 MODEL + apexModel.getPolicyModel().getKey().getId() + ALREADY_LOADED);
182 ApexDao apexDao = null;
184 apexDao = new ApexDaoFactory().createApexDao(daoParameters);
185 apexDao.init(daoParameters);
187 // Single specific model requested
188 if (modelVersion != null) {
189 AxPolicyModel daoPolicyModel =
190 apexDao.get(AxPolicyModel.class, new AxArtifactKey(modelName, modelVersion));
192 if (daoPolicyModel != null) {
193 apexModel.setPolicyModel(daoPolicyModel);
194 return new ApexApiResult();
196 apexModel.setPolicyModel(new AxPolicyModel());
197 return new ApexApiResult(ApexApiResult.Result.FAILED, "no policy model with name " + modelName
198 + " and version " + modelVersion + FOUND_IN_DATABASE);
201 // Fishing expedition
202 return searchInDatabase(modelName, apexDao, apexModel);
204 } catch (ApexException | ApexRuntimeException e) {
205 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
207 if (apexDao != null) {
214 * Search for an Apex model in the database.
216 * @param modelName the name of the model to load
217 * @param apexDao the DAO to use to find the model
218 * @param apexModel the APEX model we are loading the found model into
219 * @return the result of the operation
221 private ApexApiResult searchInDatabase(String modelName, ApexDao apexDao, ApexModel apexModel) {
222 AxPolicyModel foundPolicyModel = null;
224 List<AxPolicyModel> policyModelList = apexDao.getAll(AxPolicyModel.class);
225 for (AxPolicyModel dbPolicyModel : policyModelList) {
226 if (dbPolicyModel.getKey().getName().equals(modelName)) {
227 if (foundPolicyModel == null) {
228 foundPolicyModel = dbPolicyModel;
230 return new ApexApiResult(ApexApiResult.Result.FAILED,
231 "more than one policy model with name " + modelName + FOUND_IN_DATABASE);
236 if (foundPolicyModel != null) {
237 apexModel.setPolicyModel(foundPolicyModel);
238 return new ApexApiResult();
240 apexModel.setPolicyModel(new AxPolicyModel());
241 return new ApexApiResult(ApexApiResult.Result.FAILED,
242 "no policy model with name " + modelName + FOUND_IN_DATABASE);
247 * Save an Apex model to a database.
249 * @param daoParameters the parameters to use to access the database over JDBC
250 * @return the result of the operation
252 public ApexApiResult saveToDatabase(final DaoParameters daoParameters) {
253 ApexDao apexDao = null;
256 apexDao = new ApexDaoFactory().createApexDao(daoParameters);
257 apexDao.init(daoParameters);
259 apexDao.create(apexModel.getPolicyModel());
260 return new ApexApiResult();
261 } catch (ApexException e) {
262 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
264 if (apexDao != null) {
271 * Read an APEX model from a location identified by a URL.
273 * @param urlString the url string
274 * @return the result of the operation
276 public ApexApiResult readFromUrl(final String urlString) {
277 Assertions.argumentNotNull(urlString, "urlString may not be null");
279 if (!apexModel.getPolicyModel().getKey().equals(AxArtifactKey.getNullKey())) {
280 return new ApexApiResult(ApexApiResult.Result.CONCEPT_EXISTS,
281 MODEL + apexModel.getPolicyModel().getKey().getId() + ALREADY_LOADED);
286 apexModelUrl = new URL(urlString);
287 } catch (MalformedURLException e) {
288 ApexApiResult result = new ApexApiResult(ApexApiResult.Result.FAILED);
289 result.addMessage("URL string " + urlString + " is not a valid URL");
290 result.addThrowable(e);
295 ApexModelReader<AxPolicyModel> apexModelReader = new ApexModelReader<>(AxPolicyModel.class);
296 apexModelReader.setValidateFlag(false);
297 AxPolicyModel newPolicyModel = apexModelReader.read(apexModelUrl.openStream());
298 apexModel.setPolicyModel(newPolicyModel != null ? newPolicyModel : new AxPolicyModel());
299 return new ApexApiResult();
300 } catch (ApexModelException | IOException e) {
301 apexModel.setPolicyModel(new AxPolicyModel());
302 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
307 * Write an APEX model to a location identified by a URL.
309 * @param urlString the URL to read the model from
310 * @param xmlFlag if true, save the file in XML format, otherwise save the file in the default JSON format
311 * @return the result of the operation
313 public ApexApiResult writeToUrl(final String urlString, final boolean xmlFlag) {
314 Assertions.argumentNotNull(urlString, "urlString may not be null");
318 apexModelUrl = new URL(urlString);
319 } catch (MalformedURLException e) {
320 ApexApiResult result = new ApexApiResult(ApexApiResult.Result.FAILED);
321 result.addMessage("URL string " + urlString + " is not a valid URL");
322 result.addThrowable(e);
327 ApexModelWriter<AxPolicyModel> apexModelWriter = new ApexModelWriter<>(AxPolicyModel.class);
328 apexModelWriter.setValidateFlag(false);
329 apexModelWriter.setJsonOutput(!xmlFlag);
331 // Open the URL for output and write the model
332 URLConnection urlConnection = apexModelUrl.openConnection();
333 urlConnection.setDoOutput(true);
335 apexModelWriter.write(apexModel.getPolicyModel(), urlConnection.getOutputStream());
336 return new ApexApiResult();
337 } catch (ApexModelException | IOException e) {
338 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
343 * Analyse an Apex model that shows the concept usage references of a policy model.
345 * @return the result of the operation
347 public ApexApiResult analyse() {
348 PolicyAnalysisResult analysisResult = new PolicyAnalyser().analyse(apexModel.getPolicyModel());
349 return new ApexApiResult(ApexApiResult.Result.SUCCESS, analysisResult.toString());
353 * Validate an Apex model, checking all concepts and references in the model.
355 * @return the result of the operation
357 public ApexApiResult validate() {
358 ApexApiResult result = new ApexApiResult();
360 AxValidationResult validationResult = apexModel.getPolicyModel().validate(new AxValidationResult());
362 if (!validationResult.isValid()) {
363 result.setResult(ApexApiResult.Result.FAILED);
365 result.addMessage(new ApexModelStringWriter<AxArtifactKey>(false)
366 .writeString(apexModel.getPolicyModel().getKey(), AxArtifactKey.class, jsonMode));
367 result.addMessage(validationResult.toString());
369 } catch (Exception e) {
370 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
375 * Compare to Apex models, returning the differences between the models.
377 * @param otherModelFileName the file name of the other model
378 * @param diffsOnly only returns differences between the model when set
379 * @param keysOnly only returns the keys that are different when set, when not set values are also returned
380 * @return the result of the operation
382 public ApexApiResult compare(final String otherModelFileName, final boolean diffsOnly, final boolean keysOnly) {
383 ApexApiResult result = new ApexApiResult();
385 AxPolicyModel otherPolicyModel = loadModelFromFile(otherModelFileName, result);
386 if (!result.getResult().equals(ApexApiResult.Result.SUCCESS)) {
390 PolicyModelComparer policyModelComparer =
391 new PolicyModelComparer(apexModel.getPolicyModel(), otherPolicyModel);
392 result.addMessage(new ApexModelStringWriter<AxArtifactKey>(false)
393 .writeString(apexModel.getPolicyModel().getKey(), AxArtifactKey.class, jsonMode));
394 result.addMessage(policyModelComparer.toString());
397 } catch (Exception e) {
398 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
403 * Compare two Apex models, returning the differences between the models.
405 * @param otherModelString the other model as a string
406 * @param diffsOnly only returns differences between the model when set
407 * @param keysOnly only returns the keys that are different when set, when not set values are also returned
408 * @return the result of the operation
410 public ApexApiResult compareWithString(final String otherModelString, final boolean diffsOnly,
411 final boolean keysOnly) {
412 ApexApiResult result = new ApexApiResult();
414 AxPolicyModel otherPolicyModel = loadModelFromString(otherModelString, result);
415 if (!result.getResult().equals(ApexApiResult.Result.SUCCESS)) {
419 PolicyModelComparer policyModelComparer =
420 new PolicyModelComparer(apexModel.getPolicyModel(), otherPolicyModel);
421 result.addMessage(new ApexModelStringWriter<AxArtifactKey>(false)
422 .writeString(apexModel.getPolicyModel().getKey(), AxArtifactKey.class, jsonMode));
423 result.addMessage(policyModelComparer.toString());
426 } catch (Exception e) {
427 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
432 * Split out a sub model from an Apex model that contains a given subset of the policies in the original model.
434 * @param targetModelName the file name of the target model in which to store the model split out from the original
436 * @param splitOutPolicies the policies form the original model to include in the split out model, specified as a
437 * comma delimited list of policy names
438 * @return the result of the operation
440 public ApexApiResult split(final String targetModelName, final String splitOutPolicies) {
441 Set<AxArtifactKey> requiredPolicySet = new LinkedHashSet<>();
443 // Split the policy names on comma
444 String[] policyNames = splitOutPolicies.split(",");
446 // Iterate over the policy names
447 for (String policyName : policyNames) {
448 // Split out this specific policy
449 AxPolicy requiredPolicy = apexModel.getPolicyModel().getPolicies().get(policyName);
451 if (requiredPolicy != null) {
452 requiredPolicySet.add(requiredPolicy.getKey());
454 return new ApexApiResult(ApexApiResult.Result.FAILED,
455 "policy for policy name " + policyName + " not found in model");
460 AxPolicyModel splitPolicyModel =
461 PolicyModelSplitter.getSubPolicyModel(apexModel.getPolicyModel(), requiredPolicySet, false);
463 ApexModelFileWriter<AxPolicyModel> apexModelFileWriter = new ApexModelFileWriter<>(false);
464 apexModelFileWriter.apexModelWriteJsonFile(splitPolicyModel, AxPolicyModel.class, targetModelName);
465 return new ApexApiResult();
466 } catch (ApexException e) {
467 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
472 * Split out a sub model from an Apex model that contains a given subset of the policies in the original model,
473 * return the split model in the result as a string.
475 * @param splitOutPolicies the policies form the original model to include in the split out model, specified as a
476 * comma delimited list of policy names
477 * @return the result of the operation
479 public ApexApiResult split(final String splitOutPolicies) {
480 ApexApiResult splitResult = new ApexApiResult();
481 File tempSplitPolicyFile = null;
483 tempSplitPolicyFile = File.createTempFile("ApexTempPolicy", null);
485 // Split the policy into a temporary file
486 splitResult = split(tempSplitPolicyFile.getCanonicalPath(), splitOutPolicies);
487 if (splitResult.isNok()) {
491 // Get the policy model into a string
492 String splitPolicyModelString = TextFileUtils.getTextFileAsString(tempSplitPolicyFile.getCanonicalPath());
494 // Return the policy model
495 splitResult.addMessage(splitPolicyModelString);
497 } catch (Exception e) {
498 return new ApexApiResult(ApexApiResult.Result.FAILED,
499 "split of policy model " + apexModel.getPolicyModel().getId() + " failed", e);
501 if (tempSplitPolicyFile != null) {
503 Files.delete(tempSplitPolicyFile.toPath());
504 } catch (IOException e) {
505 LOGGER.debug("delete of temporary file failed", e);
512 * Merge two Apex models together.
514 * @param mergeInModelName the file name of the model to merge into the current model
515 * @param keepOriginal if this flag is set to true, if a concept exists in both models, the original model copy of
516 * that concept is kept, if the flag is set to false, then the copy of the concept from the mergeInModel
517 * overwrites the concept in the original model
518 * @return the result of the operation
520 public ApexApiResult merge(final String mergeInModelName, final boolean keepOriginal) {
521 ApexApiResult result = new ApexApiResult();
522 AxPolicyModel mergeInPolicyModel = loadModelFromFile(mergeInModelName, result);
523 if (!result.getResult().equals(ApexApiResult.Result.SUCCESS)) {
528 AxPolicyModel mergedPolicyModel = PolicyModelMerger.getMergedPolicyModel(apexModel.getPolicyModel(),
529 mergeInPolicyModel, keepOriginal, false, false);
530 apexModel.setPolicyModel(mergedPolicyModel != null ? mergedPolicyModel : new AxPolicyModel());
531 return new ApexApiResult();
532 } catch (ApexModelException e) {
533 apexModel.setPolicyModel(new AxPolicyModel());
534 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
539 * Merge two Apex models together.
541 * @param otherModelString the model to merge as a string
542 * @param keepOriginal if this flag is set to true, if a concept exists in both models, the original model copy of
543 * that concept is kept, if the flag is set to false, then the copy of the concept from the mergeInModel
544 * overwrites the concept in the original model
545 * @return the result of the operation
547 public ApexApiResult mergeWithString(final String otherModelString, final boolean keepOriginal) {
548 ApexApiResult result = new ApexApiResult();
549 AxPolicyModel mergeInPolicyModel = loadModelFromString(otherModelString, result);
550 if (!result.getResult().equals(ApexApiResult.Result.SUCCESS)) {
555 AxPolicyModel mergedPolicyModel = PolicyModelMerger.getMergedPolicyModel(apexModel.getPolicyModel(),
556 mergeInPolicyModel, keepOriginal, false, false);
557 apexModel.setPolicyModel(mergedPolicyModel != null ? mergedPolicyModel : new AxPolicyModel());
558 return new ApexApiResult();
559 } catch (ApexModelException e) {
560 apexModel.setPolicyModel(new AxPolicyModel());
561 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
566 * Load a policy model from a file.
568 * @param fileName the name of the file containing the model
569 * @param result the result of the operation
572 private AxPolicyModel loadModelFromFile(final String fileName, final ApexApiResult result) {
573 Assertions.argumentNotNull(fileName, FILE_NAME_MAY_NOT_BE_NULL);
575 AxPolicyModel readModel = null;
577 final URL apexModelUrl = ResourceUtils.getLocalFile(fileName);
578 if (apexModelUrl == null) {
579 result.setResult(ApexApiResult.Result.FAILED);
580 result.addMessage("file " + fileName + " not found");
585 ApexModelReader<AxPolicyModel> apexModelReader = new ApexModelReader<>(AxPolicyModel.class);
586 apexModelReader.setValidateFlag(false);
587 readModel = apexModelReader.read(apexModelUrl.openStream());
588 result.setResult(ApexApiResult.Result.SUCCESS);
590 } catch (Exception e) {
591 result.setResult(ApexApiResult.Result.FAILED);
592 result.addThrowable(e);
598 * Load a policy model from a string.
600 * @param modelString the string containing the model
601 * @param result the result of the operation
604 private AxPolicyModel loadModelFromString(final String modelString, final ApexApiResult result) {
605 Assertions.argumentNotNull(modelString, "modelString may not be null");
607 AxPolicyModel readModel = null;
609 InputStream modelStringStream = new ByteArrayInputStream(modelString.getBytes());
612 ApexModelReader<AxPolicyModel> apexModelReader = new ApexModelReader<>(AxPolicyModel.class);
613 apexModelReader.setValidateFlag(false);
614 readModel = apexModelReader.read(modelStringStream);
615 result.setResult(ApexApiResult.Result.SUCCESS);
617 } catch (Exception e) {
618 result.setResult(ApexApiResult.Result.FAILED);
619 result.addThrowable(e);