Implement closest match algorithm 28/97928/10
authorPamela Dragosh <pdragosh@research.att.com>
Mon, 4 Nov 2019 21:18:08 +0000 (16:18 -0500)
committerPamela Dragosh <pdragosh@research.att.com>
Tue, 12 Nov 2019 23:48:04 +0000 (18:48 -0500)
Needed to add more obligations, which make it easier to
scan through obligations and be able to pull information
about the policy.

Adding weight as an obligation for Optimization policies in
order to implement "closest match" algorithm.

Moved Obligation to a support class.

Added JUnit code coverage on the translator classes.

Split some methods up to reduce complexity via sonar.

Issue-ID: POLICY-2066
Change-Id: Ibb13d2dc0a63ab2a6d585b0697a0c1d129fa8f7b
Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
15 files changed:
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/OnapObligation.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaDictionary.java
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdBaseTranslator.java
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslator.java
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java
applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/OnapObligationTest.java [new file with mode: 0644]
applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/TestUtilsCommon.java [new file with mode: 0644]
applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaDictionaryTest.java
applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdBaseTranslatorTest.java
applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslatorTest.java [new file with mode: 0644]
applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchablePolicyRequestTest.java
applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java
applications/common/src/test/resources/test.policy.bad.json [new file with mode: 0644]
applications/common/src/test/resources/test.policy.json [new file with mode: 0644]
applications/optimization/src/test/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplicationTest.java

diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/OnapObligation.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/OnapObligation.java
new file mode 100644 (file)
index 0000000..da2e7f1
--- /dev/null
@@ -0,0 +1,259 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.pdp.xacml.application.common;
+
+import com.att.research.xacml.api.AttributeAssignment;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Obligation;
+import com.google.gson.Gson;
+import java.util.Map;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.ToString;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType;
+
+@Getter
+@ToString
+public class OnapObligation {
+
+    @Getter(AccessLevel.NONE)
+    private static final ObjectFactory factory = new ObjectFactory();
+
+    @Getter(AccessLevel.NONE)
+    private static final Gson gson = new Gson();
+
+    private String policyId;
+    private String policyType;
+    private String policyContent;
+    private Integer weight;
+
+    /**
+     * Constructor from an obligation.
+     *
+     * @param obligation Obligation object
+     */
+    public OnapObligation(Obligation obligation) {
+        //
+        // Scan through the obligations for them
+        //
+        for (AttributeAssignment assignment : obligation.getAttributeAssignments()) {
+            scanAttribute(assignment);
+        }
+    }
+
+    /**
+     * Constructor for just the policy details.
+     *
+     * @param policyId String
+     * @param policyContent String
+     */
+    public OnapObligation(String policyId, String policyContent) {
+        this.policyId = policyId;
+        this.policyContent = policyContent;
+    }
+
+
+    /**
+     * Constructor for policy details, type and weight.
+     *
+     * @param policyId String
+     * @param policyContent String
+     * @param policyType String
+     * @param weight int
+     */
+    public OnapObligation(String policyId, String policyContent, String policyType, Integer weight) {
+        this.policyId = policyId;
+        this.policyContent = policyContent;
+        this.policyType = policyType;
+        this.weight = weight;
+    }
+
+    /**
+     * getPolicyContentAsMap returns the policy as a map for convience.
+     *
+     * @return {@code Map<String, Object>}
+     */
+    @SuppressWarnings("unchecked")
+    public Map<String, Object> getPolicyContentAsMap() {
+        if (this.policyContent == null) {
+            return null;
+        }
+        return gson.fromJson(this.policyContent, Map.class);
+    }
+
+    /**
+     * Generates default obligation using default Permit and Obligation Id.
+     *
+     * @return ObligationExpressionType object
+     */
+    public ObligationExpressionType generateObligation() {
+        return this.generateObligation(EffectType.PERMIT, ToscaDictionary.ID_OBLIGATION_REST_BODY);
+    }
+
+    /**
+     * generateObligation - generates an obligation object with the attributes that exist. Note:
+     * any null values will result in NO attribute assignment for that attribute.
+     *
+     * @param effectType EffectType object
+     * @param obligationId Id for the obligation
+     * @return ObligationExpressionType object
+     */
+    public ObligationExpressionType generateObligation(EffectType effectType, Identifier obligationId) {
+        //
+        // Create an ObligationExpression
+        //
+        ObligationExpressionType obligation = new ObligationExpressionType();
+        obligation.setFulfillOn(effectType);
+        obligation.setObligationId(obligationId.stringValue());
+        //
+        // Update the obligation
+        //
+        updateObligation(obligation);
+        //
+        // Convenience return
+        //
+        return obligation;
+    }
+
+    /**
+     * Updates an existing Obligation object with the attributes that exist. Note: any null values
+     * will result in NO attribute assignment for that attribute.
+     *
+     * @param obligation ObligationExpressionType object
+     * @return ObligationExpressionType object
+     */
+    public ObligationExpressionType updateObligation(ObligationExpressionType obligation) {
+        //
+        // Add policy-id
+        //
+        addOptionalAttributeToObligation(obligation, ToscaDictionary.ID_OBLIGATION_POLICY_ID,
+                ToscaDictionary.ID_OBLIGATION_POLICY_ID_DATATYPE,
+                ToscaDictionary.ID_OBLIGATION_POLICY_ID_CATEGORY,
+                policyId);
+        //
+        // Add policy contents
+        //
+        addOptionalAttributeToObligation(obligation, ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT,
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_DATATYPE,
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY,
+                policyContent);
+        //
+        // Add the weight
+        //
+        addOptionalAttributeToObligation(obligation, ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT,
+                ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT_DATATYPE,
+                ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT_CATEGORY,
+                weight);
+        //
+        // Add the policy type
+        //
+        addOptionalAttributeToObligation(obligation, ToscaDictionary.ID_OBLIGATION_POLICY_TYPE,
+                ToscaDictionary.ID_OBLIGATION_POLICY_TYPE_DATATYPE,
+                ToscaDictionary.ID_OBLIGATION_POLICY_TYPE_CATEGORY,
+                policyType);
+        //
+        // Return as a convenience
+        //
+        return obligation;
+    }
+
+    /**
+     * scanAttribute - scans the assignment for a supported obligation assignment. Applications
+     * can override this class and provide their own custom attribute assignments if desired.
+     *
+     * @param assignment AttributeAssignment object
+     * @return true if found an ONAP supported attribute
+     */
+    protected boolean scanAttribute(AttributeAssignment assignment) {
+        //
+        // Check for our supported attributes. Note: Cannot use a switch
+        // as Identifier isn't a constant.
+        //
+        if (ToscaDictionary.ID_OBLIGATION_POLICY_ID.equals(assignment.getAttributeId())) {
+            policyId = assignment.getAttributeValue().getValue().toString();
+            return true;
+        } else if (ToscaDictionary.ID_OBLIGATION_POLICY_TYPE.equals(assignment.getAttributeId())) {
+            policyType = assignment.getAttributeValue().getValue().toString();
+            return true;
+        } else if (ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.equals(assignment.getAttributeId())) {
+            policyContent = assignment.getAttributeValue().getValue().toString();
+            return true;
+        } else if (ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT.equals(assignment.getAttributeId())) {
+            weight = Integer.decode(assignment.getAttributeValue().getValue().toString());
+            return true;
+        }
+        //
+        // By returning true, we indicate this isn't an attribute
+        // supported in the this class. Targeted for applications
+        // that derive from this class in order to extend it.
+        //
+        return false;
+    }
+
+    /**
+     * Creates the necessary objects to insert into the obligation, if the value object is not null.
+     *
+     * @param obligation Incoming Obligation
+     * @param id Attribute Id
+     * @param datatype Attribute's Data type
+     * @param category Attributes Category
+     * @param theValue Attribute value
+     * @return obligation Incoming obligation
+     */
+    protected ObligationExpressionType addOptionalAttributeToObligation(ObligationExpressionType obligation,
+            Identifier id, Identifier datatype, Identifier category, Object theValue) {
+        //
+        // Simple check for null
+        //
+        if (theValue == null) {
+            return obligation;
+        }
+        //
+        // Create an AttributeValue for it
+        //
+        AttributeValueType value = new AttributeValueType();
+        value.setDataType(datatype.stringValue());
+        value.getContent().add(theValue.toString());
+        //
+        // Create our AttributeAssignmentExpression where we will
+        // store the contents of the policy id.
+        //
+        AttributeAssignmentExpressionType expressionType = new AttributeAssignmentExpressionType();
+        expressionType.setAttributeId(id.stringValue());
+        expressionType.setCategory(category.stringValue());
+        expressionType.setExpression(factory.createAttributeValue(value));
+        //
+        // Add it to the obligation
+        //
+        obligation.getAttributeAssignmentExpression().add(expressionType);
+        //
+        // Return as convenience
+        //
+        return obligation;
+    }
+
+}
index 500be2e..1a89997 100644 (file)
@@ -112,20 +112,41 @@ public final class ToscaDictionary {
     public static final Identifier ID_OBLIGATION_REST_BODY =
             new IdentifierImpl(ID_URN_ONAP, "rest:body");
 
-    public static final Identifier ID_OBLIGATION_POLICY_MONITORING =
-            new IdentifierImpl(ID_URN_ONAP, ":obligation:monitoring");
+    public static final Identifier ID_OBLIGATION_POLICY_CONTENT =
+            new IdentifierImpl(ID_URN_ONAP, ":obligation:policycontent");
 
-    public static final Identifier ID_OBLIGATION_POLICY_MONITORING_CONTENTS =
-            new IdentifierImpl(ID_URN_ONAP, ":obligation:monitoring:contents");
+    public static final Identifier ID_OBLIGATION_POLICY_CONTENT_CATEGORY =
+            XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE;
+
+    public static final Identifier ID_OBLIGATION_POLICY_CONTENT_DATATYPE =
+            XACML3.ID_DATATYPE_STRING;
 
-    public static final Identifier ID_OBLIGATION_POLICY_MONITORING_CATEGORY =
+    public static final Identifier ID_OBLIGATION_POLICY_ID =
+            new IdentifierImpl(ID_URN_ONAP, ":obligation:policyid");
+
+    public static final Identifier ID_OBLIGATION_POLICY_ID_CATEGORY =
             XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE;
 
-    public static final Identifier ID_OBLIGATION_POLICY_MONITORING_DATATYPE =
+    public static final Identifier ID_OBLIGATION_POLICY_ID_DATATYPE =
             XACML3.ID_DATATYPE_STRING;
 
-    public static final Identifier ID_OBLIGATION_MONITORING_ISSUER =
-            new IdentifierImpl(ID_URN_ONAP, "issuer:monitoring");
+    public static final Identifier ID_OBLIGATION_POLICY_WEIGHT =
+            new IdentifierImpl(ID_URN_ONAP, ":obligation:weight");
+
+    public static final Identifier ID_OBLIGATION_POLICY_WEIGHT_CATEGORY =
+            XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE;
+
+    public static final Identifier ID_OBLIGATION_POLICY_WEIGHT_DATATYPE =
+            XACML3.ID_DATATYPE_INTEGER;
+
+    public static final Identifier ID_OBLIGATION_POLICY_TYPE =
+            new IdentifierImpl(ID_URN_ONAP, ":obligation:policytype");
+
+    public static final Identifier ID_OBLIGATION_POLICY_TYPE_CATEGORY =
+            XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE;
+
+    public static final Identifier ID_OBLIGATION_POLICY_TYPE_DATATYPE =
+            XACML3.ID_DATATYPE_STRING;
 
 
 
index d2d383b..508bc24 100644 (file)
 
 package org.onap.policy.pdp.xacml.application.common.std;
 
-import com.att.research.xacml.api.AttributeAssignment;
 import com.att.research.xacml.api.Decision;
 import com.att.research.xacml.api.Obligation;
 import com.att.research.xacml.api.Request;
 import com.att.research.xacml.api.Response;
 import com.att.research.xacml.api.Result;
 import com.att.research.xacml.api.XACML3;
-import com.google.gson.Gson;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
-import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
-import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType;
@@ -50,6 +46,7 @@ import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
 import org.onap.policy.models.decisions.concepts.DecisionRequest;
 import org.onap.policy.models.decisions.concepts.DecisionResponse;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.pdp.xacml.application.common.OnapObligation;
 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
@@ -58,16 +55,16 @@ import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class StdBaseTranslator implements ToscaPolicyTranslator {
+public abstract class StdBaseTranslator implements ToscaPolicyTranslator {
     private static final Logger LOGGER = LoggerFactory.getLogger(StdBaseTranslator.class);
-    private static Gson gson = new Gson();
+    private static final ObjectFactory factory = new ObjectFactory();
 
     public static final String POLICY_ID = "policy-id";
     public static final String POLICY_VERSION = "policy-version";
 
     @Override
     public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
-        throw new ToscaPolicyConversionException("Please override converPolicy");
+        throw new ToscaPolicyConversionException("Please override convertPolicy");
     }
 
     @Override
@@ -95,8 +92,7 @@ public class StdBaseTranslator implements ToscaPolicyTranslator {
                 // Go through obligations
                 //
                 scanObligations(xacmlResult.getObligations(), decisionResponse);
-            } else if (xacmlResult.getDecision() == Decision.DENY
-                    || xacmlResult.getDecision() == Decision.INDETERMINATE) {
+            } else {
                 //
                 // TODO we have to return an ErrorResponse object instead
                 //
@@ -109,55 +105,13 @@ public class StdBaseTranslator implements ToscaPolicyTranslator {
 
     /**
      * scanObligations - scans the list of obligations and make appropriate method calls to process
-     * obligations.
+     * obligations. This method must be overridden and be implemented for the specific application as
+     * obligations may have different expected attributes per application.
      *
      * @param obligations Collection of obligation objects
      * @param decisionResponse DecisionResponse object used to store any results from obligations.
      */
-    protected void scanObligations(Collection<Obligation> obligations, DecisionResponse decisionResponse) {
-        for (Obligation obligation : obligations) {
-            LOGGER.info("Obligation: {}", obligation);
-            for (AttributeAssignment assignment : obligation.getAttributeAssignments()) {
-                LOGGER.info("Attribute Assignment: {}", assignment);
-                processObligationAttribute(assignment, decisionResponse);
-            }
-        }
-    }
-
-    /**
-     * processObligationAttribute - processes an individual obligation attribute assignment object.
-     *
-     * @param assignment AttributeAssignment object
-     * @param decisionResponse DecisionResponse object used to store any results from attribute assignment.
-     */
-    @SuppressWarnings("unchecked")
-    protected void processObligationAttribute(AttributeAssignment assignment, DecisionResponse decisionResponse) {
-        //
-        // We care about the content attribute
-        //
-        if (ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_CONTENTS
-                .equals(assignment.getAttributeId())) {
-            //
-            // The contents are in Json form
-            //
-            Object stringContents = assignment.getAttributeValue().getValue();
-            LOGGER.info("DCAE contents: {}{}", XacmlPolicyUtils.LINE_SEPARATOR, stringContents);
-            //
-            // Let's parse it into a map using Gson
-            //
-            Map<String, Object> result;
-            result = gson.fromJson(stringContents.toString(), Map.class);
-            //
-            // Find the metadata section
-            //
-            Map<String, Object> metadata = (Map<String, Object>) result.get("metadata");
-            if (metadata != null) {
-                decisionResponse.getPolicies().put(metadata.get(POLICY_ID).toString(), result);
-            } else {
-                LOGGER.error("Missing metadata section in policy contained in obligation.");
-            }
-        }
-    }
+    protected abstract void scanObligations(Collection<Obligation> obligations, DecisionResponse decisionResponse);
 
     /**
      * From the TOSCA metadata section, pull in values that are needed into the XACML policy.
@@ -196,36 +150,27 @@ public class StdBaseTranslator implements ToscaPolicyTranslator {
      * But this is fine for now.
      *
      * @param <T> RuleType, PolicyType, PolicySetType object
+     * @Param policyId The policy-id
      * @param ruleOrPolicy Incoming RuleType, PolicyType, PolicySetType object
      * @param jsonPolicy JSON String representation of policy.
+     * @param weight Weighting for the policy (optional)
      * @return Return the Incoming RuleType, PolicyType, PolicySetType object for convenience.
      */
-    protected <T> T addObligation(T ruleOrPolicy, String jsonPolicy) {
+    protected <T> T addObligation(T ruleOrPolicy, String policyId, String jsonPolicy, Integer weight,
+            String policyType) {
         //
         // Creating obligation for returning policy
         //
-        LOGGER.info("Obligation Policy {}{}", XacmlPolicyUtils.LINE_SEPARATOR, jsonPolicy);
-        //
-        // Create an AttributeValue for it
-        //
-        AttributeValueType value = new AttributeValueType();
-        value.setDataType(ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_DATATYPE.stringValue());
-        value.getContent().add(jsonPolicy);
+        LOGGER.info("Obligation Policy id: {} type: {} weight: {} policy:{}{}", policyId, policyType, weight,
+                XacmlPolicyUtils.LINE_SEPARATOR, jsonPolicy);
         //
-        // Create our AttributeAssignmentExpression where we will
-        // store the contents of the policy in JSON format.
+        // Create our OnapObligation
         //
-        AttributeAssignmentExpressionType expressionType = new AttributeAssignmentExpressionType();
-        expressionType.setAttributeId(ToscaDictionary.ID_OBLIGATION_POLICY_MONITORING_CONTENTS.stringValue());
-        ObjectFactory factory = new ObjectFactory();
-        expressionType.setExpression(factory.createAttributeValue(value));
+        OnapObligation onapObligation = new OnapObligation(policyId, jsonPolicy, policyType, weight);
         //
-        // Create an ObligationExpression for it
+        // Generate the obligation
         //
-        ObligationExpressionType obligation = new ObligationExpressionType();
-        obligation.setFulfillOn(EffectType.PERMIT);
-        obligation.setObligationId(ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue());
-        obligation.getAttributeAssignmentExpression().add(expressionType);
+        ObligationExpressionType obligation = onapObligation.generateObligation();
         //
         // Now we can add it into the rule/policy/policyset
         //
@@ -237,6 +182,8 @@ public class StdBaseTranslator implements ToscaPolicyTranslator {
             ((PolicyType) ruleOrPolicy).setObligationExpressions(obligations);
         } else if (ruleOrPolicy instanceof PolicySetType) {
             ((PolicySetType) ruleOrPolicy).setObligationExpressions(obligations);
+        } else {
+            LOGGER.error("Unsupported class for adding obligation {}", ruleOrPolicy.getClass());
         }
         //
         // Return as a convenience
@@ -300,7 +247,6 @@ public class StdBaseTranslator implements ToscaPolicyTranslator {
         valueZero.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
         valueZero.getContent().add("0");    // Yes really - represent as a string
 
-        ObjectFactory factory = new ObjectFactory();
         applyBagSize.getExpression().add(factory.createAttributeDesignator(designator));
 
         ApplyType applyGreaterThan = new ApplyType();
index be0a507..bcd594f 100644 (file)
 package org.onap.policy.pdp.xacml.application.common.std;
 
 import com.att.research.xacml.api.DataTypeException;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Obligation;
 import com.att.research.xacml.api.Request;
 import com.att.research.xacml.api.XACML3;
 import com.att.research.xacml.std.annotations.RequestParser;
+import com.google.common.base.Strings;
+import java.util.Collection;
+import java.util.Map;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
@@ -35,7 +40,9 @@ import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.coder.StandardCoder;
 import org.onap.policy.models.decisions.concepts.DecisionRequest;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.pdp.xacml.application.common.OnapObligation;
 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
@@ -52,11 +59,24 @@ public class StdCombinedPolicyResultsTranslator extends StdBaseTranslator {
 
     @Override
     public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
+        //
+        // Sanity checks
+        //
+        if (toscaPolicy == null) {
+            throw new ToscaPolicyConversionException("Cannot convert a NULL policy");
+        }
+        if (toscaPolicy.getMetadata() == null) {
+            throw new ToscaPolicyConversionException("Cannot convert a policy with missing metadata section");
+        }
+        //
+        // Get the policy Id
+        //
+        String policyId = toscaPolicy.getMetadata().get(POLICY_ID);
         //
         // Set it as the policy ID
         //
         PolicyType newPolicyType = new PolicyType();
-        newPolicyType.setPolicyId(toscaPolicy.getMetadata().get(POLICY_ID));
+        newPolicyType.setPolicyId(policyId);
         //
         // Optional description
         //
@@ -72,8 +92,7 @@ public class StdCombinedPolicyResultsTranslator extends StdBaseTranslator {
         //
         // Generate the TargetType
         //
-        TargetType target = this.generateTargetType(toscaPolicy.getMetadata().get(POLICY_ID),
-                toscaPolicy.getType(), toscaPolicy.getVersion());
+        TargetType target = this.generateTargetType(policyId, toscaPolicy.getType(), toscaPolicy.getVersion());
         newPolicyType.setTarget(target);
         //
         // Now create the Permit Rule
@@ -82,7 +101,7 @@ public class StdCombinedPolicyResultsTranslator extends StdBaseTranslator {
         //
         RuleType rule = new RuleType();
         rule.setDescription("Default is to PERMIT if the policy matches.");
-        rule.setRuleId(toscaPolicy.getMetadata().get(POLICY_ID) + ":rule");
+        rule.setRuleId(policyId + ":rule");
         rule.setEffect(EffectType.PERMIT);
         rule.setTarget(new TargetType());
         //
@@ -95,7 +114,7 @@ public class StdCombinedPolicyResultsTranslator extends StdBaseTranslator {
         } catch (CoderException e) {
             throw new ToscaPolicyConversionException(e);
         }
-        addObligation(rule, jsonPolicy);
+        addObligation(rule, policyId, jsonPolicy, null, toscaPolicy.getType());
         //
         // Add the rule to the policy
         //
@@ -120,6 +139,60 @@ public class StdCombinedPolicyResultsTranslator extends StdBaseTranslator {
         return null;
     }
 
+    /**
+     * scanObligations - scans the list of obligations and make appropriate method calls to process
+     * obligations.
+     *
+     * @param obligations Collection of obligation objects
+     * @param decisionResponse DecisionResponse object used to store any results from obligations.
+     */
+    @Override
+    protected void scanObligations(Collection<Obligation> obligations, DecisionResponse decisionResponse) {
+        for (Obligation obligation : obligations) {
+            Identifier obligationId = obligation.getId();
+            LOGGER.info("Obligation: {}", obligationId);
+            if (ToscaDictionary.ID_OBLIGATION_REST_BODY.equals(obligationId)) {
+                scanContentObligation(obligation, decisionResponse);
+            }
+        }
+    }
+
+    /**
+     * scanContentObligation - scans the specific obligation for policy-id and policy-content.
+     *
+     * @param obligation Obligation incoming obligation object
+     * @param decisionResponse DecisionResponse object
+     */
+    protected void scanContentObligation(Obligation obligation, DecisionResponse decisionResponse) {
+        //
+        // Create our OnapObligation which will scan for attributes
+        //
+        OnapObligation onapObligation = new OnapObligation(obligation);
+        //
+        // Get the attributes we care about
+        //
+        String policyId = onapObligation.getPolicyId();
+        Map<String, Object> policyContent = onapObligation.getPolicyContentAsMap();
+        //
+        // Sanity check that we got the attributes we care about. NOTE: This translator
+        // ensures that these are set when convertPolicy is called.
+        //
+        if (! Strings.isNullOrEmpty(policyId) && policyContent != null) {
+            decisionResponse.getPolicies().put(policyId, policyContent);
+        } else {
+            LOGGER.error("Missing obligation policyId {} or policyContent {}", policyId,
+                    policyContent == null ? "null" : policyContent.size());
+        }
+    }
+
+    /**
+     * generateTargetType - Generates a TargetType object for the policy-id and policy-type.
+     *
+     * @param policyId String policy-id
+     * @param policyType String policy type
+     * @param policyTypeVersion String policy type version
+     * @return TargetType object
+     */
     protected TargetType generateTargetType(String policyId, String policyType, String policyTypeVersion) {
         //
         // Create all the match's that are possible
index 66770e9..addb0df 100644 (file)
@@ -23,6 +23,7 @@
 package org.onap.policy.pdp.xacml.application.common.std;
 
 import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Obligation;
 import com.att.research.xacml.api.Request;
 import com.att.research.xacml.api.XACML3;
 import com.att.research.xacml.std.IdentifierImpl;
@@ -38,6 +39,8 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -48,17 +51,20 @@ import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
+import org.apache.commons.lang3.tuple.Pair;
 import org.onap.policy.common.endpoints.parameters.RestServerParameters;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.coder.StandardCoder;
 import org.onap.policy.common.utils.coder.StandardYamlCoder;
 import org.onap.policy.models.decisions.concepts.DecisionRequest;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
+import org.onap.policy.pdp.xacml.application.common.OnapObligation;
 import org.onap.policy.pdp.xacml.application.common.PolicyApiCaller;
 import org.onap.policy.pdp.xacml.application.common.PolicyApiException;
 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
@@ -104,6 +110,127 @@ public class StdMatchableTranslator  extends StdBaseTranslator {
         return null;
     }
 
+    /**
+     * scanObligations - scans the list of obligations and make appropriate method calls to process
+     * obligations.
+     *
+     * @param obligations Collection of obligation objects
+     * @param decisionResponse DecisionResponse object used to store any results from obligations.
+     */
+    @Override
+    protected void scanObligations(Collection<Obligation> obligations, DecisionResponse decisionResponse) {
+        //
+        // Implementing a crude "closest match" on the results, which means we will strip out
+        // any policies that has the lower weight than any of the others.
+        //
+        // Most likely these are "default" policies with a weight of zero, but not always.
+        //
+        // It is possible to have multiple policies with an equal weight, that is desired.
+        //
+        // So we need to track each policy type separately and the weights for each policy.
+        //
+        // policy-type -> weight -> List({policy-id, policy-content}, {policy-id, policy-content})
+        //
+        Map<String, Map<Integer, List<Pair<String, Map<String, Object>>>>> closestMatches = new LinkedHashMap<>();
+        //
+        // Now scan the list of obligations
+        //
+        for (Obligation obligation : obligations) {
+            Identifier obligationId = obligation.getId();
+            LOGGER.info("Obligation: {}", obligationId);
+            if (ToscaDictionary.ID_OBLIGATION_REST_BODY.equals(obligationId)) {
+                scanClosestMatchObligation(closestMatches, obligation);
+            } else {
+                LOGGER.warn("Unsupported Obligation Id {}", obligation.getId());
+            }
+        }
+        //
+        // Now add all the policies to the DecisionResponse
+        //
+        closestMatches.forEach((thePolicyType, weightMap) ->
+            weightMap.forEach((weight, policies) ->
+                policies.forEach(policy -> {
+                    LOGGER.info("Policy {}", policy);
+                    decisionResponse.getPolicies().put(policy.getLeft(), policy.getRight());
+                })
+            )
+        );
+    }
+
+    /**
+     * scanClosestMatchObligation - scans for the obligation specifically holding policy
+     * contents and their details.
+     *
+     * @param closestMatches Map holding the current set of highest weight policy types
+     * @param Obligation Obligation object
+     */
+    protected void scanClosestMatchObligation(
+            Map<String, Map<Integer, List<Pair<String, Map<String, Object>>>>> closestMatches, Obligation obligation) {
+        //
+        // Create our OnapObligation object
+        //
+        OnapObligation onapObligation = new OnapObligation(obligation);
+        //
+        // All 4 *should* be there
+        //
+        if (onapObligation.getPolicyId() == null || onapObligation.getPolicyContent() == null
+                || onapObligation.getPolicyType() == null || onapObligation.getWeight() == null) {
+            LOGGER.error("Missing an expected attribute in obligation.");
+            return;
+        }
+        //
+        // Save the values
+        //
+        String policyId = onapObligation.getPolicyId();
+        String policyType = onapObligation.getPolicyType();
+        Map<String, Object> policyContent = onapObligation.getPolicyContentAsMap();
+        int policyWeight = onapObligation.getWeight();
+        //
+        // If the Policy Type exists, get the weight map.
+        //
+        Map<Integer, List<Pair<String, Map<String, Object>>>> weightMap = closestMatches.get(policyType);
+        if (weightMap != null) {
+            //
+            // Only need to check first one - as we will ensure there is only one weight
+            //
+            Entry<Integer, List<Pair<String, Map<String, Object>>>> firstEntry =
+                    weightMap.entrySet().iterator().next();
+            if (policyWeight < firstEntry.getKey()) {
+                //
+                // Existing policies have a greater weight, so we will not add it
+                //
+                LOGGER.info("{} is lesser weight {} than current policies, will not return it", policyWeight,
+                        firstEntry.getKey());
+            } else if (firstEntry.getKey().equals(policyWeight)) {
+                //
+                // Same weight - we will add it
+                //
+                LOGGER.info("Same weight {}, adding policy", policyWeight);
+                firstEntry.getValue().add(Pair.of(policyId, policyContent));
+            } else {
+                //
+                // The weight is greater, so we need to remove the other policies
+                // and point to this one.
+                //
+                LOGGER.info("New policy has greater weight {}, replacing {}", policyWeight, firstEntry.getKey());
+                List<Pair<String, Map<String, Object>>> listPolicies = new LinkedList<>();
+                listPolicies.add(Pair.of(policyId, policyContent));
+                weightMap.clear();
+                weightMap.put(policyWeight, listPolicies);
+            }
+        } else {
+            //
+            // Create a new entry
+            //
+            LOGGER.info("New entry {} weight {}", policyType, policyWeight);
+            List<Pair<String, Map<String, Object>>> listPolicies = new LinkedList<>();
+            listPolicies.add(Pair.of(policyId, policyContent));
+            Map<Integer, List<Pair<String, Map<String, Object>>>> newWeightMap = new LinkedHashMap<>();
+            newWeightMap.put(policyWeight, listPolicies);
+            closestMatches.put(policyType, newWeightMap);
+        }
+    }
+
     @Override
     public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
         //
@@ -143,7 +270,8 @@ public class StdMatchableTranslator  extends StdBaseTranslator {
         // Generate the TargetType - the policy should not be evaluated
         // unless all the matchable properties it cares about are matched.
         //
-        newPolicyType.setTarget(generateTargetType(toscaPolicy.getProperties(), toscaPolicyTypes));
+        Pair<TargetType, Integer> pairGenerated = generateTargetType(toscaPolicy.getProperties(), toscaPolicyTypes);
+        newPolicyType.setTarget(pairGenerated.getLeft());
         //
         // Now represent the policy as Json
         //
@@ -157,7 +285,7 @@ public class StdMatchableTranslator  extends StdBaseTranslator {
         //
         // Add it as an obligation
         //
-        addObligation(newPolicyType, jsonPolicy);
+        addObligation(newPolicyType, policyName, jsonPolicy, pairGenerated.getRight(), toscaPolicy.getType());
         //
         // Now create the Permit Rule.
         //
@@ -196,24 +324,28 @@ public class StdMatchableTranslator  extends StdBaseTranslator {
      *
      * @param properties Properties section of policy
      * @param policyTypes Collection of policy Type to find matchable metadata
-     * @return TargetType object
+     * @return {@code Pair<TargetType, Integer>} Returns a TargetType and a Total Weight of matchables.
      */
-    protected TargetType generateTargetType(Map<String, Object> properties, Collection<ToscaPolicyType> policyTypes) {
+    protected Pair<TargetType, Integer> generateTargetType(Map<String, Object> properties,
+            Collection<ToscaPolicyType> policyTypes) {
         TargetType targetType = new TargetType();
         //
         // Iterate the properties
         //
+        int totalWeight = 0;
         for (Entry<String, Object> entrySet : properties.entrySet()) {
             //
             // Find matchable properties
             //
             if (isMatchable(entrySet.getKey(), policyTypes)) {
                 LOGGER.info("Found matchable property {}", entrySet.getKey());
-                generateMatchable(targetType, entrySet.getKey(), entrySet.getValue());
+                int weight = generateMatchable(targetType, entrySet.getKey(), entrySet.getValue());
+                LOGGER.info("Weight is {}", weight);
+                totalWeight += weight;
             }
         }
-
-        return targetType;
+        LOGGER.info("Total weight is {}", totalWeight);
+        return Pair.of(targetType, totalWeight);
     }
 
     /**
@@ -259,29 +391,33 @@ public class StdMatchableTranslator  extends StdBaseTranslator {
 
     /**
      * generateMatchable - Given the object, generates list of MatchType objects and add them
-     * to the TargetType object.
+     * to the TargetType object. Returns a weight which is the number of AnyOf's generated. The
+     * weight can be used to further filter the results for "closest match".
      *
      * @param targetType TargetType object to add matches to
      * @param key Property key
      * @param value Object is the value - which can be a Collection or single Object
-     * @return TargetType incoming TargetType returned as a convenience
+     * @return int Weight of the match.
      */
     @SuppressWarnings("unchecked")
-    protected TargetType generateMatchable(TargetType targetType, String key, Object value) {
+    protected int generateMatchable(TargetType targetType, String key, Object value) {
+        int weight = 0;
         if (value instanceof Collection) {
             AnyOfType anyOf = generateMatches((Collection<Object>) value,
                     new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key));
             if (! anyOf.getAllOf().isEmpty()) {
                 targetType.getAnyOf().add(anyOf);
+                weight = 1;
             }
         } else {
             AnyOfType anyOf = generateMatches(Arrays.asList(value),
                     new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key));
             if (! anyOf.getAllOf().isEmpty()) {
                 targetType.getAnyOf().add(anyOf);
+                weight = 1;
             }
         }
-        return targetType;
+        return weight;
     }
 
     /**
diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/OnapObligationTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/OnapObligationTest.java
new file mode 100644 (file)
index 0000000..c02d7fb
--- /dev/null
@@ -0,0 +1,144 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.pdp.xacml.application.common;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertNotNull;
+
+import com.att.research.xacml.api.AttributeAssignment;
+import com.att.research.xacml.api.Obligation;
+import com.att.research.xacml.api.XACML3;
+import java.util.Arrays;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+
+public class OnapObligationTest {
+
+    String policyJson;
+    String policyBadJson;
+
+    AttributeAssignment assignmentPolicyId;
+    AttributeAssignment assignmentPolicy;
+    AttributeAssignment assignmentBadPolicy;
+    AttributeAssignment assignmentWeight;
+    AttributeAssignment assignmentPolicyType;
+    AttributeAssignment assignmentUnknown;
+
+    Obligation obligation;
+
+    /**
+     * setup - create test data.
+     */
+    @Before
+    public void setup() {
+        policyJson = ResourceUtils.getResourceAsString("test.policy.json");
+        policyBadJson = ResourceUtils.getResourceAsString("test.policy.bad.json");
+
+        assignmentPolicyId = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_ID.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_ID_CATEGORY.stringValue(),
+                policyJson
+                );
+
+        assignmentPolicy = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY.stringValue(),
+                policyJson
+                );
+
+        assignmentBadPolicy = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY.stringValue(),
+                policyBadJson
+                );
+
+        assignmentWeight = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT_CATEGORY.stringValue(),
+                0
+                );
+
+        assignmentPolicyType = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_TYPE.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_TYPE_CATEGORY.stringValue(),
+                "onap.policies.Test"
+                );
+
+        assignmentUnknown = TestUtilsCommon.createAttributeAssignment(
+                "foo:bar",
+                XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue(),
+                10.2
+                );
+
+        obligation = TestUtilsCommon.createXacmlObligation(
+                ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue(),
+                Arrays.asList(assignmentPolicyId, assignmentPolicy, assignmentWeight, assignmentPolicyType,
+                        assignmentUnknown));
+    }
+
+    @Test
+    public void testObligation() {
+        OnapObligation onapObligation = new OnapObligation(obligation);
+        assertNotNull(onapObligation);
+        assertThat(onapObligation.getPolicyId()).isEqualTo(assignmentPolicyId.getAttributeValue().getValue());
+        assertThat(onapObligation.getPolicyType()).isEqualTo(assignmentPolicyType.getAttributeValue().getValue());
+        assertThat(onapObligation.getPolicyContent()).isEqualTo(assignmentPolicy.getAttributeValue().getValue());
+        assertThat(onapObligation.getWeight()).isEqualTo(assignmentWeight.getAttributeValue().getValue());
+    }
+
+    @Test
+    public void testSimplePolicy() {
+        OnapObligation onapObligation = new OnapObligation("my.policy.id", policyJson);
+        assertNotNull(onapObligation);
+        assertThat(onapObligation.getPolicyId()).isEqualTo("my.policy.id");
+        assertThat(onapObligation.getPolicyContent()).isEqualTo(policyJson);
+        assertThat(onapObligation.getPolicyType()).isNull();
+        assertThat(onapObligation.getWeight()).isNull();
+        //
+        // Create an obligation from it
+        //
+        ObligationExpressionType newObligation = onapObligation.generateObligation();
+        assertNotNull(newObligation);
+        assertThat(newObligation.getAttributeAssignmentExpression()).hasSize(2);
+    }
+
+
+    @Test
+    public void testWeightedPolicy() {
+        OnapObligation onapObligation = new OnapObligation("my.policy.id", policyJson, "onap.policies.Test", 5);
+        assertNotNull(onapObligation);
+        assertThat(onapObligation.getPolicyId()).isEqualTo("my.policy.id");
+        assertThat(onapObligation.getPolicyContent()).isEqualTo(policyJson);
+        assertThat(onapObligation.getPolicyType()).isEqualTo("onap.policies.Test");
+        assertThat(onapObligation.getWeight()).isEqualTo(5);
+        //
+        // Create an obligation from it
+        //
+        ObligationExpressionType newObligation = onapObligation.generateObligation();
+        assertNotNull(newObligation);
+        assertThat(newObligation.getAttributeAssignmentExpression()).hasSize(4);
+    }
+
+}
diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/TestUtilsCommon.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/TestUtilsCommon.java
new file mode 100644 (file)
index 0000000..ab5dde2
--- /dev/null
@@ -0,0 +1,126 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.pdp.xacml.application.common;
+
+import com.att.research.xacml.api.AttributeAssignment;
+import com.att.research.xacml.api.Decision;
+import com.att.research.xacml.api.IdReference;
+import com.att.research.xacml.api.Obligation;
+import com.att.research.xacml.api.Response;
+import com.att.research.xacml.api.StatusCode;
+import com.att.research.xacml.api.XACML3;
+import com.att.research.xacml.std.IdentifierImpl;
+import com.att.research.xacml.std.StdAttributeAssignment;
+import com.att.research.xacml.std.StdAttributeValue;
+import com.att.research.xacml.std.StdIdReference;
+import com.att.research.xacml.std.StdMutableObligation;
+import com.att.research.xacml.std.StdMutableResponse;
+import com.att.research.xacml.std.StdMutableResult;
+import com.att.research.xacml.std.StdStatus;
+import com.att.research.xacml.std.StdVersion;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class TestUtilsCommon {
+
+    /**
+     * createAttributeAssignment.
+     *
+     * @param <T> Object can be String, Integer, Double, Boolean
+     * @param id String attribute id
+     * @param category String for the attribute category
+     * @param value Object containing a value
+     * @return AttributeAssignment object
+     */
+    public static <T> AttributeAssignment createAttributeAssignment(String id, String category, T value) {
+        StdAttributeValue<T> attributeValue = null;
+        if (value instanceof String) {
+            attributeValue = new StdAttributeValue<>(XACML3.ID_DATATYPE_STRING, value);
+        } else if (value instanceof Integer) {
+            attributeValue = new StdAttributeValue<>(XACML3.ID_DATATYPE_INTEGER, value);
+        } else if (value instanceof Double) {
+            attributeValue = new StdAttributeValue<>(XACML3.ID_DATATYPE_DOUBLE, value);
+        } else if (value instanceof Boolean) {
+            attributeValue = new StdAttributeValue<>(XACML3.ID_DATATYPE_BOOLEAN, value);
+        } else {
+            throw new IllegalArgumentException("Unsupported value object " + value.getClass());
+        }
+
+        return new StdAttributeAssignment(new IdentifierImpl(category),
+                new IdentifierImpl(id), "", attributeValue);
+    }
+
+    /**
+     * createXacmlObligation.
+     *
+     * @param id String obligation id
+     * @param attributeAssignments Collection of AttributeAssignment objects
+     * @return Obligation object
+     */
+    public static Obligation createXacmlObligation(String id, Collection<AttributeAssignment> attributeAssignments) {
+        return new StdMutableObligation(new IdentifierImpl(id), attributeAssignments);
+    }
+
+    /**
+     * createPolicyIdList.
+     *
+     * @param ids Map of policy Ids
+     * @return {@code Collection<IdReference>} objects
+     * @throws ParseException ParseException
+     */
+    public static Collection<IdReference> createPolicyIdList(Map<String, String> ids) throws ParseException {
+        List<IdReference> policyIds = new ArrayList<>();
+
+        for (Entry<String, String> entrySet : ids.entrySet()) {
+            policyIds.add(new StdIdReference(new IdentifierImpl(entrySet.getKey()),
+                    StdVersion.newInstance(entrySet.getValue())));
+        }
+
+        return policyIds;
+    }
+
+    /**
+     * createXacmlResponse.
+     *
+     * @param code StatusCode
+     * @param decision Decision
+     * @param obligations Collection of Obligation objects
+     * @param policyIds Collection of IdReference objects
+     * @return Response object
+     */
+    public static Response createXacmlResponse(StatusCode code, Decision decision, Collection<Obligation> obligations,
+            Collection<IdReference> policyIds) {
+        StdStatus status = new StdStatus(code);
+
+        StdMutableResult result = new StdMutableResult(decision, status);
+        result.addObligations(obligations);
+        result.addPolicyIdentifiers(policyIds);
+
+        return new StdMutableResponse(result);
+    }
+
+}
index b86617c..b6a7ae2 100644 (file)
@@ -23,7 +23,6 @@
 package org.onap.policy.pdp.xacml.application.common;
 
 import static org.assertj.core.api.Assertions.assertThatCode;
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import java.lang.reflect.Constructor;
@@ -47,10 +46,6 @@ public class ToscaDictionaryTest {
             constructor.setAccessible(true);
             constructor.newInstance();
         }).doesNotThrowAnyException();
-        //
-        // Probably don't need these as these ID's are used by other components
-        //
-        assertNotNull(ToscaDictionary.ID_OBLIGATION_MONITORING_ISSUER);
     }
 
 }
index 0b3ce6c..a7391fa 100644 (file)
 
 package org.onap.policy.pdp.xacml.application.common.std;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
+import com.att.research.xacml.api.AttributeAssignment;
+import com.att.research.xacml.api.Decision;
+import com.att.research.xacml.api.IdReference;
+import com.att.research.xacml.api.Obligation;
+import com.att.research.xacml.api.Response;
+import com.att.research.xacml.api.XACML3;
+import com.att.research.xacml.std.StdStatusCode;
+import java.text.ParseException;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
+import org.junit.Before;
 import org.junit.Test;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.pdp.xacml.application.common.TestUtilsCommon;
+import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
 
 public class StdBaseTranslatorTest {
 
+    String policyJson;
+    String policyBadJson;
+
+    AttributeAssignment assignmentPolicyId;
+    AttributeAssignment assignmentPolicy;
+    AttributeAssignment assignmentBadPolicy;
+    AttributeAssignment assignmentWeight;
+    AttributeAssignment assignmentPolicyType;
+    AttributeAssignment assignmentUnknown;
+
+    Obligation obligation;
+
+    /**
+     * beforeSetup - loads and creates objects used later by the tests.
+     * @throws CoderException CoderException
+     *
+     */
+    @Before
+    public void beforeSetup() throws CoderException {
+        policyJson = ResourceUtils.getResourceAsString("test.policy.json");
+        policyBadJson = ResourceUtils.getResourceAsString("test.policy.bad.json");
+
+        assignmentPolicyId = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_ID.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_ID_CATEGORY.stringValue(),
+                "policy.id"
+                );
+
+        assignmentPolicy = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY.stringValue(),
+                policyJson
+                );
+
+        assignmentBadPolicy = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY.stringValue(),
+                policyBadJson
+                );
+
+        assignmentWeight = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_WEIGHT_CATEGORY.stringValue(),
+                0
+                );
+
+        assignmentPolicyType = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_TYPE.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_TYPE_CATEGORY.stringValue(),
+                "onap.policies.Test"
+                );
+
+        assignmentUnknown = TestUtilsCommon.createAttributeAssignment(
+                "foo:bar",
+                XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue(),
+                10.2
+                );
+
+        obligation = TestUtilsCommon.createXacmlObligation(
+                ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue(),
+                Arrays.asList(assignmentPolicyId, assignmentPolicy, assignmentWeight, assignmentPolicyType));
+    }
+
     @Test
-    public void test() {
-        StdBaseTranslator translator = new StdBaseTranslator();
+    public void test() throws ParseException {
+        StdBaseTranslator translator = new MyStdBaseTranslator();
         assertNotNull(translator);
         assertThatThrownBy(() -> translator.convertPolicy(null)).isInstanceOf(ToscaPolicyConversionException.class);
         assertNull(translator.convertRequest(null));
+
+        assertThat(translator.generateAnyOfForPolicyType("foo.bar")).isNotNull();
+        assertThat(translator.generateAnyOfForPolicyType("foo.bar").getAllOf().size()).isEqualTo(1);
+
+        assertThat(translator.generateConditionForPolicyType("foo.bar")).isNotNull();
+        assertThat(translator.generateConditionForPolicyType("foo.bar").getExpression()).isNotNull();
+
+        //
+        // Test the addObligation method
+        //
+        PolicySetType policySet = new PolicySetType();
+
+        translator.addObligation(policySet, "policy.id", policyJson, 0, "foo.bar");
+
+        assertThat(policySet.getObligationExpressions().getObligationExpression().size()).isEqualTo(1);
+        assertThat(policySet.getObligationExpressions().getObligationExpression().get(0)
+                .getAttributeAssignmentExpression().size()).isEqualTo(4);
+
+        PolicyType policy = new PolicyType();
+        translator.addObligation(policy, null, policyJson, null, null);
+
+        assertThat(policy.getObligationExpressions().getObligationExpression().size()).isEqualTo(1);
+        assertThat(policy.getObligationExpressions().getObligationExpression().get(0)
+                .getAttributeAssignmentExpression().size()).isEqualTo(1);
+
+        RuleType rule = new RuleType();
+        translator.addObligation(rule, "policy.id", null, null, "foo.bar");
+
+        assertThat(rule.getObligationExpressions().getObligationExpression().size()).isEqualTo(1);
+        assertThat(rule.getObligationExpressions().getObligationExpression().get(0)
+                .getAttributeAssignmentExpression().size()).isEqualTo(2);
+
+        rule = new RuleType();
+        translator.addObligation(rule, null, null, null, null);
+
+        assertThat(rule.getObligationExpressions().getObligationExpression().size()).isEqualTo(1);
+        assertThat(rule.getObligationExpressions().getObligationExpression().get(0)
+                .getAttributeAssignmentExpression().size()).isEqualTo(0);
+
+        //
+        // Should not throw an exception
+        //
+        translator.addObligation(new String(), "policy.id", policyJson, null, "foo.bar");
+
+        //
+        // Test the response conversion
+        //
+        Map<String, String> ids = new HashMap<>();
+        ids.put("onap.policies.Test", "1.0.0");
+        Collection<IdReference> policyIds = TestUtilsCommon.createPolicyIdList(ids);
+
+        Response xacmlResponse = TestUtilsCommon.createXacmlResponse(StdStatusCode.STATUS_CODE_OK,
+                Decision.PERMIT, Arrays.asList(obligation), policyIds);
+
+        DecisionResponse decision = translator.convertResponse(xacmlResponse);
+
+        assertNotNull(decision);
+
+        assertThat(decision.getPolicies()).isNotNull();
+        assertThat(decision.getPolicies().size()).isEqualTo(0);
     }
 
     @Test
-    public void testBadData() throws ToscaPolicyConversionException {
+    public void testBadData() throws ToscaPolicyConversionException, ParseException {
         TestTranslator translator = new TestTranslator();
 
         assertThatThrownBy(() -> translator.convertPolicy(
@@ -63,11 +205,59 @@ public class StdBaseTranslatorTest {
         ToscaPolicy policy = new ToscaPolicy();
         assertEquals("1.0.0", translator.convertPolicy(policy).getVersion());
 
+        Map<String, String> ids = new HashMap<>();
+        ids.put("onap.policies.Test", "1.0.0");
+        Collection<IdReference> policyIds = TestUtilsCommon.createPolicyIdList(ids);
+
+        Response xacmlResponse = TestUtilsCommon.createXacmlResponse(StdStatusCode.STATUS_CODE_OK,
+                Decision.PERMIT, Arrays.asList(obligation), policyIds);
+
+        DecisionResponse decision = translator.convertResponse(xacmlResponse);
+
+        assertNotNull(decision);
+
+        assertThat(decision.getPolicies()).isNotNull();
+        assertThat(decision.getPolicies().size()).isEqualTo(0);
+
+        //
+        // This will need more work when I fix
+        // the convertResponse
+        //
+
+        Obligation badObligation = TestUtilsCommon.createXacmlObligation(
+                ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue(),
+                Arrays.asList(assignmentBadPolicy, assignmentUnknown));
+
+        xacmlResponse = TestUtilsCommon.createXacmlResponse(StdStatusCode.STATUS_CODE_MISSING_ATTRIBUTE,
+                Decision.PERMIT, Arrays.asList(badObligation), policyIds);
+
+        decision = translator.convertResponse(xacmlResponse);
+
+        assertNotNull(decision);
+
+        xacmlResponse = TestUtilsCommon.createXacmlResponse(StdStatusCode.STATUS_CODE_OK,
+                Decision.DENY, Arrays.asList(badObligation), policyIds);
+
+        decision = translator.convertResponse(xacmlResponse);
+
+        assertNotNull(decision);
+    }
+
+    private class MyStdBaseTranslator extends StdBaseTranslator {
+
+        @Override
+        protected void scanObligations(Collection<Obligation> obligations, DecisionResponse decisionResponse) {
+        }
+
     }
 
-    public class TestTranslator extends StdBaseTranslator {
+    private class TestTranslator extends StdBaseTranslator {
         public Map<String, String> metadata = new HashMap<>();
 
+        @Override
+        protected void scanObligations(Collection<Obligation> obligations, DecisionResponse decisionResponse) {
+        }
+
         @Override
         public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
             PolicyType xacmlPolicy = new PolicyType();
diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslatorTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdCombinedPolicyResultsTranslatorTest.java
new file mode 100644 (file)
index 0000000..9312455
--- /dev/null
@@ -0,0 +1,155 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.pdp.xacml.application.common.std;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertNotNull;
+
+import com.att.research.xacml.api.AttributeAssignment;
+import com.att.research.xacml.api.Decision;
+import com.att.research.xacml.api.IdReference;
+import com.att.research.xacml.api.Obligation;
+import com.att.research.xacml.api.Response;
+import com.att.research.xacml.std.StdStatusCode;
+import java.text.ParseException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
+import org.onap.policy.pdp.xacml.application.common.TestUtilsCommon;
+import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
+
+public class StdCombinedPolicyResultsTranslatorTest {
+
+    String policyJson;
+    String policyBadJson;
+
+    AttributeAssignment assignmentPolicyId;
+    AttributeAssignment assignmentPolicy;
+    AttributeAssignment assignmentBadPolicy;
+
+    Obligation obligation;
+
+    /**
+     * setup - preload policies.
+     */
+    @Before
+    public void setup() {
+        policyJson = ResourceUtils.getResourceAsString("test.policy.json");
+        policyBadJson = ResourceUtils.getResourceAsString("test.policy.bad.json");
+
+        assignmentPolicyId = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_ID.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_ID_CATEGORY.stringValue(),
+                policyJson
+                );
+
+        assignmentPolicy = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY.stringValue(),
+                policyJson
+                );
+
+        assignmentBadPolicy = TestUtilsCommon.createAttributeAssignment(
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT.stringValue(),
+                ToscaDictionary.ID_OBLIGATION_POLICY_CONTENT_CATEGORY.stringValue(),
+                policyBadJson
+                );
+
+
+        obligation = TestUtilsCommon.createXacmlObligation(
+                ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue(),
+                Arrays.asList(assignmentPolicyId, assignmentPolicy));
+
+    }
+
+    @Test
+    public void test() throws ParseException {
+        StdCombinedPolicyResultsTranslator translator = new StdCombinedPolicyResultsTranslator();
+
+        assertNotNull(translator);
+        assertThatThrownBy(() -> translator.convertPolicy(null)).isInstanceOf(ToscaPolicyConversionException.class);
+
+        assertThat(translator.generateTargetType("policy.id", "onap.policy.type", "1.0.0")).isNotNull();
+
+        Map<String, String> ids = new HashMap<>();
+        ids.put("onap.policies.Test", "1.0.0");
+        Collection<IdReference> policyIds = TestUtilsCommon.createPolicyIdList(ids);
+
+        Response xacmlResponse = TestUtilsCommon.createXacmlResponse(StdStatusCode.STATUS_CODE_OK,
+                Decision.PERMIT, Arrays.asList(obligation), policyIds);
+
+        DecisionResponse decision = translator.convertResponse(xacmlResponse);
+
+        assertNotNull(decision);
+
+        assertThat(decision.getPolicies()).isNotNull();
+        assertThat(decision.getPolicies().size()).isEqualTo(1);
+    }
+
+    @Test
+    public void testConvert() throws ToscaPolicyConversionException, CoderException {
+        StdCombinedPolicyResultsTranslator translator = new StdCombinedPolicyResultsTranslator();
+
+        assertThatThrownBy(() -> translator.convertPolicy(
+                new ToscaPolicy())).isInstanceOf(ToscaPolicyConversionException.class)
+                    .hasMessageContaining("missing metadata");
+
+        StandardCoder coder = new StandardCoder();
+
+        ToscaServiceTemplate template = coder.decode(policyJson, ToscaServiceTemplate.class);
+        //
+        // Make sure all the fields are setup properly
+        //
+        JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
+        jtst.fromAuthorative(template);
+        ToscaServiceTemplate completedJtst = jtst.toAuthorative();
+        for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
+            for (ToscaPolicy policy : policies.values()) {
+                translator.convertPolicy(policy);
+            }
+        }
+    }
+
+    @Test
+    public void testDecision() {
+        StdCombinedPolicyResultsTranslator translator = new StdCombinedPolicyResultsTranslator();
+
+        DecisionRequest decision = new DecisionRequest();
+        Map<String, Object> resource = new HashMap<>();
+        decision.setResource(resource);
+        assertNotNull(translator.convertRequest(decision));
+    }
+}
index d3e362c..f259c20 100644 (file)
@@ -96,39 +96,4 @@ public class StdMatchablePolicyRequestTest {
 
     }
 
-    /*
-    @Test
-    public void testCreateInstance_StringValues() {
-        resources.put(StdMatchablePolicyRequest.POLICY_SCOPE_KEY, POLICY_SCOPE);
-        resources.put(StdMatchablePolicyRequest.POLICY_SCOPE_KEY + "-x", "unused value");
-        resources.put(StdMatchablePolicyRequest.POLICY_TYPE_KEY, POLICY_TYPE);
-
-        stdreq = StdMatchablePolicyRequest.createInstance(decreq);
-
-        Collection<String> res = stdreq.getPolicyScopes();
-        assertFalse(res.isEmpty());
-        assertEquals(POLICY_SCOPE, res.iterator().next());
-
-        res = stdreq.getPolicyTypes();
-        assertFalse(res.isEmpty());
-        assertEquals(POLICY_TYPE, res.iterator().next());
-    }
-
-    @Test
-    public void testCreateInstance_Collections() {
-        resources.put(StdMatchablePolicyRequest.POLICY_SCOPE_KEY, Collections.singleton(POLICY_SCOPE));
-        resources.put(StdMatchablePolicyRequest.POLICY_TYPE_KEY, Collections.singleton(POLICY_TYPE));
-
-        stdreq = StdMatchablePolicyRequest.createInstance(decreq);
-
-        Collection<String> res = stdreq.getPolicyScopes();
-        assertFalse(res.isEmpty());
-        assertEquals(POLICY_SCOPE, res.iterator().next());
-
-        res = stdreq.getPolicyTypes();
-        assertFalse(res.isEmpty());
-        assertEquals(POLICY_TYPE, res.iterator().next());
-    }
-*/
-
 }
index 07317c0..e9e8814 100644 (file)
 
 package org.onap.policy.pdp.xacml.application.common.std;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import com.att.research.xacml.api.AttributeAssignment;
+import com.att.research.xacml.api.Decision;
+import com.att.research.xacml.api.IdReference;
+import com.att.research.xacml.api.Obligation;
+import com.att.research.xacml.api.Request;
+import com.att.research.xacml.std.StdStatusCode;
 import java.io.IOException;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.UUID;
@@ -37,6 +50,8 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Response;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -52,10 +67,14 @@ import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.coder.StandardYamlCoder;
 import org.onap.policy.common.utils.network.NetworkUtil;
 import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
+import org.onap.policy.pdp.xacml.application.common.TestUtilsCommon;
+import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
 import org.slf4j.Logger;
@@ -141,7 +160,7 @@ public class StdMatchableTranslatorTest {
     }
 
     @Test
-    public void test() throws CoderException, ToscaPolicyConversionException {
+    public void test() throws CoderException, ToscaPolicyConversionException, ParseException {
         //
         // Create our translator
         //
@@ -168,15 +187,76 @@ public class StdMatchableTranslatorTest {
         jtst.fromAuthorative(serviceTemplate);
         ToscaServiceTemplate completedJtst = jtst.toAuthorative();
         //
-        // Get the policies
+        // Convert the policy
         //
         for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
             for (ToscaPolicy policy : policies.values()) {
                 PolicyType translatedPolicy = translator.convertPolicy(policy);
                 assertNotNull(translatedPolicy);
+                assertThat(translatedPolicy.getObligationExpressions().getObligationExpression()).hasSize(1);
                 logger.info("Translated policy {} {}", XacmlPolicyUtils.LINE_SEPARATOR, translatedPolicy);
+                //
+                // Shortcut to create an obligation, we are just going to steal
+                // the attributes from the translated policy.
+                //
+                List<AttributeAssignment> listAttributes = new ArrayList<>();
+                ObligationExpressionType xacmlObligation = translatedPolicy.getObligationExpressions()
+                        .getObligationExpression().get(0);
+                assertThat(xacmlObligation.getAttributeAssignmentExpression()).hasSize(4);
+                //
+                // Copy into the list
+                //
+                xacmlObligation.getAttributeAssignmentExpression().forEach(assignment -> {
+                    Object value = ((AttributeValueType) assignment.getExpression().getValue()).getContent().get(0);
+                    listAttributes.add(TestUtilsCommon.createAttributeAssignment(assignment.getAttributeId(),
+                            assignment.getCategory(), value));
+                });
+                //
+                // Pretend we got multiple policies to match a fictional request
+                //
+                Obligation obligation1 = TestUtilsCommon.createXacmlObligation(
+                        ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue(),
+                        listAttributes);
+                Obligation obligation2 = TestUtilsCommon.createXacmlObligation(
+                        ToscaDictionary.ID_OBLIGATION_REST_BODY.stringValue(),
+                        listAttributes);
+                //
+                // Should ignore this obligation
+                //
+                Obligation obligation3 = TestUtilsCommon.createXacmlObligation(
+                        "nobody:cares",
+                        listAttributes);
+                //
+                // Create a test XACML Response
+                //
+                Map<String, String> ids = new HashMap<>();
+                ids.put("onap.policies.Test", "1.0.0");
+                Collection<IdReference> policyIds = TestUtilsCommon.createPolicyIdList(ids);
+
+                com.att.research.xacml.api.Response xacmlResponse = TestUtilsCommon.createXacmlResponse(
+                        StdStatusCode.STATUS_CODE_OK, Decision.PERMIT,
+                        Arrays.asList(obligation1, obligation2, obligation3), policyIds);
+                //
+                // Test the response
+                //
+                DecisionResponse decisionResponse = translator.convertResponse(xacmlResponse);
+                assertNotNull(decisionResponse);
+                assertThat(decisionResponse.getPolicies()).hasSize(1);
             }
         }
+        //
+        // Test request decisions
+        //
+        DecisionRequest decisionRequest = new DecisionRequest();
+        decisionRequest.setAction("action");
+        decisionRequest.setOnapComponent("onap-component");
+        decisionRequest.setOnapName("onap");
+        Map<String, Object> resource = new HashMap<>();
+        resource.put("matchableString", "I should be matched");
+        decisionRequest.setResource(resource);
+        Request xacmlRequest = translator.convertRequest(decisionRequest);
+        assertNotNull(xacmlRequest);
+        assertThat(xacmlRequest.getRequestAttributes()).hasSize(3);
     }
 
     /**
diff --git a/applications/common/src/test/resources/test.policy.bad.json b/applications/common/src/test/resources/test.policy.bad.json
new file mode 100644 (file)
index 0000000..6bc06c3
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "tosca_definitions_version": "tosca_simple_yaml_1_0_0",
+    "topology_template": {
+        "policies": [
+            {
+                "Test.policy": {
+                    "type": "onap.policies.Test",
+                    "type_version": "1.0.0",
+                    "version": "1.0.0",
+                    "properties": {
+                        "foo": "bar"
+                    }
+                }
+            }
+        ]
+    }
+}
diff --git a/applications/common/src/test/resources/test.policy.json b/applications/common/src/test/resources/test.policy.json
new file mode 100644 (file)
index 0000000..f152938
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    "tosca_definitions_version": "tosca_simple_yaml_1_0_0",
+    "topology_template": {
+        "policies": [
+            {
+                "Test.policy": {
+                    "type": "onap.policies.Test",
+                    "type_version": "1.0.0",
+                    "version": "1.0.0",
+                    "metadata": {
+                        "policy-id": "Test.policy",
+                        "policy-version": 1
+                    },
+                    "properties": {
+                        "foo": "bar"
+                    }
+                }
+            }
+        ]
+    }
+}
index 1bcb522..b77f301 100644 (file)
@@ -255,7 +255,7 @@ public class OptimizationPdpApplicationTest {
         //
         DecisionResponse response = makeDecision();
         assertThat(response).isNotNull();
-        assertThat(response.getPolicies().size()).isEqualTo(3); // Should be 1
+        assertThat(response.getPolicies().size()).isEqualTo(2);
         //
         // Validate it
         //
@@ -275,7 +275,7 @@ public class OptimizationPdpApplicationTest {
         DecisionResponse response = makeDecision();
 
         assertThat(response).isNotNull();
-        assertThat(response.getPolicies().size()).isEqualTo(6); // should be 1
+        assertThat(response.getPolicies().size()).isEqualTo(4);
         //
         // Validate it
         //
@@ -286,7 +286,7 @@ public class OptimizationPdpApplicationTest {
     @Test
     public void test07OptimizationDefaultGeographyAndServiceAndResource() throws CoderException {
         //
-        // Add vCPE to the service list
+        // Add vG to the resource list
         //
         ((List<String>)baseRequest.getResource().get("resources")).add("vG");
         //
@@ -295,7 +295,7 @@ public class OptimizationPdpApplicationTest {
         DecisionResponse response = makeDecision();
 
         assertThat(response).isNotNull();
-        assertThat(response.getPolicies().size()).isEqualTo(11); // should be 4
+        assertThat(response.getPolicies().size()).isEqualTo(8);
         //
         // Validate it
         //
@@ -315,7 +315,7 @@ public class OptimizationPdpApplicationTest {
         DecisionResponse response = makeDecision();
 
         assertThat(response).isNotNull();
-        assertThat(response.getPolicies().size()).isEqualTo(12); // should be 1
+        assertThat(response.getPolicies().size()).isEqualTo(8);
         //
         // Validate it
         //
@@ -335,7 +335,7 @@ public class OptimizationPdpApplicationTest {
         DecisionResponse response = makeDecision();
 
         assertThat(response).isNotNull();
-        assertThat(response.getPolicies().size()).isEqualTo(14); // should be 3
+        assertThat(response.getPolicies().size()).isEqualTo(10);
         //
         // Validate it
         //
@@ -355,7 +355,7 @@ public class OptimizationPdpApplicationTest {
         DecisionResponse response = makeDecision();
 
         assertThat(response).isNotNull();
-        assertThat(response.getPolicies().size()).isEqualTo(13); // should be 2
+        assertThat(response.getPolicies().size()).isEqualTo(9);
         //
         // Validate it
         //
@@ -375,7 +375,7 @@ public class OptimizationPdpApplicationTest {
         DecisionResponse response = makeDecision();
 
         assertThat(response).isNotNull();
-        assertThat(response.getPolicies().size()).isEqualTo(4); // should be 1
+        assertThat(response.getPolicies().size()).isEqualTo(1);
         //
         // Validate it
         //
@@ -395,7 +395,7 @@ public class OptimizationPdpApplicationTest {
         DecisionResponse response = makeDecision();
 
         assertThat(response).isNotNull();
-        assertThat(response.getPolicies().size()).isEqualTo(6); // should be 2
+        assertThat(response.getPolicies().size()).isEqualTo(2);
         //
         // Validate it
         //