From 82da1e9fa73e6a19455ea979bbf084aeed43af90 Mon Sep 17 00:00:00 2001 From: "a.sreekumar" Date: Wed, 16 Oct 2019 11:46:21 +0100 Subject: Resolve mapping between TOSCA policies and APEX policy models Change-Id: Ifaedc5074bcc51a5d495e342feae89b6a2aac1cf Issue-ID: POLICY-1626 Signed-off-by: a.sreekumar --- .../policymodel/handling/PolicyModelMerger.java | 179 ++++++++++++--------- 1 file changed, 102 insertions(+), 77 deletions(-) (limited to 'model/policy-model/src/main') diff --git a/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/handling/PolicyModelMerger.java b/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/handling/PolicyModelMerger.java index 28133cefa..37c3b2368 100644 --- a/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/handling/PolicyModelMerger.java +++ b/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/handling/PolicyModelMerger.java @@ -1,32 +1,38 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ package org.onap.policy.apex.model.policymodel.handling; -import java.util.Set; -import java.util.TreeSet; - +import java.util.Map; +import java.util.Map.Entry; import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; +import org.onap.policy.apex.model.basicmodel.concepts.AxKeyInfo; import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult; import org.onap.policy.apex.model.basicmodel.handling.ApexModelException; +import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum; +import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema; +import org.onap.policy.apex.model.eventmodel.concepts.AxEvent; +import org.onap.policy.apex.model.policymodel.concepts.AxPolicy; import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel; +import org.onap.policy.apex.model.policymodel.concepts.AxTask; import org.slf4j.ext.XLogger; import org.slf4j.ext.XLoggerFactory; @@ -42,7 +48,8 @@ public final class PolicyModelMerger { /** * Private constructor used to prevent sub class instantiation. */ - private PolicyModelMerger() {} + private PolicyModelMerger() { + } /** * Get a merged policy model with information from two policy models merged into a larger policy @@ -52,12 +59,14 @@ public final class PolicyModelMerger { * @param rightPolicyModel the policies to include in sub policy model * @param useLeftOnMatches if true, uses concepts from the left model if concepts with common * keys are found, if false it uses the concepts from the right model + * @param failOnDuplicateKeys whether to fail or not on the occurence of duplicate concept keys * @return the new Destination Model * @throws ApexModelException on model transfer errors */ public static AxPolicyModel getMergedPolicyModel(final AxPolicyModel leftPolicyModel, - final AxPolicyModel rightPolicyModel, final boolean useLeftOnMatches) throws ApexModelException { - return getMergedPolicyModel(leftPolicyModel, rightPolicyModel, useLeftOnMatches, false); + final AxPolicyModel rightPolicyModel, final boolean useLeftOnMatches, final boolean failOnDuplicateKeys) + throws ApexModelException { + return getMergedPolicyModel(leftPolicyModel, rightPolicyModel, useLeftOnMatches, false, failOnDuplicateKeys); } /** @@ -69,89 +78,105 @@ public final class PolicyModelMerger { * @param useLeftOnMatches if true, uses concepts from the left model if concepts with common * keys are found, if false it uses the concepts from the right model * @param ignoreInvalidSource Ignore errors on the source model, do the best you can + * @param failOnDuplicateKeys whether to fail or not on the occurence of duplicate concept keys * @return the new Destination Model * @throws ApexModelException on model transfer errors */ public static AxPolicyModel getMergedPolicyModel(final AxPolicyModel leftPolicyModel, - final AxPolicyModel rightPolicyModel, final boolean useLeftOnMatches, final boolean ignoreInvalidSource) - throws ApexModelException { - // Validate the left model - if (!ignoreInvalidSource) { - final AxValidationResult leftValidationResult = new AxValidationResult(); - leftPolicyModel.validate(leftValidationResult); - if (!leftValidationResult.isValid()) { - String message = "left model is invalid: " + leftValidationResult.toString(); - LOGGER.warn(message); - throw new ApexModelException(message); - } - } + final AxPolicyModel rightPolicyModel, final boolean useLeftOnMatches, final boolean ignoreInvalidSource, + final boolean failOnDuplicateKeys) throws ApexModelException { - // Validate the right model if (!ignoreInvalidSource) { - final AxValidationResult rightValidationResult = new AxValidationResult(); - rightPolicyModel.validate(rightValidationResult); - if (!rightValidationResult.isValid()) { - String message = "right model is invalid: " + rightValidationResult.toString(); - LOGGER.warn(message); - throw new ApexModelException(message); - } + validateModels(leftPolicyModel, "left"); + validateModels(rightPolicyModel, "right"); } // The new policy model uses the favoured copy side as its base - final AxPolicyModel mergedPolicyModel = (useLeftOnMatches ? new AxPolicyModel(leftPolicyModel) - : new AxPolicyModel(rightPolicyModel)); + final AxPolicyModel mergedPolicyModel = + (useLeftOnMatches ? new AxPolicyModel(leftPolicyModel) : new AxPolicyModel(rightPolicyModel)); // The Compared to policy model is the unfavoured side - final AxPolicyModel copyFromPolicyModel = (useLeftOnMatches ? rightPolicyModel : leftPolicyModel); - - //  Get the keys to copy over - final Set copyOverKeyInfoKeys = - new TreeSet<>(copyFromPolicyModel.getKeyInformation().getKeyInfoMap().keySet()); - final Set copyOverContextSchemaKeys = - new TreeSet<>(copyFromPolicyModel.getSchemas().getSchemasMap().keySet()); - final Set copyOverEventKeys = - new TreeSet<>(copyFromPolicyModel.getEvents().getEventMap().keySet()); - final Set copyOverContextAlbumKeys = - new TreeSet<>(copyFromPolicyModel.getAlbums().getAlbumsMap().keySet()); - final Set copyOverTaskKeys = new TreeSet<>(copyFromPolicyModel.getTasks().getTaskMap().keySet()); - final Set copyOverPolicyKeys = - new TreeSet<>(copyFromPolicyModel.getPolicies().getPolicyMap().keySet()); - - //  Remove keys that already exist - copyOverKeyInfoKeys.removeAll(mergedPolicyModel.getKeyInformation().getKeyInfoMap().keySet()); - copyOverContextSchemaKeys.removeAll(mergedPolicyModel.getSchemas().getSchemasMap().keySet()); - copyOverEventKeys.removeAll(mergedPolicyModel.getEvents().getEventMap().keySet()); - copyOverContextAlbumKeys.removeAll(mergedPolicyModel.getAlbums().getAlbumsMap().keySet()); - copyOverTaskKeys.removeAll(mergedPolicyModel.getTasks().getTaskMap().keySet()); - copyOverPolicyKeys.removeAll(mergedPolicyModel.getPolicies().getPolicyMap().keySet()); + final AxPolicyModel copyFromPolicyModel = + (useLeftOnMatches ? new AxPolicyModel(rightPolicyModel) : new AxPolicyModel(leftPolicyModel)); - // Now add all the concepts that must be copied over - for (final AxArtifactKey keyInfoKey : copyOverKeyInfoKeys) { - mergedPolicyModel.getKeyInformation().getKeyInfoMap().put(keyInfoKey, - copyFromPolicyModel.getKeyInformation().getKeyInfoMap().get(keyInfoKey)); - } - for (final AxArtifactKey contextSchemaKey : copyOverContextSchemaKeys) { - mergedPolicyModel.getSchemas().getSchemasMap().put(contextSchemaKey, - copyFromPolicyModel.getSchemas().getSchemasMap().get(contextSchemaKey)); - } - for (final AxArtifactKey eventKey : copyOverEventKeys) { - mergedPolicyModel.getEvents().getEventMap().put(eventKey, - copyFromPolicyModel.getEvents().getEventMap().get(eventKey)); - } - for (final AxArtifactKey contextAlbumKey : copyOverContextAlbumKeys) { - mergedPolicyModel.getAlbums().getAlbumsMap().put(contextAlbumKey, - copyFromPolicyModel.getAlbums().getAlbumsMap().get(contextAlbumKey)); - } - for (final AxArtifactKey taskKey : copyOverTaskKeys) { - mergedPolicyModel.getTasks().getTaskMap().put(taskKey, - copyFromPolicyModel.getTasks().getTaskMap().get(taskKey)); - } - for (final AxArtifactKey policyKey : copyOverPolicyKeys) { - mergedPolicyModel.getPolicies().getPolicyMap().put(policyKey, - copyFromPolicyModel.getPolicies().getPolicyMap().get(policyKey)); + Map mergedKeyInfoMap = mergedPolicyModel.getKeyInformation().getKeyInfoMap(); + Map mergedSchemasMap = mergedPolicyModel.getSchemas().getSchemasMap(); + Map mergedEventMap = mergedPolicyModel.getEvents().getEventMap(); + Map mergedAlbumsMap = mergedPolicyModel.getAlbums().getAlbumsMap(); + Map mergedTaskMap = mergedPolicyModel.getTasks().getTaskMap(); + Map mergedPolicyMap = mergedPolicyModel.getPolicies().getPolicyMap(); + + Map copyOverKeyInfoMap = copyFromPolicyModel.getKeyInformation().getKeyInfoMap(); + Map copyOverSchemasMap = copyFromPolicyModel.getSchemas().getSchemasMap(); + Map copyOverEventMap = copyFromPolicyModel.getEvents().getEventMap(); + Map copyOverAlbumsMap = copyFromPolicyModel.getAlbums().getAlbumsMap(); + Map copyOverTaskMap = copyFromPolicyModel.getTasks().getTaskMap(); + Map copyOverPolicyMap = copyFromPolicyModel.getPolicies().getPolicyMap(); + + if (failOnDuplicateKeys) { + StringBuilder errorMessage = new StringBuilder(); + checkForDuplicateContextItem(mergedSchemasMap, copyOverSchemasMap, errorMessage, "schema"); + checkForDuplicateItem(mergedEventMap, copyOverEventMap, errorMessage, "event"); + checkForDuplicateContextItem(mergedAlbumsMap, copyOverAlbumsMap, errorMessage, "album"); + checkForDuplicateItem(mergedTaskMap, copyOverTaskMap, errorMessage, "task"); + checkForDuplicateItem(mergedPolicyMap, copyOverPolicyMap, errorMessage, "policy"); + if (errorMessage.length() > 0) { + throw new ApexModelException(errorMessage.toString()); + } + } else { + //  Remove entries that already exist + copyOverKeyInfoMap.keySet().removeIf(mergedKeyInfoMap::containsKey); + copyOverSchemasMap.keySet().removeIf(mergedSchemasMap::containsKey); + copyOverEventMap.keySet().removeIf(mergedEventMap::containsKey); + copyOverAlbumsMap.keySet().removeIf(mergedAlbumsMap::containsKey); + copyOverTaskMap.keySet().removeIf(mergedTaskMap::containsKey); + copyOverPolicyMap.keySet().removeIf(mergedPolicyMap::containsKey); } + // Now add all the concepts that must be copied over + mergedKeyInfoMap.putAll(copyOverKeyInfoMap); + mergedSchemasMap.putAll(copyOverSchemasMap); + mergedEventMap.putAll(copyOverEventMap); + mergedAlbumsMap.putAll(copyOverAlbumsMap); + mergedTaskMap.putAll(copyOverTaskMap); + mergedPolicyMap.putAll(copyOverPolicyMap); // That's it, return the model return mergedPolicyModel; } + + private static void checkForDuplicateItem(Map mergedItemsMap, + Map copyOverItemsMap, StringBuilder errorMessage, String itemType) { + for (AxArtifactKey key : copyOverItemsMap.keySet()) { + if (mergedItemsMap.containsKey(key)) { + errorMessage.append("\n Duplicate " + itemType + " found - ").append(key.getId()); + } + } + } + + private static void checkForDuplicateContextItem(Map mergedItemsMap, + Map copyOverItemsMap, StringBuilder errorMessage, String itemType) { + for (Entry entry : copyOverItemsMap.entrySet()) { + V item = mergedItemsMap.get(entry.getKey()); + // same context schema name with different definitions cannot occur in multiple policies + if (null != item) { + if (item.equals(entry.getValue())) { + LOGGER.info("Same {} - {} is used by multiple policies.", itemType, entry.getKey().getId()); + } else { + errorMessage.append("\n Same " + itemType + " - ").append(entry.getKey().getId()) + .append(" with different definitions used in different policies"); + } + } + } + } + + private static void validateModels(AxPolicyModel policyModel, String position) throws ApexModelException { + // Validate the model + final AxValidationResult validationResult = new AxValidationResult(); + policyModel.validate(validationResult); + if (!validationResult.isValid()) { + String message = position + " model is invalid: " + validationResult.toString(); + LOGGER.warn(message); + throw new ApexModelException(message); + } + } } -- cgit 1.2.3-korg