Upgrade to oparent 3.2.1
[policy/xacml-pdp.git] / applications / common / src / main / java / org / onap / policy / pdp / xacml / application / common / std / StdMatchableTranslator.java
index 66770e9..5672295 100644 (file)
@@ -2,7 +2,8 @@
  * ============LICENSE_START=======================================================
  * ONAP
  * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2021 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,7 +23,9 @@
 
 package org.onap.policy.pdp.xacml.application.common.std;
 
+import com.att.research.xacml.api.Advice;
 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;
@@ -33,38 +36,43 @@ import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.ArrayList;
-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;
 import lombok.Setter;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
 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;
 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.ToscaConceptIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType;
 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;
 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
+import org.onap.policy.pdp.xacml.application.common.matchable.MatchableCallback;
+import org.onap.policy.pdp.xacml.application.common.matchable.MatchablePolicyType;
+import org.onap.policy.pdp.xacml.application.common.matchable.MatchableProperty;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -75,12 +83,14 @@ import org.slf4j.LoggerFactory;
  * @author pameladragosh
  *
  */
-public class StdMatchableTranslator  extends StdBaseTranslator {
+public class StdMatchableTranslator  extends StdBaseTranslator implements MatchableCallback {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(StdMatchableTranslator.class);
     private static final StandardYamlCoder standardYamlCoder = new StandardYamlCoder();
 
-    private final Map<ToscaPolicyTypeIdentifier, ToscaPolicyType> matchablePolicyTypes = new HashMap<>();
+    private final Map<ToscaConceptIdentifier, ToscaServiceTemplate> matchablePolicyTypes = new HashMap<>();
+    private final Map<ToscaConceptIdentifier, MatchablePolicyType> matchableCache = new HashMap<>();
+
     @Setter
     private RestServerParameters apiRestParameters;
     @Setter
@@ -91,30 +101,152 @@ public class StdMatchableTranslator  extends StdBaseTranslator {
     }
 
     @Override
-    public Request convertRequest(DecisionRequest request) {
+    public Request convertRequest(DecisionRequest request) throws ToscaPolicyConversionException {
         LOGGER.info("Converting Request {}", request);
         try {
             return StdMatchablePolicyRequest.createInstance(request);
         } catch (XacmlApplicationException e) {
-            LOGGER.error("Failed to convert DecisionRequest: {}", e);
+            throw new ToscaPolicyConversionException("Failed to convert DecisionRequest", e);
         }
+    }
+
+    /**
+     * 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) {
         //
-        // TODO throw exception
+        // 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.
         //
-        return null;
+        // 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());
+                })
+            )
+        );
+    }
+
+    @Override
+    protected void scanAdvice(Collection<Advice> advice, DecisionResponse decisionResponse) {
+        LOGGER.warn("scanAdvice not supported by {}", this.getClass());
+    }
+
+    /**
+     * 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 {
+    public Object convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException {
         //
         // Get the TOSCA Policy Type for this policy
         //
-        Collection<ToscaPolicyType> toscaPolicyTypes = this.getPolicyTypes(toscaPolicy.getTypeIdentifier());
+        ToscaServiceTemplate toscaPolicyTypeTemplate = this.findPolicyType(toscaPolicy.getTypeIdentifier());
         //
         // If we don't have any TOSCA policy types, then we cannot know
         // which properties are matchable.
         //
-        if (toscaPolicyTypes.isEmpty()) {
+        if (toscaPolicyTypeTemplate == null) {
             throw new ToscaPolicyConversionException(
                     "Cannot retrieve Policy Type definition for policy " + toscaPolicy.getName());
         }
@@ -143,7 +275,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, toscaPolicyTypeTemplate);
+        newPolicyType.setTarget(pairGenerated.getLeft());
         //
         // Now represent the policy as Json
         //
@@ -157,7 +290,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.
         //
@@ -190,256 +323,192 @@ public class StdMatchableTranslator  extends StdBaseTranslator {
         return newPolicyType;
     }
 
-    /**
-     * For generating target type, we scan for matchable properties
-     * and use those to build the policy.
-     *
-     * @param properties Properties section of policy
-     * @param policyTypes Collection of policy Type to find matchable metadata
-     * @return TargetType object
-     */
-    protected TargetType generateTargetType(Map<String, Object> properties, Collection<ToscaPolicyType> policyTypes) {
-        TargetType targetType = new TargetType();
-        //
-        // Iterate the properties
-        //
-        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());
-            }
+    @Override
+    public ToscaPolicyType retrievePolicyType(String derivedFrom) {
+        ToscaServiceTemplate template = this.findPolicyType(new ToscaConceptIdentifier(derivedFrom, "1.0.0"));
+        if (template == null) {
+            LOGGER.error("Could not retrieve Policy Type {}", derivedFrom);
+            return null;
         }
-
-        return targetType;
+        return template.getPolicyTypes().get(derivedFrom);
     }
 
-    /**
-     * isMatchable - Iterates through available TOSCA Policy Types to determine if a property
-     * should be treated as matchable.
-     *
-     * @param propertyName Name of property
-     * @param policyTypes Collection of TOSCA Policy Types to scan
-     * @return true if matchable
-     */
-    protected boolean isMatchable(String propertyName, Collection<ToscaPolicyType> policyTypes) {
-        for (ToscaPolicyType policyType : policyTypes) {
-            for (Entry<String, ToscaProperty> propertiesEntry : policyType.getProperties().entrySet()) {
-                if (checkIsMatchableProperty(propertyName, propertiesEntry)) {
-                    return true;
-                }
-            }
-        }
-        return false;
+    @Override
+    public ToscaDataType retrieveDataType(String datatype) {
+        //
+        // Our outer class is not storing the current template being scanned
+        //
+        LOGGER.error("this retrieveDataType should not be called.");
+        return null;
     }
 
-    /**
-     * checkIsMatchableProperty - checks the policy contents for matchable field. If the metadata doesn't exist,
-     * then definitely not. If the property doesn't exist, then definitely not. Otherwise need to have a metadata
-     * section with the matchable property set to true.
-     *
-     * @param propertyName String value of property
-     * @param propertiesEntry Section of the TOSCA Policy Type where properties and metadata sections are held
-     * @return true if matchable
-     */
-    protected boolean checkIsMatchableProperty(String propertyName, Entry<String, ToscaProperty> propertiesEntry) {
-        if (! propertiesEntry.getKey().equals(propertyName)
-                || propertiesEntry.getValue().getMetadata() == null) {
-            return false;
+    private class MyMatchableCallback implements MatchableCallback {
+        private StdMatchableTranslator translator;
+        private ToscaServiceTemplate template;
+
+        public MyMatchableCallback(StdMatchableTranslator translator, ToscaServiceTemplate template) {
+            this.translator = translator;
+            this.template = template;
         }
-        for (Entry<String, String> entrySet : propertiesEntry.getValue().getMetadata().entrySet()) {
-            if ("matchable".equals(entrySet.getKey()) && "true".equals(entrySet.getValue())) {
-                return true;
+
+        @Override
+        public ToscaPolicyType retrievePolicyType(String derivedFrom) {
+            ToscaPolicyType policyType = this.template.getPolicyTypes().get(derivedFrom);
+            if (policyType != null) {
+                return policyType;
             }
+            return translator.retrievePolicyType(derivedFrom);
         }
-        return false;
-    }
 
-    /**
-     * generateMatchable - Given the object, generates list of MatchType objects and add them
-     * to the TargetType object.
-     *
-     * @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
-     */
-    @SuppressWarnings("unchecked")
-    protected TargetType generateMatchable(TargetType targetType, String key, Object value) {
-        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);
-            }
-        } else {
-            AnyOfType anyOf = generateMatches(Arrays.asList(value),
-                    new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key));
-            if (! anyOf.getAllOf().isEmpty()) {
-                targetType.getAnyOf().add(anyOf);
-            }
+        @Override
+        public ToscaDataType retrieveDataType(String datatype) {
+            return this.template.getDataTypes().get(datatype);
         }
-        return targetType;
+
     }
 
     /**
-     * generateMatches - Goes through the collection of objects, creates a MatchType object
-     * for each object and associates it with the given attribute Id. Returns the AnyOfType
-     * object that contains all the generated MatchType objects.
+     * For generating target type, we scan for matchable properties
+     * and use those to build the policy.
      *
-     * @param matchables Collection of object to generate MatchType from
-     * @param attributeId Given attribute Id for each MatchType
-     * @return AnyOfType object
+     * @param policy Tosca Policy to generate Target Type
+     * @param template Toca Template
+     * @return {@code Pair<TargetType, Integer>} Returns a TargetType and a Total Weight of matchables.
      */
-    protected AnyOfType generateMatches(Collection<Object> matchables, Identifier attributeId) {
+    protected Pair<TargetType, Integer> generateTargetType(ToscaPolicy policy, ToscaServiceTemplate template) {
         //
-        // This is our outer AnyOf - which is an OR
+        // Our return object
         //
-        AnyOfType anyOf = new AnyOfType();
-        for (Object matchable : matchables) {
-            //
-            // Default to string
-            //
-            Identifier idFunction = XACML3.ID_FUNCTION_STRING_EQUAL;
-            Identifier idDatatype = XACML3.ID_DATATYPE_STRING;
-            //
-            // See if we are another datatype
+        TargetType target = new TargetType();
+        //
+        // See if we have a matchable in the cache already
+        //
+        MatchablePolicyType matchablePolicyType = matchableCache.get(policy.getTypeIdentifier());
+        //
+        // If not found, create one
+        //
+        if (matchablePolicyType == null) {
             //
-            // We should add datetime support. But to do that we need
-            // probably more metadata to describe how that would be translated.
+            // Our callback
             //
-            if (matchable instanceof Integer) {
-                idFunction = XACML3.ID_FUNCTION_INTEGER_EQUAL;
-                idDatatype = XACML3.ID_DATATYPE_INTEGER;
-            } else if (matchable instanceof Double) {
-                idFunction = XACML3.ID_FUNCTION_DOUBLE_EQUAL;
-                idDatatype = XACML3.ID_DATATYPE_DOUBLE;
-            } else if (matchable instanceof Boolean) {
-                idFunction = XACML3.ID_FUNCTION_BOOLEAN_EQUAL;
-                idDatatype = XACML3.ID_DATATYPE_BOOLEAN;
-            }
+            MyMatchableCallback myCallback = new MyMatchableCallback(this, template);
             //
-            // Create a match for this
+            // Create the matchable
             //
-            MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
-                    idFunction,
-                    matchable.toString(),
-                    idDatatype,
-                    attributeId,
-                    XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
+            matchablePolicyType = new MatchablePolicyType(
+                    template.getPolicyTypes().get(policy.getType()), myCallback);
             //
-            // Now create an anyOf (OR)
+            // Cache it
             //
-            anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(match));
+            matchableCache.put(policy.getTypeIdentifier(), matchablePolicyType);
         }
-        return anyOf;
-    }
-
-    /**
-     * Get Policy Type definitions. This could be previously loaded, or could be
-     * stored in application path, or may need to be pulled from the API.
-     *
-     *
-     * @param policyTypeId Policy Type Id
-     * @return A list of PolicyTypes
-     */
-    private List<ToscaPolicyType> getPolicyTypes(ToscaPolicyTypeIdentifier policyTypeId) {
         //
-        // Create identifier from the policy
+        // Fill in the target type with potential matchables
         //
-        ToscaPolicyTypeIdentifier typeId = new ToscaPolicyTypeIdentifier(policyTypeId);
-        //
-        // Find the Policy Type
-        //
-        ToscaPolicyType policyType = findPolicyType(typeId);
-        if (policyType == null)  {
-            return Collections.emptyList();
+        try {
+            fillTargetTypeWithMatchables(target, matchablePolicyType, policy.getProperties());
+        } catch (ToscaPolicyConversionException e) {
+            LOGGER.error("Could not generate target type", e);
         }
         //
-        // Create our return object
+        // There may be a case for default policies there is no weight - need to clean
+        // up the target then else PDP will report bad policy missing AnyOf
         //
-        List<ToscaPolicyType> listTypes = new ArrayList<>();
-        listTypes.add(policyType);
+        int weight = calculateWeight(target);
+        LOGGER.debug("Weight is {} for policy {}", weight, policy.getName());
         //
-        // Look for parent policy types that could also contain matchable properties
+        // Assume the number of AllOf's is the weight for now
         //
-        ToscaPolicyType childPolicyType = policyType;
-        while (! childPolicyType.getDerivedFrom().startsWith("tosca.policies.Root")) {
-            //
-            // Create parent policy type id.
-            //
-            // We will have to assume the same version between child and the
-            // parent policy type it derives from.
-            //
-            // Or do we assume 1.0.0?
-            //
-            ToscaPolicyTypeIdentifier parentId = new ToscaPolicyTypeIdentifier(childPolicyType.getDerivedFrom(),
-                    "1.0.0");
-            //
-            // Find the policy type
-            //
-            ToscaPolicyType parentPolicyType = findPolicyType(parentId);
-            if (parentPolicyType == null) {
-                //
-                // Probably would be best to throw an exception and
-                // return nothing back.
+        return Pair.of(target, weight);
+    }
+
+    @SuppressWarnings("unchecked")
+    protected void fillTargetTypeWithMatchables(TargetType target, MatchablePolicyType matchablePolicyType,
+            Map<String, Object> properties) throws ToscaPolicyConversionException {
+        for (Entry<String, Object> entrySet : properties.entrySet()) {
+            String propertyName = entrySet.getKey();
+            Object propertyValue = entrySet.getValue();
+            MatchableProperty matchable = matchablePolicyType.get(propertyName);
+            if (matchable != null) {
                 //
-                // But instead we will log a warning
+                // Construct attribute id
                 //
-                LOGGER.warn("Missing parent policy type - proceeding anyway {}", parentId);
+                Identifier id = new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + propertyName);
                 //
-                // Break the loop
+                // Depending on what type it is, add it into the target
                 //
-                break;
+                ToscaPolicyTranslatorUtils.buildAndAppendTarget(target,
+                        matchable.getType().generate(propertyValue, id));
+
+                continue;
             }
             //
-            // Great save it
-            //
-            listTypes.add(parentPolicyType);
-            //
-            // Move to the next parent
+            // Here is the special case where we look for a Collection of values that may
+            // contain potential matchables
             //
-            childPolicyType = parentPolicyType;
+            if (propertyValue instanceof List) {
+                for (Object listValue : ((List<?>) propertyValue)) {
+                    if (listValue instanceof Map) {
+                        fillTargetTypeWithMatchables(target, matchablePolicyType, (Map<String, Object>) listValue);
+                    }
+                }
+            } else if (propertyValue instanceof Map) {
+                fillTargetTypeWithMatchables(target, matchablePolicyType, (Map<String, Object>) propertyValue);
+            }
+        }
+    }
+
+    protected int calculateWeight(TargetType target) {
+        int weight = 0;
+        for (AnyOfType anyOf : target.getAnyOf()) {
+            for (AllOfType allOf : anyOf.getAllOf()) {
+                weight += allOf.getMatch().size();
+            }
         }
-        return listTypes;
+
+        return weight;
     }
 
     /**
-     * findPolicyType - given the ToscaPolicyTypeIdentifier, finds it in memory, or
+     * findPolicyType - given the ToscaConceptIdentifier, finds it in memory, or
      * then tries to find it either locally on disk or pull it from the Policy
      * Lifecycle API the given TOSCA Policy Type.
      *
-     * @param policyTypeId ToscaPolicyTypeIdentifier to find
+     * @param policyTypeId ToscaConceptIdentifier to find
      * @return ToscaPolicyType object. Can be null if failure.
      */
-    private ToscaPolicyType findPolicyType(ToscaPolicyTypeIdentifier policyTypeId) {
+    protected ToscaServiceTemplate findPolicyType(ToscaConceptIdentifier policyTypeId) {
         //
         // Is it loaded in memory?
         //
-        ToscaPolicyType policyType = this.matchablePolicyTypes.get(policyTypeId);
-        if (policyType == null)  {
+        ToscaServiceTemplate policyTemplate = this.matchablePolicyTypes.get(policyTypeId);
+        if (policyTemplate == null)  {
             //
             // Load the policy
             //
-            policyType = this.loadPolicyType(policyTypeId);
+            policyTemplate = this.loadPolicyType(policyTypeId);
+            //
+            // Save it
+            //
+            if (policyTemplate != null) {
+                this.matchablePolicyTypes.put(policyTypeId, policyTemplate);
+            }
         }
         //
         // Yep return it
         //
-        return policyType;
+        return policyTemplate;
     }
 
     /**
-     * loadPolicyType - Tries to load the given ToscaPolicyTypeIdentifier from local
+     * loadPolicyType - Tries to load the given ToscaConceptIdentifier from local
      * storage. If it does not exist, will then attempt to pull from Policy Lifecycle
      * API.
      *
-     * @param policyTypeId ToscaPolicyTypeIdentifier input
+     * @param policyTypeId ToscaConceptIdentifier input
      * @return ToscaPolicyType object. Null if failure.
      */
-    private ToscaPolicyType loadPolicyType(ToscaPolicyTypeIdentifier policyTypeId) {
+    protected ToscaServiceTemplate loadPolicyType(ToscaConceptIdentifier policyTypeId) {
         //
         // Construct what the file name should be
         //
@@ -469,34 +538,17 @@ public class StdMatchableTranslator  extends StdBaseTranslator {
         //
         LOGGER.info("Read in local policy type {}", policyTypePath.toAbsolutePath());
         try {
-            ToscaServiceTemplate serviceTemplate = standardYamlCoder.decode(new String(bytes, StandardCharsets.UTF_8),
-                    ToscaServiceTemplate.class);
-            JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
-            jtst.fromAuthorative(serviceTemplate);
-            ToscaServiceTemplate completedJtst = jtst.toAuthorative();
             //
-            // Search for our Policy Type, there really only should be one but
-            // this is returned as a map.
+            // Decode the template
             //
-            for ( Entry<String, ToscaPolicyType> entrySet : completedJtst.getPolicyTypes().entrySet()) {
-                ToscaPolicyType entryPolicyType = entrySet.getValue();
-                if (policyTypeId.getName().equals(entryPolicyType.getName())
-                        && policyTypeId.getVersion().equals(entryPolicyType.getVersion())) {
-                    LOGGER.info("Found existing local policy type {} {}", entryPolicyType.getName(),
-                            entryPolicyType.getVersion());
-                    //
-                    // Just simply return the policy type right here
-                    //
-                    return entryPolicyType;
-                } else {
-                    LOGGER.warn("local policy type contains different name version {} {}", entryPolicyType.getName(),
-                            entryPolicyType.getVersion());
-                }
-            }
+            ToscaServiceTemplate template = standardYamlCoder.decode(new String(bytes, StandardCharsets.UTF_8),
+                    ToscaServiceTemplate.class);
             //
-            // This would be an error, if the file stored does not match what its supposed to be
+            // Ensure all the fields are setup correctly
             //
-            LOGGER.error("Existing policy type file does not contain right name and version");
+            JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
+            jtst.fromAuthorative(template);
+            return jtst.toAuthorative();
         } catch (CoderException e) {
             LOGGER.error("Failed to decode tosca template for {}", policyTypePath, e);
         }
@@ -508,49 +560,51 @@ public class StdMatchableTranslator  extends StdBaseTranslator {
     }
 
     /**
-     * pullPolicyType - pulls the given ToscaPolicyTypeIdentifier from the Policy Lifecycle API.
+     * pullPolicyType - pulls the given ToscaConceptIdentifier from the Policy Lifecycle API.
      * If successful, will store it locally given the policyTypePath.
      *
-     * @param policyTypeId ToscaPolicyTypeIdentifier
+     * @param policyTypeId ToscaConceptIdentifier
      * @param policyTypePath Path object to store locally
      * @return ToscaPolicyType object. Null if failure.
      */
-    private synchronized ToscaPolicyType pullPolicyType(ToscaPolicyTypeIdentifier policyTypeId, Path policyTypePath) {
+    protected synchronized ToscaServiceTemplate pullPolicyType(ToscaConceptIdentifier policyTypeId,
+            Path policyTypePath) {
         //
         // This is what we return
         //
-        ToscaPolicyType policyType = null;
+        ToscaServiceTemplate policyTemplate = null;
         try {
             PolicyApiCaller api = new PolicyApiCaller(this.apiRestParameters);
 
-            policyType = api.getPolicyType(policyTypeId);
+            policyTemplate = api.getPolicyType(policyTypeId);
         } catch (PolicyApiException e) {
             LOGGER.error("Failed to make API call", e);
             LOGGER.error("parameters: {} ", this.apiRestParameters);
             return null;
         }
+        LOGGER.info("Successfully pulled {}", policyTypeId);
         //
         // Store it locally
         //
         try {
-            standardYamlCoder.encode(policyTypePath.toFile(), policyType);
+            standardYamlCoder.encode(policyTypePath.toFile(), policyTemplate);
         } catch (CoderException e) {
             LOGGER.error("Failed to store {} locally to {}", policyTypeId, policyTypePath, e);
         }
         //
         // Done return the policy type
         //
-        return policyType;
+        return policyTemplate;
     }
 
     /**
      * constructLocalFilePath - common method to ensure the name of the local file for the
      * policy type is the same.
      *
-     * @param policyTypeId ToscaPolicyTypeIdentifier
+     * @param policyTypeId ToscaConceptIdentifier
      * @return Path object
      */
-    private Path constructLocalFilePath(ToscaPolicyTypeIdentifier policyTypeId) {
+    protected Path constructLocalFilePath(ToscaConceptIdentifier policyTypeId) {
         return Paths.get(this.pathForData.toAbsolutePath().toString(), policyTypeId.getName() + "-"
                 + policyTypeId.getVersion() + ".yaml");
     }