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;
37 import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
38 import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException;
39 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
40 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult;
41 import org.onap.policy.apex.model.basicmodel.dao.ApexDao;
42 import org.onap.policy.apex.model.basicmodel.dao.ApexDaoFactory;
43 import org.onap.policy.apex.model.basicmodel.dao.DaoParameters;
44 import org.onap.policy.apex.model.basicmodel.handling.ApexModelException;
45 import org.onap.policy.apex.model.basicmodel.handling.ApexModelFileWriter;
46 import org.onap.policy.apex.model.basicmodel.handling.ApexModelReader;
47 import org.onap.policy.apex.model.basicmodel.handling.ApexModelStringWriter;
48 import org.onap.policy.apex.model.basicmodel.handling.ApexModelWriter;
49 import org.onap.policy.apex.model.modelapi.ApexApiResult;
50 import org.onap.policy.apex.model.modelapi.ApexModel;
51 import org.onap.policy.apex.model.policymodel.concepts.AxPolicy;
52 import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
53 import org.onap.policy.apex.model.policymodel.handling.PolicyAnalyser;
54 import org.onap.policy.apex.model.policymodel.handling.PolicyAnalysisResult;
55 import org.onap.policy.apex.model.policymodel.handling.PolicyModelComparer;
56 import org.onap.policy.apex.model.policymodel.handling.PolicyModelMerger;
57 import org.onap.policy.apex.model.policymodel.handling.PolicyModelSplitter;
58 import org.onap.policy.common.utils.resources.ResourceUtils;
59 import org.onap.policy.common.utils.resources.TextFileUtils;
60 import org.onap.policy.common.utils.validation.Assertions;
61 import org.slf4j.ext.XLogger;
62 import org.slf4j.ext.XLoggerFactory;
65 * This class acts as a facade for model handling for the Apex Model API.
67 * @author Liam Fallon (liam.fallon@ericsson.com)
69 public class ModelHandlerFacade {
70 private static final String FOUND_IN_DATABASE = " found in database";
71 private static final String FILE_NAME_MAY_NOT_BE_NULL = "fileName may not be null";
72 private static final String MODEL = "model ";
73 private static final String ALREADY_LOADED = " already loaded";
75 private static final XLogger LOGGER = XLoggerFactory.getXLogger(ModelHandlerFacade.class);
77 // Apex model we're working towards
78 private final ApexModel apexModel;
80 // JSON output on list/delete if set
81 private final boolean jsonMode;
84 * This Constructor creates a model handling facade for the given {@link ApexModel}.
86 * @param apexModel the apex model to manipulate
87 * @param apexProperties properties for the model
88 * @param jsonMode set to true to return JSON strings in list and delete operations, otherwise set to false
90 public ModelHandlerFacade(final ApexModel apexModel, final Properties apexProperties, final boolean jsonMode) {
91 Assertions.argumentNotNull(apexModel, "apexModel may not be null");
92 Assertions.argumentNotNull(apexProperties, "apexProperties may not be null");
94 this.apexModel = apexModel;
95 this.jsonMode = jsonMode;
99 * Load an Apex model from a string.
101 * @param modelString the string with the model
102 * @return the result of the operation
104 public ApexApiResult loadFromString(final String modelString) {
105 Assertions.argumentNotNull(modelString, "modelString may not be null");
107 if (!apexModel.getPolicyModel().getKey().equals(AxArtifactKey.getNullKey())) {
108 return new ApexApiResult(ApexApiResult.Result.CONCEPT_EXISTS,
109 MODEL + apexModel.getPolicyModel().getKey().getId() + ALREADY_LOADED);
112 ApexApiResult result = new ApexApiResult();
113 AxPolicyModel newPolicyModel = loadModelFromString(modelString, result);
114 apexModel.setPolicyModel(newPolicyModel != null ? newPolicyModel : new AxPolicyModel());
120 * Load an Apex model from a file.
122 * @param fileName the file name of the file with the model
123 * @return the result of the operation
125 public ApexApiResult loadFromFile(final String fileName) {
126 Assertions.argumentNotNull(fileName, FILE_NAME_MAY_NOT_BE_NULL);
128 if (!apexModel.getPolicyModel().getKey().equals(AxArtifactKey.getNullKey())) {
129 return new ApexApiResult(ApexApiResult.Result.CONCEPT_EXISTS,
130 MODEL + apexModel.getPolicyModel().getKey().getId() + ALREADY_LOADED);
133 ApexApiResult result = new ApexApiResult();
134 AxPolicyModel newPolicyModel = loadModelFromFile(fileName, result);
135 apexModel.setPolicyModel(newPolicyModel != null ? newPolicyModel : new AxPolicyModel());
141 * Save an Apex model to a file.
143 * @param fileName the file name
144 * @param xmlFlag if true, save the file in XML format, otherwise save the file in the default JSON format
145 * @return the result of the operation
147 public ApexApiResult saveToFile(final String fileName, final boolean xmlFlag) {
148 Assertions.argumentNotNull(fileName, FILE_NAME_MAY_NOT_BE_NULL);
150 ApexModelFileWriter<AxPolicyModel> apexModelFileWriter = new ApexModelFileWriter<>(false);
154 apexModelFileWriter.apexModelWriteXmlFile(apexModel.getPolicyModel(), AxPolicyModel.class, fileName);
156 apexModelFileWriter.apexModelWriteJsonFile(apexModel.getPolicyModel(), AxPolicyModel.class, fileName);
158 return new ApexApiResult();
159 } catch (ApexException e) {
160 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
165 * Load an Apex model from a database.
167 * @param modelName the name of the model to load
168 * @param modelVersion the version of the model to load, loads the policy model from the database with this name, if
169 * more than one exist, an exception is thrown
170 * @param daoParameters the parameters to use to access the database over JDBC
171 * @return the result of the operation
173 public ApexApiResult loadFromDatabase(final String modelName, final String modelVersion,
174 final DaoParameters daoParameters) {
175 Assertions.argumentNotNull(modelName, "modelName may not be null");
176 Assertions.argumentNotNull(daoParameters, "DaoParameters may not be null");
178 if (!apexModel.getPolicyModel().getKey().equals(AxArtifactKey.getNullKey())) {
179 return new ApexApiResult(ApexApiResult.Result.CONCEPT_EXISTS,
180 MODEL + apexModel.getPolicyModel().getKey().getId() + ALREADY_LOADED);
183 ApexDao apexDao = null;
185 apexDao = new ApexDaoFactory().createApexDao(daoParameters);
186 apexDao.init(daoParameters);
188 // Single specific model requested
189 if (modelVersion != null) {
190 AxPolicyModel daoPolicyModel =
191 apexDao.get(AxPolicyModel.class, new AxArtifactKey(modelName, modelVersion));
193 if (daoPolicyModel != null) {
194 apexModel.setPolicyModel(daoPolicyModel);
195 return new ApexApiResult();
197 apexModel.setPolicyModel(new AxPolicyModel());
198 return new ApexApiResult(ApexApiResult.Result.FAILED, "no policy model with name " + modelName
199 + " and version " + modelVersion + FOUND_IN_DATABASE);
202 // Fishing expedition
204 return searchInDatabase(modelName, apexDao, apexModel);
206 } catch (ApexException | ApexRuntimeException e) {
207 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
209 if (apexDao != null) {
216 * Search for an Apex model in the database.
218 * @param modelName the name of the model to load
219 * @param apexDao the DAO to use to find the model
220 * @param apexModel the APEX model we are loading the found model into
221 * @return the result of the operation
223 private ApexApiResult searchInDatabase(String modelName, ApexDao apexDao, ApexModel apexModel) {
224 AxPolicyModel foundPolicyModel = null;
226 List<AxPolicyModel> policyModelList = apexDao.getAll(AxPolicyModel.class);
227 for (AxPolicyModel dbPolicyModel : policyModelList) {
228 if (dbPolicyModel.getKey().getName().equals(modelName)) {
229 if (foundPolicyModel == null) {
230 foundPolicyModel = dbPolicyModel;
232 return new ApexApiResult(ApexApiResult.Result.FAILED,
233 "more than one policy model with name " + modelName + FOUND_IN_DATABASE);
238 if (foundPolicyModel != null) {
239 apexModel.setPolicyModel(foundPolicyModel);
240 return new ApexApiResult();
242 apexModel.setPolicyModel(new AxPolicyModel());
243 return new ApexApiResult(ApexApiResult.Result.FAILED,
244 "no policy model with name " + modelName + FOUND_IN_DATABASE);
249 * Save an Apex model to a database.
251 * @param daoParameters the parameters to use to access the database over JDBC
252 * @return the result of the operation
254 public ApexApiResult saveToDatabase(final DaoParameters daoParameters) {
255 ApexDao apexDao = null;
258 apexDao = new ApexDaoFactory().createApexDao(daoParameters);
259 apexDao.init(daoParameters);
261 apexDao.create(apexModel.getPolicyModel());
262 return new ApexApiResult();
263 } catch (ApexException e) {
264 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
266 if (apexDao != null) {
273 * Read an APEX model from a location identified by a URL.
275 * @param urlString the url string
276 * @return the result of the operation
278 public ApexApiResult readFromUrl(final String urlString) {
279 Assertions.argumentNotNull(urlString, "urlString may not be null");
281 if (!apexModel.getPolicyModel().getKey().equals(AxArtifactKey.getNullKey())) {
282 return new ApexApiResult(ApexApiResult.Result.CONCEPT_EXISTS,
283 MODEL + apexModel.getPolicyModel().getKey().getId() + ALREADY_LOADED);
288 apexModelUrl = new URL(urlString);
289 } catch (MalformedURLException e) {
290 ApexApiResult result = new ApexApiResult(ApexApiResult.Result.FAILED);
291 result.addMessage("URL string " + urlString + " is not a valid URL");
292 result.addThrowable(e);
297 ApexModelReader<AxPolicyModel> apexModelReader = new ApexModelReader<>(AxPolicyModel.class);
298 apexModelReader.setValidateFlag(false);
299 AxPolicyModel newPolicyModel = apexModelReader.read(apexModelUrl.openStream());
300 apexModel.setPolicyModel(newPolicyModel != null ? newPolicyModel : new AxPolicyModel());
301 return new ApexApiResult();
302 } catch (ApexModelException | IOException e) {
303 apexModel.setPolicyModel(new AxPolicyModel());
304 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
309 * Write an APEX model to a location identified by a URL.
311 * @param urlString the URL to read the model from
312 * @param xmlFlag if true, save the file in XML format, otherwise save the file in the default JSON format
313 * @return the result of the operation
315 public ApexApiResult writeToUrl(final String urlString, final boolean xmlFlag) {
316 Assertions.argumentNotNull(urlString, "urlString may not be null");
320 apexModelUrl = new URL(urlString);
321 } catch (MalformedURLException e) {
322 ApexApiResult result = new ApexApiResult(ApexApiResult.Result.FAILED);
323 result.addMessage("URL string " + urlString + " is not a valid URL");
324 result.addThrowable(e);
329 ApexModelWriter<AxPolicyModel> apexModelWriter = new ApexModelWriter<>(AxPolicyModel.class);
330 apexModelWriter.setValidateFlag(false);
331 apexModelWriter.setJsonOutput(!xmlFlag);
333 // Open the URL for output and write the model
334 URLConnection urlConnection = apexModelUrl.openConnection();
335 urlConnection.setDoOutput(true);
337 apexModelWriter.write(apexModel.getPolicyModel(), urlConnection.getOutputStream());
338 return new ApexApiResult();
339 } catch (ApexModelException | IOException e) {
340 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
345 * Analyse an Apex model that shows the concept usage references of a policy model.
347 * @return the result of the operation
349 public ApexApiResult analyse() {
350 PolicyAnalysisResult analysisResult = new PolicyAnalyser().analyse(apexModel.getPolicyModel());
351 return new ApexApiResult(ApexApiResult.Result.SUCCESS, analysisResult.toString());
355 * Validate an Apex model, checking all concepts and references in the model.
357 * @return the result of the operation
359 public ApexApiResult validate() {
360 ApexApiResult result = new ApexApiResult();
362 AxValidationResult validationResult = apexModel.getPolicyModel().validate(new AxValidationResult());
364 if (!validationResult.isValid()) {
365 result.setResult(ApexApiResult.Result.FAILED);
367 result.addMessage(new ApexModelStringWriter<AxArtifactKey>(false)
368 .writeString(apexModel.getPolicyModel().getKey(), AxArtifactKey.class, jsonMode));
369 result.addMessage(validationResult.toString());
371 } catch (Exception e) {
372 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
377 * Compare to Apex models, returning the differences between the models.
379 * @param otherModelFileName the file name of the other model
380 * @param diffsOnly only returns differences between the model when set
381 * @param keysOnly only returns the keys that are different when set, when not set values are also returned
382 * @return the result of the operation
384 public ApexApiResult compare(final String otherModelFileName, final boolean diffsOnly, final boolean keysOnly) {
385 ApexApiResult result = new ApexApiResult();
387 AxPolicyModel otherPolicyModel = loadModelFromFile(otherModelFileName, result);
388 if (!result.getResult().equals(ApexApiResult.Result.SUCCESS)) {
392 PolicyModelComparer policyModelComparer =
393 new PolicyModelComparer(apexModel.getPolicyModel(), otherPolicyModel);
394 result.addMessage(new ApexModelStringWriter<AxArtifactKey>(false)
395 .writeString(apexModel.getPolicyModel().getKey(), AxArtifactKey.class, jsonMode));
396 result.addMessage(policyModelComparer.toString());
399 } catch (Exception e) {
400 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
405 * Compare two Apex models, returning the differences between the models.
407 * @param otherModelString the other model as a string
408 * @param diffsOnly only returns differences between the model when set
409 * @param keysOnly only returns the keys that are different when set, when not set values are also returned
410 * @return the result of the operation
412 public ApexApiResult compareWithString(final String otherModelString, final boolean diffsOnly,
413 final boolean keysOnly) {
414 ApexApiResult result = new ApexApiResult();
416 AxPolicyModel otherPolicyModel = loadModelFromString(otherModelString, result);
417 if (!result.getResult().equals(ApexApiResult.Result.SUCCESS)) {
421 PolicyModelComparer policyModelComparer =
422 new PolicyModelComparer(apexModel.getPolicyModel(), otherPolicyModel);
423 result.addMessage(new ApexModelStringWriter<AxArtifactKey>(false)
424 .writeString(apexModel.getPolicyModel().getKey(), AxArtifactKey.class, jsonMode));
425 result.addMessage(policyModelComparer.toString());
428 } catch (Exception e) {
429 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
434 * Split out a sub model from an Apex model that contains a given subset of the policies in the original model.
436 * @param targetModelName the file name of the target model in which to store the model split out from the original
438 * @param splitOutPolicies the policies form the original model to include in the split out model, specified as a
439 * comma delimited list of policy names
440 * @return the result of the operation
442 public ApexApiResult split(final String targetModelName, final String splitOutPolicies) {
443 Set<AxArtifactKey> requiredPolicySet = new LinkedHashSet<>();
445 // Split the policy names on comma
446 String[] policyNames = splitOutPolicies.split(",");
448 // Iterate over the policy names
449 for (String policyName : policyNames) {
450 // Split out this specific policy
451 AxPolicy requiredPolicy = apexModel.getPolicyModel().getPolicies().get(policyName);
453 if (requiredPolicy != null) {
454 requiredPolicySet.add(requiredPolicy.getKey());
456 return new ApexApiResult(ApexApiResult.Result.FAILED,
457 "policy for policy name " + policyName + " not found in model");
462 AxPolicyModel splitPolicyModel =
463 PolicyModelSplitter.getSubPolicyModel(apexModel.getPolicyModel(), requiredPolicySet, false);
465 ApexModelFileWriter<AxPolicyModel> apexModelFileWriter = new ApexModelFileWriter<>(false);
466 apexModelFileWriter.apexModelWriteJsonFile(splitPolicyModel, AxPolicyModel.class, targetModelName);
467 return new ApexApiResult();
468 } catch (ApexException e) {
469 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
474 * Split out a sub model from an Apex model that contains a given subset of the policies in the original model,
475 * return the split model in the result as a string.
477 * @param splitOutPolicies the policies form the original model to include in the split out model, specified as a
478 * comma delimited list of policy names
479 * @return the result of the operation
481 public ApexApiResult split(final String splitOutPolicies) {
482 ApexApiResult splitResult = new ApexApiResult();
483 File tempSplitPolicyFile = null;
485 tempSplitPolicyFile = File.createTempFile("ApexTempPolicy", null);
487 // Split the policy into a temporary file
488 splitResult = split(tempSplitPolicyFile.getCanonicalPath(), splitOutPolicies);
489 if (splitResult.isNok()) {
493 // Get the policy model into a string
494 String splitPolicyModelString = TextFileUtils.getTextFileAsString(tempSplitPolicyFile.getCanonicalPath());
496 // Return the policy model
497 splitResult.addMessage(splitPolicyModelString);
499 } catch (Exception e) {
500 return new ApexApiResult(ApexApiResult.Result.FAILED,
501 "split of policy model " + apexModel.getPolicyModel().getId() + " failed", e);
503 if (tempSplitPolicyFile != null) {
505 Files.delete(tempSplitPolicyFile.toPath());
506 } catch (IOException e) {
507 LOGGER.debug("delete of temporary file failed", e);
514 * Merge two Apex models together.
516 * @param mergeInModelName the file name of the model to merge into the current model
517 * @param keepOriginal if this flag is set to true, if a concept exists in both models, the original model copy of
518 * that concept is kept, if the flag is set to false, then the copy of the concept from the mergeInModel
519 * overwrites the concept in the original model
520 * @return the result of the operation
522 public ApexApiResult merge(final String mergeInModelName, final boolean keepOriginal) {
523 ApexApiResult result = new ApexApiResult();
524 AxPolicyModel mergeInPolicyModel = loadModelFromFile(mergeInModelName, result);
525 if (!result.getResult().equals(ApexApiResult.Result.SUCCESS)) {
530 AxPolicyModel mergedPolicyModel = PolicyModelMerger.getMergedPolicyModel(apexModel.getPolicyModel(),
531 mergeInPolicyModel, keepOriginal, false, false);
532 apexModel.setPolicyModel(mergedPolicyModel != null ? mergedPolicyModel : new AxPolicyModel());
533 return new ApexApiResult();
534 } catch (ApexModelException e) {
535 apexModel.setPolicyModel(new AxPolicyModel());
536 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
541 * Merge two Apex models together.
543 * @param otherModelString the model to merge as a string
544 * @param keepOriginal if this flag is set to true, if a concept exists in both models, the original model copy of
545 * that concept is kept, if the flag is set to false, then the copy of the concept from the mergeInModel
546 * overwrites the concept in the original model
547 * @return the result of the operation
549 public ApexApiResult mergeWithString(final String otherModelString, final boolean keepOriginal) {
550 ApexApiResult result = new ApexApiResult();
551 AxPolicyModel mergeInPolicyModel = loadModelFromString(otherModelString, result);
552 if (!result.getResult().equals(ApexApiResult.Result.SUCCESS)) {
557 AxPolicyModel mergedPolicyModel = PolicyModelMerger.getMergedPolicyModel(apexModel.getPolicyModel(),
558 mergeInPolicyModel, keepOriginal, false, false);
559 apexModel.setPolicyModel(mergedPolicyModel != null ? mergedPolicyModel : new AxPolicyModel());
560 return new ApexApiResult();
561 } catch (ApexModelException e) {
562 apexModel.setPolicyModel(new AxPolicyModel());
563 return new ApexApiResult(ApexApiResult.Result.FAILED, e);
568 * Load a policy model from a file.
570 * @param fileName the name of the file containing the model
571 * @param result the result of the operation
574 private AxPolicyModel loadModelFromFile(final String fileName, final ApexApiResult result) {
575 Assertions.argumentNotNull(fileName, FILE_NAME_MAY_NOT_BE_NULL);
577 AxPolicyModel readModel = null;
579 final URL apexModelUrl = ResourceUtils.getLocalFile(fileName);
580 if (apexModelUrl == null) {
581 result.setResult(ApexApiResult.Result.FAILED);
582 result.addMessage("file " + fileName + " not found");
587 ApexModelReader<AxPolicyModel> apexModelReader = new ApexModelReader<>(AxPolicyModel.class);
588 apexModelReader.setValidateFlag(false);
589 readModel = apexModelReader.read(apexModelUrl.openStream());
590 result.setResult(ApexApiResult.Result.SUCCESS);
592 } catch (Exception e) {
593 result.setResult(ApexApiResult.Result.FAILED);
594 result.addThrowable(e);
600 * Load a policy model from a string.
602 * @param modelString the string containing the model
603 * @param result the result of the operation
606 private AxPolicyModel loadModelFromString(final String modelString, final ApexApiResult result) {
607 Assertions.argumentNotNull(modelString, "modelString may not be null");
609 AxPolicyModel readModel = null;
611 InputStream modelStringStream = new ByteArrayInputStream(modelString.getBytes());
614 ApexModelReader<AxPolicyModel> apexModelReader = new ApexModelReader<>(AxPolicyModel.class);
615 apexModelReader.setValidateFlag(false);
616 readModel = apexModelReader.read(modelStringStream);
617 result.setResult(ApexApiResult.Result.SUCCESS);
619 } catch (Exception e) {
620 result.setResult(ApexApiResult.Result.FAILED);
621 result.addThrowable(e);