Re-factor matchable to reduce complexity 55/103855/6
authorPamela Dragosh <pdragosh@research.att.com>
Wed, 18 Mar 2020 11:50:22 +0000 (07:50 -0400)
committerPamela Dragosh <pdragosh@research.att.com>
Thu, 19 Mar 2020 12:03:24 +0000 (08:03 -0400)
This solution is much cleaner than what is in StdMatchableTranslator.
Over 90% code coverage on it - utilizes a callback to retrieve DataType
and PolicyTypes. Support for missing timestamp TOSCA type. Also can
do a better job differentiating between a property contained in the policy
vs a schema.

Changed StdMatchableTranslator to utilize these classes. And removed the
old spaghetti.

Added some JUnit coverage for ToscaPolicyTranslatorUtils.

Removed duplicate code in the XACML Native Exception classes.

Issue-ID: POLICY-2242
Change-Id: I18f898d9e65f6da28e3b27517d40f8d389de18a0
Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
24 files changed:
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtils.java
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchableCallback.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePolicyType.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchableProperty.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyType.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeBase.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeBoolean.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeFloat.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeInteger.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeList.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeMap.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeString.java [new file with mode: 0644]
applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeTimestamp.java [new file with mode: 0644]
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/ToscaPolicyTranslatorUtilsTest.java
applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePolicyTypeTest.java [new file with mode: 0644]
applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java
applications/common/src/test/resources/matchable/onap.policies.Test-1.0.0.yaml
applications/common/src/test/resources/matchable/test.policies.input.tosca.yaml
applications/optimization/src/test/resources/bad-subscriber-policies.yaml
applications/optimization/src/test/resources/test-optimization-policies.yaml
main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlExceptionMapper.java [new file with mode: 0644]
main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlJsonExceptionMapper.java
main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlXmlExceptionMapper.java

index f1d3d5e..796499d 100644 (file)
@@ -25,11 +25,13 @@ package org.onap.policy.pdp.xacml.application.common;
 import com.att.research.xacml.api.Identifier;
 import com.att.research.xacml.api.XACML3;
 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.ApplyType;
 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.MatchType;
 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
 import org.apache.commons.lang3.StringUtils;
 
 /**
@@ -166,4 +168,50 @@ public final class ToscaPolicyTranslatorUtils {
         }
         return theInt;
     }
+
+    /**
+     * For a given MatchType or AnyOfType, builds it and appends it into the
+     * AnyOfType.
+     *
+     * @param anyOf AnyOfType - will create if null
+     * @param type MatchType or AnyOfType
+     * @return returns the given anyOf or new AnyTypeOf if null
+     */
+    public static AnyOfType buildAndAppendAllof(AnyOfType anyOf, Object type) {
+        if (type instanceof MatchType) {
+            AllOfType allOf = new AllOfType();
+            allOf.getMatch().add((MatchType) type);
+            if (anyOf == null) {
+                anyOf = new AnyOfType();
+            }
+            anyOf.getAllOf().add(allOf);
+        } else if (type instanceof AllOfType) {
+            if (anyOf == null) {
+                anyOf = new AnyOfType();
+            }
+            anyOf.getAllOf().add((AllOfType) type);
+        }
+
+        return anyOf;
+    }
+
+    /**
+     * buildAndAppendTarget - adds in the potential object into TargetType.
+     *
+     * @param target TargetType - must exist
+     * @param object AnyOfType or MatchType
+     * @return TargetType
+     */
+    public static TargetType buildAndAppendTarget(TargetType target, Object object) {
+        if (object instanceof AnyOfType) {
+            target.getAnyOf().add((AnyOfType) object);
+        } else if (object instanceof MatchType) {
+            AllOfType allOf = new AllOfType();
+            allOf.getMatch().add((MatchType) object);
+            AnyOfType anyOf = new AnyOfType();
+            anyOf.getAllOf().add(allOf);
+            target.getAnyOf().add(anyOf);
+        }
+        return target;
+    }
 }
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchableCallback.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchableCallback.java
new file mode 100644 (file)
index 0000000..a076929
--- /dev/null
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
+
+public interface MatchableCallback {
+
+    ToscaPolicyType retrievePolicyType(String derivedFrom);
+
+    ToscaDataType retrieveDataType(String datatype);
+
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePolicyType.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePolicyType.java
new file mode 100644 (file)
index 0000000..3bbc6ea
--- /dev/null
@@ -0,0 +1,338 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.function.Function;
+import lombok.Getter;
+import lombok.NonNull;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntrySchema;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Getter
+public class MatchablePolicyType {
+    private static final Logger LOGGER = LoggerFactory.getLogger(MatchablePolicyType.class);
+
+    public static final String TOSCA_PRIMITIVE_STRING = "string";
+    public static final String TOSCA_PRIMITIVE_INTEGER = "integer";
+    public static final String TOSCA_PRIMITIVE_FLOAT = "float";
+    public static final String TOSCA_PRIMITIVE_BOOLEAN = "boolean";
+    public static final String TOSCA_PRIMITIVE_TIMESTAMP = "timestamp";
+    public static final String TOSCA_TYPE_LIST = "list";
+    public static final String TOSCA_TYPE_MAP = "map";
+
+    private static final Map<String, Function<ToscaProperty, MatchablePropertyTypeBase<?>>>
+        mapPrimitivesProperty = Map.of(
+            TOSCA_PRIMITIVE_STRING, MatchablePropertyTypeString::new,
+            TOSCA_PRIMITIVE_INTEGER, MatchablePropertyTypeInteger::new,
+            TOSCA_PRIMITIVE_FLOAT, MatchablePropertyTypeFloat::new,
+            TOSCA_PRIMITIVE_BOOLEAN, MatchablePropertyTypeBoolean::new,
+            TOSCA_PRIMITIVE_TIMESTAMP, MatchablePropertyTypeTimestamp::new
+            );
+
+    private static final Map<String, Function<ToscaEntrySchema, MatchablePropertyTypeBase<?>>>
+        mapPrimitivesSchema = Map.of(
+            TOSCA_PRIMITIVE_STRING, MatchablePropertyTypeString::new,
+            TOSCA_PRIMITIVE_INTEGER, MatchablePropertyTypeInteger::new,
+            TOSCA_PRIMITIVE_FLOAT, MatchablePropertyTypeFloat::new,
+            TOSCA_PRIMITIVE_BOOLEAN, MatchablePropertyTypeBoolean::new,
+            TOSCA_PRIMITIVE_TIMESTAMP, MatchablePropertyTypeTimestamp::new
+            );
+
+    ToscaPolicyIdentifier policyId;
+    Map<String, MatchableProperty> matchables = new HashMap<>();
+
+    public MatchablePolicyType(@NonNull ToscaPolicyType policyType, @NonNull MatchableCallback callback) {
+        this.policyId = new ToscaPolicyIdentifier(policyType.getName(), policyType.getVersion());
+        scanPolicyType(policyType, callback);
+    }
+
+    public MatchableProperty get(@NonNull String property) {
+        return this.matchables.get(property);
+    }
+
+    protected void scanPolicyType(@NonNull ToscaPolicyType inPolicyType, @NonNull MatchableCallback callback) {
+        ToscaPolicyType policyType = inPolicyType;
+        while (policyType != null) {
+            LOGGER.info("Scanning PolicyType {}:{}", policyType.getName(), policyType.getVersion());
+            //
+            // Scan for all the matchable properties
+            //
+            scanProperties(policyType.getProperties(), matchables, callback);
+            //
+            // Does this PolicyType derive from another Policy Type?
+            //
+            if ("tosca.policies.Root".equals(policyType.getDerivedFrom())) {
+                //
+                // No we are finished
+                //
+                LOGGER.info("Found root - done scanning");
+                break;
+            }
+            //
+            // Move to the parent policy and scan it for matchables.
+            //
+            policyType = callback.retrievePolicyType(policyType.getDerivedFrom());
+        }
+    }
+
+    /**
+     * Scans properties for matchables.
+     *
+     * @param properties Map of ToscaProperties to scan
+     * @param matchables Found matchables will be put into this list
+     * @param callback Callback routine for finding Policy Types and Data Types
+     */
+    public static void scanProperties(Map<String, ToscaProperty> properties, Map<String, MatchableProperty> matchables,
+            MatchableCallback callback) {
+        for (Entry<String, ToscaProperty> entrySet : properties.entrySet()) {
+            final String property = entrySet.getKey();
+            final ToscaProperty toscaProperty = entrySet.getValue();
+            //
+            // Most likely case is its a primitive
+            //
+            if (isPrimitive(toscaProperty.getType())) {
+                MatchableProperty primitiveProperty = handlePrimitive(property, toscaProperty);
+                if (primitiveProperty != null) {
+                    matchables.put(property, primitiveProperty);
+                }
+            } else if (TOSCA_TYPE_LIST.equals(toscaProperty.getType())) {
+                MatchableProperty listProperty = handleList(property, toscaProperty, matchables, callback);
+                if (listProperty != null) {
+                    matchables.put(property, listProperty);
+                }
+            } else if (TOSCA_TYPE_MAP.equals(toscaProperty.getType())) {
+                MatchableProperty mapProperty = handleMap(property, toscaProperty, matchables, callback);
+                if (mapProperty != null) {
+                    matchables.put(property, mapProperty);
+                }
+            } else {
+                scanDatatype(toscaProperty, matchables, callback);
+            }
+        }
+    }
+
+    /**
+     * handlePrimitive - handles a primitive type only if its matchable.
+     *
+     * @param property String containing property name
+     * @param toscaProperty ToscaProperty object
+     * @return MatchableProperty object
+     */
+    public static MatchableProperty handlePrimitive(String property, ToscaProperty toscaProperty) {
+        if (!isMatchable(toscaProperty)) {
+            return null;
+        }
+        Function<ToscaProperty, MatchablePropertyTypeBase<?>> function =
+                mapPrimitivesProperty.get(toscaProperty.getType());
+        if (function != null) {
+            return new MatchableProperty(property, function.apply(toscaProperty));
+        }
+        throw new IllegalArgumentException("Not a primitive " + toscaProperty.getType());
+    }
+
+    /**
+     * handlePrimitive from a schema. Note that a ToscaEntrySchema does NOT have a metadata section
+     * so you cannot check if its matchable.
+     *
+     * @param property String containing property name
+     * @param toscaSchema ToscaSchema
+     * @return MatchableProperty object
+     */
+    public static MatchableProperty handlePrimitive(String property, ToscaEntrySchema toscaSchema) {
+        Function<ToscaEntrySchema, MatchablePropertyTypeBase<?>> function =
+                mapPrimitivesSchema.get(toscaSchema.getType());
+        if (function != null) {
+            return new MatchableProperty(property, function.apply(toscaSchema)); // compilation err wants ToscaProperty
+        }
+        throw new IllegalArgumentException("Not a primitive " + toscaSchema.getType());
+    }
+
+    /**
+     * handleList - iterates a list looking for matchables.
+     *
+     * @param property String containing property name
+     * @param toscaProperty ToscaProperty object
+     * @param matchables list of matchables to add to
+     * @param callback MatchableCallback to retrieve Data Types
+     * @return MatchableProperty object
+     */
+    public static MatchableProperty handleList(@NonNull String property, @NonNull ToscaProperty toscaProperty,
+            Map<String, MatchableProperty> matchables, @NonNull MatchableCallback callback) {
+        if (! TOSCA_TYPE_LIST.equals(toscaProperty.getType())) {
+            throw new IllegalArgumentException("must be a list");
+        }
+        //
+        // Is it a simple or complex list?
+        //
+        if (isPrimitive(toscaProperty.getEntrySchema().getType())) {
+            //
+            // Only if the list is matchable
+            //
+            if (!isMatchable(toscaProperty)) {
+                return null;
+            }
+            //
+            // Simple list of primitives
+            //
+            return new MatchableProperty(property, new MatchablePropertyTypeList(toscaProperty));
+        }
+        //
+        // Scan the datatype for matchables
+        //
+        scanDatatype(toscaProperty.getEntrySchema(), matchables, callback);
+        //
+        // Return nothing - scanning the datatype should find the matchables
+        //
+        return null;
+    }
+
+    /**
+     * handleMap - iterates a map looking for matchables.
+     *
+     * @param property String containing property name
+     * @param toscaProperty ToscaProperty object
+     * @param matchables list of matchables to add to
+     * @param callback MatchableCallback to retrieve Data Types
+     * @return MatchableProperty object
+     */
+    public static MatchableProperty handleMap(@NonNull String property, @NonNull ToscaProperty toscaProperty,
+            Map<String, MatchableProperty> matchables, @NonNull MatchableCallback callback) {
+        if (! TOSCA_TYPE_MAP.equals(toscaProperty.getType())) {
+            throw new IllegalArgumentException("must be a map");
+        }
+        //
+        // Is it a simple or complex map?
+        //
+        if (isPrimitive(toscaProperty.getEntrySchema().getType())) {
+            //
+            // Only if the map is matchable
+            //
+            if (!isMatchable(toscaProperty)) {
+                return null;
+            }
+            //
+            // Simple map of primitives
+            //
+            return new MatchableProperty(property, new MatchablePropertyTypeMap(toscaProperty));
+        }
+        //
+        // Scan the datatype for matchables
+        //
+        scanDatatype(toscaProperty.getEntrySchema(), matchables, callback);
+        //
+        // Return nothing - scanning the datatype should find the matchables
+        //
+        return null;
+    }
+
+    /**
+     * scanDatatype - scans a datatypes schema properties for matchables.
+     *
+     * @param toscaProperty ToscaProperty object
+     * @param matchables list of matchables to add to
+     * @param callback MatchableCallback to retrieve Data Types
+     */
+    public static void scanDatatype(@NonNull ToscaProperty toscaProperty, Map<String, MatchableProperty> matchables,
+            @NonNull MatchableCallback callback) {
+        //
+        // Don't check for matchable property, as that does not make sense to support right now. But we need to
+        // scan the datatype for matchable properties.
+        //
+        LOGGER.info("Retrieving datatype {}", toscaProperty.getType());
+        //
+        // Try to retrieve the datatype
+        //
+        ToscaDataType dataType = callback.retrieveDataType(toscaProperty.getType());
+        if (dataType == null) {
+            LOGGER.error("Failed to retrieve datatype {}", toscaProperty.getType());
+            return;
+        }
+        //
+        // Now scan the properties in the datatype
+        //
+        scanProperties(dataType.getProperties(), matchables, callback);
+    }
+
+    /**
+     * scanDatatypes - scans a datatype schema for matchables.
+     *
+     * @param toscaSchema ToscaEntrySchema
+     * @param matchables list of matchables to add to
+     * @param callback MatchableCallback object for retrieving other data types
+     */
+    public static void scanDatatype(@NonNull ToscaEntrySchema toscaSchema, Map<String, MatchableProperty> matchables,
+            @NonNull MatchableCallback callback) {
+        //
+        // Don't check for matchable property, as that does not make sense to support right now. But we need to
+        // scan the datatype for matchable properties.
+        //
+        LOGGER.info("Retrieving datatype {}", toscaSchema.getType());
+        //
+        // Try to retrieve the datatype
+        //
+        ToscaDataType dataType = callback.retrieveDataType(toscaSchema.getType());
+        if (dataType == null) {
+            LOGGER.error("Failed to retrieve datatype {}", toscaSchema.getType());
+            return;
+        }
+        //
+        // Now scan the properties in the datatype
+        //
+        scanProperties(dataType.getProperties(), matchables, callback);
+    }
+
+    /**
+     * isPrimitive.
+     *
+     * @param type String containing type
+     * @return true if it is a primitive
+     */
+    public static boolean isPrimitive(@NonNull String type) {
+        return mapPrimitivesProperty.containsKey(type);
+    }
+
+    /**
+     * isMatchable - scans metadata for matchable field set to true.
+     *
+     * @param property ToscaProperty object
+     * @return true if matchable
+     */
+    public static boolean isMatchable(@NonNull ToscaProperty property) {
+        if (property.getMetadata() == null) {
+            return false;
+        }
+        String isMatchable = property.getMetadata().get("matchable");
+        if (isMatchable == null) {
+            return false;
+        }
+        return "true".equalsIgnoreCase(isMatchable);
+    }
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchableProperty.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchableProperty.java
new file mode 100644 (file)
index 0000000..9b5de5c
--- /dev/null
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import lombok.Data;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+@Data
+@RequiredArgsConstructor
+public class MatchableProperty {
+    @NonNull
+    String property;
+    @NonNull
+    MatchablePropertyType<?> type;
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyType.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyType.java
new file mode 100644 (file)
index 0000000..8f910c4
--- /dev/null
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import com.att.research.xacml.api.Identifier;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
+
+public interface MatchablePropertyType<T> {
+
+    public T validate(Object value) throws ToscaPolicyConversionException;
+
+    public Object generate(Object value, Identifier attributeId) throws ToscaPolicyConversionException;
+
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeBase.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeBase.java
new file mode 100644 (file)
index 0000000..f93f8a3
--- /dev/null
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import lombok.Getter;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntrySchema;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
+
+@Getter
+public abstract class MatchablePropertyTypeBase<T> implements MatchablePropertyType<T> {
+    private ToscaProperty toscaProperty;
+    private ToscaEntrySchema toscaSchema;
+
+    public MatchablePropertyTypeBase(ToscaProperty inProperty) {
+        this.toscaProperty = inProperty;
+    }
+
+    public MatchablePropertyTypeBase(ToscaEntrySchema inSchema) {
+        this.toscaSchema = inSchema;
+    }
+
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeBoolean.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeBoolean.java
new file mode 100644 (file)
index 0000000..d3b16c2
--- /dev/null
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.XACML3;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntrySchema;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
+
+public class MatchablePropertyTypeBoolean extends MatchablePropertyTypeBase<Boolean> {
+
+    public MatchablePropertyTypeBoolean(ToscaProperty inProperty) {
+        super(inProperty);
+    }
+
+    public MatchablePropertyTypeBoolean(ToscaEntrySchema toscaSchema) {
+        super(toscaSchema);
+    }
+
+    @Override
+    public Boolean validate(Object value) throws ToscaPolicyConversionException {
+        if (value instanceof Boolean) {
+            return (Boolean) value;
+        }
+        return Boolean.parseBoolean(value.toString());
+    }
+
+    @Override
+    public Object generate(Object value, Identifier attributeId)
+            throws ToscaPolicyConversionException {
+        return ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
+                XACML3.ID_FUNCTION_BOOLEAN_EQUAL,
+                validate(value).toString(),
+                XACML3.ID_DATATYPE_BOOLEAN,
+                attributeId,
+                XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
+    }
+
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeFloat.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeFloat.java
new file mode 100644 (file)
index 0000000..5231ca6
--- /dev/null
@@ -0,0 +1,68 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.XACML3;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntrySchema;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
+
+public class MatchablePropertyTypeFloat extends MatchablePropertyTypeBase<Float> {
+
+    public MatchablePropertyTypeFloat(ToscaProperty inProperty) {
+        super(inProperty);
+    }
+
+    public MatchablePropertyTypeFloat(ToscaEntrySchema toscaSchema) {
+        super(toscaSchema);
+    }
+
+    @Override
+    public Float validate(Object value) throws ToscaPolicyConversionException {
+        //
+        // Most likely it isn't because Gson does not recognize floats
+        //
+        if (value instanceof Float) {
+            return (Float) value;
+        }
+        try {
+            return Float.parseFloat(value.toString());
+        } catch (NumberFormatException e) {
+            throw new ToscaPolicyConversionException("Bad float value" + value.toString(), e);
+        }
+    }
+
+    @Override
+    public Object generate(Object value, Identifier attributeId)
+            throws ToscaPolicyConversionException {
+        return ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
+                XACML3.ID_FUNCTION_INTEGER_EQUAL,
+                validate(value).toString(),
+                XACML3.ID_DATATYPE_INTEGER,
+                attributeId,
+                XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
+    }
+
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeInteger.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeInteger.java
new file mode 100644 (file)
index 0000000..ea798a5
--- /dev/null
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.XACML3;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntrySchema;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
+
+public class MatchablePropertyTypeInteger extends MatchablePropertyTypeBase<Integer> {
+
+    public MatchablePropertyTypeInteger(ToscaProperty inProperty) {
+        super(inProperty);
+    }
+
+    public MatchablePropertyTypeInteger(ToscaEntrySchema toscaSchema) {
+        super(toscaSchema);
+    }
+
+    @Override
+    public Integer validate(Object value) throws ToscaPolicyConversionException {
+        if (value instanceof Integer) {
+            return (Integer) value;
+        }
+        try {
+            return Integer.valueOf(value.toString());
+        } catch (NumberFormatException e) {
+            throw new ToscaPolicyConversionException("Bad integer value" + value.toString(), e);
+        }
+    }
+
+    @Override
+    public Object generate(Object value, Identifier attributeId) throws ToscaPolicyConversionException {
+        return ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
+                XACML3.ID_FUNCTION_INTEGER_EQUAL,
+                validate(value).toString(),
+                XACML3.ID_DATATYPE_INTEGER,
+                attributeId,
+                XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
+    }
+
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeList.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeList.java
new file mode 100644 (file)
index 0000000..55fea54
--- /dev/null
@@ -0,0 +1,73 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import com.att.research.xacml.api.Identifier;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntrySchema;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
+
+public class MatchablePropertyTypeList extends MatchablePropertyTypeBase<List<MatchablePropertyType<?>>> {
+    MatchableProperty primitiveProperty;
+
+    /**
+     * constructor.
+     *
+     * @param toscaProperty ToscaProperty object
+     */
+    public MatchablePropertyTypeList(ToscaProperty toscaProperty) {
+        super(toscaProperty);
+
+        ToscaEntrySchema schema = toscaProperty.getEntrySchema();
+        this.primitiveProperty = MatchablePolicyType.handlePrimitive(schema.getType(), schema);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<MatchablePropertyType<?>> validate(Object value) throws ToscaPolicyConversionException {
+        if (value instanceof Collection) {
+            return (List<MatchablePropertyType<?>>) value;
+        }
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Object generate(Object value, Identifier attributeId)
+            throws ToscaPolicyConversionException {
+        AnyOfType anyOf = null;
+        for (Object val : this.validate(value)) {
+            //
+            // Build the AnyOfType
+            //
+            anyOf = ToscaPolicyTranslatorUtils.buildAndAppendAllof(anyOf,
+                    primitiveProperty.getType().generate(val, attributeId));
+        }
+        return anyOf;
+    }
+
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeMap.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeMap.java
new file mode 100644 (file)
index 0000000..d5083e1
--- /dev/null
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.std.IdentifierImpl;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
+import lombok.NonNull;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntrySchema;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
+
+public class MatchablePropertyTypeMap extends MatchablePropertyTypeBase<Map<String, MatchablePropertyType<?>>> {
+    MatchableProperty primitiveProperty;
+
+    /**
+     * constructor.
+     *
+     * @param toscaProperty ToscaProperty object
+     */
+    public MatchablePropertyTypeMap(@NonNull ToscaProperty toscaProperty) {
+        super(toscaProperty);
+
+        ToscaEntrySchema schema = toscaProperty.getEntrySchema();
+        this.primitiveProperty = MatchablePolicyType.handlePrimitive(schema.getType(), schema);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Map<String, MatchablePropertyType<?>> validate(Object value) throws ToscaPolicyConversionException {
+        if (value instanceof Map) {
+            return (Map<String, MatchablePropertyType<?>>) value;
+        }
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Object generate(Object value, Identifier attributeId) throws ToscaPolicyConversionException {
+        AnyOfType anyOf = new AnyOfType();
+        for (Entry<String, MatchablePropertyType<?>> entrySet : this.validate(value).entrySet()) {
+            final String id = entrySet.getKey();
+            final Object val = entrySet.getValue();
+            //
+            // For map we use the LHS as part of the attribute id
+            //
+            Identifier newId = new IdentifierImpl(attributeId + ":" + id);
+            //
+            // Build the AnyOfType
+            //
+            anyOf = ToscaPolicyTranslatorUtils.buildAndAppendAllof(anyOf,
+                    primitiveProperty.getType().generate(val, newId));
+        }
+        return anyOf;
+    }
+
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeString.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeString.java
new file mode 100644 (file)
index 0000000..4605b84
--- /dev/null
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.XACML3;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntrySchema;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
+
+public class MatchablePropertyTypeString extends MatchablePropertyTypeBase<String> {
+
+    public MatchablePropertyTypeString(ToscaProperty toscaProperty) {
+        super(toscaProperty);
+    }
+
+    public MatchablePropertyTypeString(ToscaEntrySchema toscaSchema) {
+        super(toscaSchema);
+    }
+
+    @Override
+    public String validate(Object value) {
+        //
+        // Future we could do constraint validation
+        //
+        return value.toString();
+    }
+
+    @Override
+    public Object generate(Object value, Identifier attributeId) {
+        return ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
+                XACML3.ID_FUNCTION_STRING_EQUAL,
+                validate(value),
+                XACML3.ID_DATATYPE_STRING,
+                attributeId,
+                XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
+    }
+
+
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeTimestamp.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeTimestamp.java
new file mode 100644 (file)
index 0000000..d24147c
--- /dev/null
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.XACML3;
+import com.att.research.xacml.std.datatypes.ISO8601DateTime;
+import java.text.ParseException;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntrySchema;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
+
+public class MatchablePropertyTypeTimestamp extends MatchablePropertyTypeBase<ISO8601DateTime> {
+
+    public MatchablePropertyTypeTimestamp(ToscaProperty inProperty) {
+        super(inProperty);
+    }
+
+    public MatchablePropertyTypeTimestamp(ToscaEntrySchema toscaSchema) {
+        super(toscaSchema);
+    }
+
+    @Override
+    public ISO8601DateTime validate(Object value) throws ToscaPolicyConversionException {
+        try {
+            return ISO8601DateTime.fromISO8601DateTimeString(value.toString());
+        } catch (ParseException e) {
+            throw new ToscaPolicyConversionException("bad ISO8601 timevalue " + value.toString(), e);
+        }
+    }
+
+    @Override
+    public Object generate(Object value, Identifier attributeId)
+            throws ToscaPolicyConversionException {
+        return ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
+                XACML3.ID_FUNCTION_DATETIME_EQUAL,
+                validate(value).toString(),
+                XACML3.ID_DATATYPE_DATETIME,
+                attributeId,
+                XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
+    }
+
+}
index 690b710..11a45e0 100644 (file)
@@ -35,7 +35,6 @@ import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -44,9 +43,9 @@ 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;
@@ -61,8 +60,8 @@ 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;
@@ -70,6 +69,9 @@ 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;
 
@@ -80,16 +82,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 static final String MSG_WEIGHT = "Weight is {}";
-    private static final String MSG_WEIGHT_LIST = "Weight list is {}";
-    private static final String MSG_WEIGHT_MAP = "Weight map is {}";
-
     private final Map<ToscaPolicyTypeIdentifier, ToscaServiceTemplate> matchablePolicyTypes = new HashMap<>();
+    private final Map<ToscaPolicyTypeIdentifier, MatchablePolicyType> matchableCache = new HashMap<>();
+
     @Setter
     private RestServerParameters apiRestParameters;
     @Setter
@@ -322,6 +322,50 @@ public class StdMatchableTranslator  extends StdBaseTranslator {
         return newPolicyType;
     }
 
+    @Override
+    public ToscaPolicyType retrievePolicyType(String derivedFrom) {
+        ToscaServiceTemplate template = this.findPolicyType(new ToscaPolicyTypeIdentifier(derivedFrom, "1.0.0"));
+        if (template == null) {
+            LOGGER.error("Could not retrieve Policy Type {}", derivedFrom);
+            return null;
+        }
+        return template.getPolicyTypes().get(derivedFrom);
+    }
+
+    @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;
+    }
+
+    private class MyMatchableCallback implements MatchableCallback {
+        private StdMatchableTranslator translator;
+        private ToscaServiceTemplate template;
+
+        public MyMatchableCallback(StdMatchableTranslator translator, ToscaServiceTemplate template) {
+            this.translator = translator;
+            this.template = template;
+        }
+
+        @Override
+        public ToscaPolicyType retrievePolicyType(String derivedFrom) {
+            ToscaPolicyType policyType = this.template.getPolicyTypes().get(derivedFrom);
+            if (policyType != null) {
+                return policyType;
+            }
+            return translator.retrievePolicyType(derivedFrom);
+        }
+
+        @Override
+        public ToscaDataType retrieveDataType(String datatype) {
+            return this.template.getDataTypes().get(datatype);
+        }
+
+    }
+
     /**
      * For generating target type, we scan for matchable properties
      * and use those to build the policy.
@@ -330,496 +374,100 @@ public class StdMatchableTranslator  extends StdBaseTranslator {
      * @param policyTypes Collection of policy Type to find matchable metadata
      * @return {@code Pair<TargetType, Integer>} Returns a TargetType and a Total Weight of matchables.
      */
-    protected Pair<TargetType, Integer> generateTargetType(ToscaPolicy policyType,
-            ToscaServiceTemplate policyTemplate) {
+    protected Pair<TargetType, Integer> generateTargetType(ToscaPolicy policy, ToscaServiceTemplate template) {
         //
         // Our return object
         //
-        TargetType targetType = new TargetType();
-        //
-        // Top-level list of properties
-        //
-        Map<String, Object> properties = policyType.getProperties();
+        TargetType target = new TargetType();
         //
-        // To start, we know these properties are for this specific Policy Type ID/Version
+        // See if we have a matchable in the cache already
         //
-        ToscaPolicyTypeIdentifier propertiesPolicyId = policyType.getTypeIdentifier();
+        MatchablePolicyType matchablePolicyType = matchableCache.get(policy.getTypeIdentifier());
         //
-        // Scan the property map for matchables
+        // If not found, create one
         //
-        int totalWeight = findMatchablesInProperties(properties, propertiesPolicyId, policyTemplate, targetType);
-        LOGGER.info("Total weight is {}", totalWeight);
-        return Pair.of(targetType, totalWeight);
-    }
-
-    protected int findMatchablesInProperties(Map<String, Object> properties,
-            ToscaPolicyTypeIdentifier propertiesPolicyId,
-            ToscaServiceTemplate policyTemplate,
-            TargetType targetType) {
-        LOGGER.info("findMatchablesInProperties from policy Type {} {}", propertiesPolicyId, properties);
-        //
-        // We better have the policy type definition available from the template
-        //
-        ToscaPolicyType policyType = getToscaPolicyTypeFromTemplate(propertiesPolicyId, policyTemplate);
-        if (policyType == null) {
-            LOGGER.error("Failed to find policy type in template {}", propertiesPolicyId);
-            return 0;
-        }
-        //
-        // Our total weight to return
-        //
-        int totalWeight = 0;
-        for (Entry<String, Object> entrySet : properties.entrySet()) {
+        if (matchablePolicyType == null) {
             //
-            // Find the property details
+            // Our callback
             //
-            Pair<ToscaProperty, ToscaServiceTemplate> property = findProperty(entrySet.getKey(),
-                    policyType, propertiesPolicyId, policyTemplate);
-            if (property == null) {
-                continue;
-            }
-            ToscaProperty toscaProperty = property.getLeft();
-            LOGGER.info("Found property {} with type {} schema {}", entrySet.getKey(), toscaProperty.getType(),
-                    (toscaProperty.getEntrySchema() == null ? "null" : toscaProperty.getEntrySchema().getType()));
+            MyMatchableCallback myCallback = new MyMatchableCallback(this, template);
             //
-            // Is it matchable?
+            // Create the matchable
             //
-            if (checkIsMatchableProperty(toscaProperty)) {
-                //
-                // This will generate the matchables for the property
-                //
-                int weight = generateMatchable(targetType, entrySet.getKey(), entrySet.getValue(),
-                        property.getLeft(), property.getRight());
-                LOGGER.info(MSG_WEIGHT, weight);
-                totalWeight += weight;
-            } else {
-                //
-                // Not matchable, but we need to check if this contains list or map of datatypes.
-                // Those will need to be searched for matchables.
-                //
-                if ("list".equals(toscaProperty.getType())) {
-                    int weight = findMatchablesInList(entrySet.getKey(), entrySet.getValue(), toscaProperty,
-                            policyTemplate, targetType);
-                    LOGGER.info(MSG_WEIGHT_LIST, weight);
-                    totalWeight += weight;
-                } else if ("map".equals(toscaProperty.getType())) {
-                    int weight = findMatchablesInMap(entrySet.getKey(), entrySet.getValue(), toscaProperty,
-                            policyTemplate, targetType);
-                    LOGGER.info(MSG_WEIGHT_MAP, weight);
-                    totalWeight += weight;
-                }
-            }
-        }
-        return totalWeight;
-    }
-
-    @SuppressWarnings("unchecked")
-    protected int findMatchablesInList(String listPropertyName, Object listValue, ToscaProperty listProperty,
-            ToscaServiceTemplate listTemplate, TargetType targetType) {
-        //
-        // Don't bother if there is no schema (which should be a problem) or
-        // its a list of primitives
-        //
-        if (listProperty.getEntrySchema() == null) {
-            LOGGER.error("No entry schema for list property {}", listPropertyName);
-            return 0;
-        }
-        //
-        // If they are primitives, then no need to go through them. ??
-        //
-        if (isYamlType(listProperty.getEntrySchema().getType())) {
-            LOGGER.info("list of primitives");
-            return 0;
-        }
-        //
-        // Find the datatype
-        //
-        ToscaDataType listDataType = listTemplate.getDataTypes().get(listProperty.getEntrySchema().getType());
-        if (listDataType == null) {
-            LOGGER.error("Unable to find datatype {}", listProperty.getEntrySchema().getType());
-            return 0;
-        }
-
-        int totalWeight = 0;
-        for (Object datatypeValue : ((Collection<Object>)listValue)) {
+            matchablePolicyType = new MatchablePolicyType(
+                    template.getPolicyTypes().get(policy.getType()), myCallback);
             //
-            // This should be a map - because this is a list of datatypes.
+            // Cache it
             //
-            if (! (datatypeValue instanceof Map)) {
-                LOGGER.error("datatype {} value is not a map {}", listDataType.getName(), datatypeValue.getClass());
-                continue;
-            }
-            for (Entry<String, Object> entrySet : ((Map<String, Object>)datatypeValue).entrySet()) {
-                ToscaProperty toscaProperty = listDataType.getProperties().get(entrySet.getKey());
-                if (toscaProperty == null) {
-                    LOGGER.error("Failed to find datatype {} property {}", listDataType.getName(), entrySet.getKey());
-                    continue;
-                }
-                LOGGER.info("Found list property {} with type {} schema {}", entrySet.getKey(), toscaProperty.getType(),
-                        (toscaProperty.getEntrySchema() == null ? "null" : toscaProperty.getEntrySchema().getType()));
-                //
-                // Is it matchable?
-                //
-                if (checkIsMatchableProperty(toscaProperty)) {
-                    //
-                    // This will generate the matchables for the property
-                    //
-                    int weight = generateMatchable(targetType, entrySet.getKey(), entrySet.getValue(),
-                            toscaProperty, listTemplate);
-                    LOGGER.info(MSG_WEIGHT, weight);
-                    totalWeight += weight;
-                } else {
-                    //
-                    // Not matchable, but we need to check if this contains list or map of datatypes.
-                    // Those will need to be searched for matchables.
-                    //
-                    if ("list".equals(toscaProperty.getType())) {
-                        int weight = findMatchablesInList(entrySet.getKey(), entrySet.getValue(), toscaProperty,
-                                listTemplate, targetType);
-                        LOGGER.info(MSG_WEIGHT_LIST, weight);
-                        totalWeight += weight;
-                    } else if ("map".equals(toscaProperty.getType())) {
-                        int weight = findMatchablesInMap(entrySet.getKey(), entrySet.getValue(), toscaProperty,
-                                listTemplate, targetType);
-                        LOGGER.info(MSG_WEIGHT_MAP, weight);
-                        totalWeight += weight;
-                    }
-                }
-            }
+            matchableCache.put(policy.getTypeIdentifier(), matchablePolicyType);
         }
-
-        return totalWeight;
-    }
-
-    @SuppressWarnings("unchecked")
-    protected int findMatchablesInMap(String mapPropertyName, Object mapValue, ToscaProperty mapProperty,
-            ToscaServiceTemplate mapTemplate, TargetType targetType) {
         //
-        // There needs to be a schema.
+        // Fill in the target type with potential matchables
         //
-        if (mapProperty.getEntrySchema() == null) {
-            LOGGER.error("No entry schema for map property {}", mapPropertyName);
-            return 0;
+        try {
+            fillTargetTypeWithMatchables(target, matchablePolicyType, policy.getProperties());
+        } catch (ToscaPolicyConversionException e) {
+            LOGGER.error("Could not generate target type", e);
         }
         //
-        // If they are primitives, then no need to go through them. ??
+        // 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
         //
-        if (isYamlType(mapProperty.getEntrySchema().getType())) {
-            LOGGER.debug("map property {} is primitives", mapPropertyName);
-            return 0;
-        }
+        int weight = calculateWeight(target);
+        LOGGER.debug("Weight is {} for policy {}", weight, policy.getName());
         //
-        // Find the datatype
+        // Assume the number of AllOf's is the weight for now
         //
-        ToscaDataType mapDataType = mapTemplate.getDataTypes().get(mapProperty.getEntrySchema().getType());
-        if (mapDataType == null) {
-            LOGGER.error("Unable to find datatype {}", mapProperty.getEntrySchema().getType());
-            return 0;
-        }
-
-        int totalWeight = 0;
-        for (Entry<String, Object> entrySet : ((Map<String, Object>)mapValue).entrySet()) {
-            ToscaProperty toscaProperty = mapDataType.getProperties().get(entrySet.getKey());
-            if (toscaProperty == null) {
-                LOGGER.error("Failed to find datatype {} property {}", mapDataType.getName(), entrySet.getKey());
-                continue;
-            }
-            LOGGER.info("Found map property {} with type {} schema {}", entrySet.getKey(), toscaProperty.getType(),
-                    (toscaProperty.getEntrySchema() == null ? "null" : toscaProperty.getEntrySchema().getType()));
-            //
-            // Is it matchable?
-            //
-            if (checkIsMatchableProperty(toscaProperty)) {
-                //
-                // This will generate the matchables for the property
-                //
-                int weight = generateMatchable(targetType, entrySet.getKey(), entrySet.getValue(),
-                        toscaProperty, mapTemplate);
-                LOGGER.info(MSG_WEIGHT, weight);
-                totalWeight += weight;
-            } else {
-                //
-                // Not matchable, but we need to check if this contains list or map of datatypes.
-                // Those will need to be searched for matchables.
-                //
-                if ("list".equals(toscaProperty.getType())) {
-                    int weight = findMatchablesInList(entrySet.getKey(), entrySet.getValue(), toscaProperty,
-                            mapTemplate, targetType);
-                    LOGGER.info(MSG_WEIGHT_LIST, weight);
-                    totalWeight += weight;
-                } else if ("map".equals(toscaProperty.getType())) {
-                    int weight = findMatchablesInMap(entrySet.getKey(), entrySet.getValue(), toscaProperty,
-                            mapTemplate, targetType);
-                    LOGGER.info(MSG_WEIGHT_MAP, weight);
-                    totalWeight += weight;
-                }
-            }
-        }
-
-        return totalWeight;
+        return Pair.of(target, weight);
     }
 
-    /**
-     * findMatchableProperty - Iterates through available TOSCA Policy Types and return the
-     * ToscaProperty and template for the property.
-     *
-     * @param propertyName Name of property
-     * @param policyTypes Collection of TOSCA Policy Types to scan
-     * @return ToscaProperty and ToscaServiceTemplate if matchable
-     */
-    protected Pair<ToscaProperty, ToscaServiceTemplate> findProperty(String propertyName,
-            ToscaPolicyType policyType, ToscaPolicyTypeIdentifier propertiesPolicyId,
-            ToscaServiceTemplate policyTemplate) {
-        //
-        // See if the property is defined by the policy template
-        //
-        ToscaProperty toscaProperty = policyType.getProperties().get(propertyName);
-        if (toscaProperty != null) {
-            //
-            // Does it contain the matchable property and if so its set to true?
-            //
-            return Pair.of(toscaProperty, policyTemplate);
-        }
-        LOGGER.debug("property {} is not in policy type {}", propertyName, propertiesPolicyId);
-        //
-        // Check its parent policy types
-        //
-        ToscaPolicyTypeIdentifier parentId = getParentDerivedFrom(propertiesPolicyId, policyTemplate);
-        while (parentId != null) {
-            LOGGER.debug("searching parent policy type {}", parentId);
-            //
-            // Search the existing template (should be there during runtime)
-            //
-            ToscaPolicyType parentPolicyType = getParentPolicyType(parentId, policyTemplate);
-            if (parentPolicyType != null) {
-                toscaProperty = parentPolicyType.getProperties().get(propertyName);
-                if (toscaProperty != null) {
-                    return Pair.of(toscaProperty, policyTemplate);
-                }
+    @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) {
                 //
-                // Move to the next parent
+                // Construct attribute id
                 //
-                parentId = getParentDerivedFrom(parentId, policyTemplate);
-            } else {
-                LOGGER.warn("Parent policy type is not found {}", parentId);
+                Identifier id = new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + propertyName);
                 //
-                // Find the parent policy type. During JUnit this may be in a separate
-                // file. We hope that during runtime the template is complete.
+                // Depending on what type it is, add it into the target
                 //
-                ToscaServiceTemplate parentTemplate = findPolicyType(parentId);
-                if (parentTemplate != null) {
-                    parentPolicyType = getParentPolicyType(parentId, parentTemplate);
-                    if (parentPolicyType != null) {
-                        toscaProperty = parentPolicyType.getProperties().get(propertyName);
-                        if (toscaProperty != null) {
-                            return Pair.of(toscaProperty, parentTemplate);
-                        }
-                    }
-                    //
-                    // Move to the next parent
-                    //
-                    parentId = getParentDerivedFrom(parentId, parentTemplate);
-                } else {
-                    LOGGER.error("Unable to find/pull parent policy type {}", parentId);
-                    parentId = null;
-                }
-            }
-        }
-        LOGGER.warn("Property {} is NOT found in any template", propertyName);
-        return null;
-    }
-
-    private ToscaPolicyType getToscaPolicyTypeFromTemplate(ToscaPolicyTypeIdentifier propertiesPolicyId,
-            ToscaServiceTemplate policyTemplate) {
-        for (Entry<String, ToscaPolicyType> entry : policyTemplate.getPolicyTypes().entrySet()) {
-            if (propertiesPolicyId.getName().equals(entry.getKey())
-                    && propertiesPolicyId.getVersion().equals(entry.getValue().getVersion())) {
-                return entry.getValue();
-            }
-        }
-        return null;
-    }
+                ToscaPolicyTranslatorUtils.buildAndAppendTarget(target,
+                        matchable.getType().generate(propertyValue, id));
 
-    private boolean isYamlType(String type) {
-        return "string".equalsIgnoreCase(type) || "integer".equalsIgnoreCase(type) || "float".equalsIgnoreCase(type)
-                || "boolean".equalsIgnoreCase(type) || "timestamp".equalsIgnoreCase(type);
-    }
-
-    /**
-     * checkIsMatchableProperty - checks the property metadata to see if matchable exists.
-     *
-     * @param toscaProperty ToscaProperty
-     * @return true if matchable
-     */
-    protected boolean checkIsMatchableProperty(ToscaProperty toscaProperty) {
-        if (toscaProperty.getMetadata() == null) {
-            return false;
-        }
-        for (Entry<String, String> entrySet : toscaProperty.getMetadata().entrySet()) {
-            if ("matchable".equals(entrySet.getKey()) && "true".equals(entrySet.getValue())) {
-                LOGGER.debug("found matchable of type {}", toscaProperty.getType());
-                return true;
+                continue;
             }
-        }
-        return false;
-    }
-
-    /**
-     * generateMatchable - Given the object, generates list of MatchType objects and add them
-     * 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
-     * @param toscaProperty The property that was found
-     * @param toscaServiceTemplate The template from which the property was found
-     * @return int Weight of the match.
-     */
-    protected int generateMatchable(TargetType targetType, String key, Object value, ToscaProperty toscaProperty,
-            ToscaServiceTemplate toscaServiceTemplate) {
-        int weight = 0;
-        if (value instanceof Collection) {
             //
-            // Further determine how we treat this collection. We will need the schema
-            // if it is not available then we have to bail.
+            // Here is the special case where we look for a Collection of values that may
+            // contain potential matchables
             //
-            if (toscaProperty.getEntrySchema() == null) {
-                LOGGER.error("No schema for property {} of type {}", key, toscaProperty.getType());
-            }
-            if ("list".equals(toscaProperty.getType())) {
-                return generateMatchableList(targetType, key, value, toscaProperty, toscaServiceTemplate);
-            }
-            if ("map".equals(toscaProperty.getType())) {
-                return generateMatchableMap(targetType, key, value, toscaProperty, toscaServiceTemplate);
-            }
-        } else {
-            AnyOfType anyOf = generateMatches(Arrays.asList(value),
-                    new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key));
-            if (! anyOf.getAllOf().isEmpty()) {
-                targetType.getAnyOf().add(anyOf);
-                weight = 1;
+            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);
             }
         }
-        return weight;
     }
 
-    @SuppressWarnings("unchecked")
-    protected int generateMatchableList(TargetType targetType, String key, Object value, ToscaProperty toscaProperty,
-            ToscaServiceTemplate toscaServiceTemplate) {
+    protected int calculateWeight(TargetType target) {
         int weight = 0;
-        if (isYamlType(toscaProperty.getEntrySchema().getType())) {
-            AnyOfType anyOf = generateMatches((Collection<Object>) value,
-                    new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key));
-            if (! anyOf.getAllOf().isEmpty()) {
-                targetType.getAnyOf().add(anyOf);
-                weight = 1;
+        for (AnyOfType anyOf : target.getAnyOf()) {
+            for (AllOfType allOf : anyOf.getAllOf()) {
+                weight += allOf.getMatch().size();
             }
-        } else {
-            LOGGER.debug("PLD use datatype for list?");
         }
-        return weight;
-    }
 
-    @SuppressWarnings("unchecked")
-    protected int generateMatchableMap(TargetType targetType, String key, Object value, ToscaProperty toscaProperty,
-            ToscaServiceTemplate toscaServiceTemplate) {
-        int weight = 0;
-        if (isYamlType(toscaProperty.getEntrySchema().getType())) {
-            //
-            // PLD TODO - this won't work. Right now there are no maps being used to match.
-            // need to investigate whether we really can support that situation.
-            //
-            AnyOfType anyOf = generateMatches((Collection<Object>) value,
-                    new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + key));
-            if (! anyOf.getAllOf().isEmpty()) {
-                targetType.getAnyOf().add(anyOf);
-                weight = 1;
-            }
-        } else {
-            LOGGER.debug("PLD use datatype for map?");
-        }
         return weight;
     }
 
-    /**
-     * 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.
-     *
-     * @param matchables Collection of object to generate MatchType from
-     * @param attributeId Given attribute Id for each MatchType
-     * @return AnyOfType object
-     */
-    protected AnyOfType generateMatches(Collection<Object> matchables, Identifier attributeId) {
-        //
-        // This is our outer AnyOf - which is an OR
-        //
-        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
-            //
-            // We should add datetime support. But to do that we need
-            // probably more metadata to describe how that would be translated.
-            //
-            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;
-            }
-            //
-            // Create a match for this
-            //
-            MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
-                    idFunction,
-                    matchable.toString(),
-                    idDatatype,
-                    attributeId,
-                    XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
-            //
-            // Now create an anyOf (OR)
-            //
-            anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(match));
-        }
-        return anyOf;
-    }
-
-    private ToscaPolicyTypeIdentifier getParentDerivedFrom(ToscaPolicyTypeIdentifier policyTypeId,
-            ToscaServiceTemplate template) {
-        for (Entry<String, ToscaPolicyType> entrySet : template.getPolicyTypes().entrySet()) {
-            ToscaPolicyType policyType = entrySet.getValue();
-            if (entrySet.getKey().equals(policyTypeId.getName())
-                    && policyType.getVersion().equals(policyTypeId.getVersion())
-                    && ! "tosca.policies.Root".equals(policyType.getDerivedFrom())) {
-                return new ToscaPolicyTypeIdentifier(policyType.getDerivedFrom(), "1.0.0");
-            }
-        }
-
-        return null;
-    }
-
-    private ToscaPolicyType getParentPolicyType(ToscaPolicyTypeIdentifier policyTypeId, ToscaServiceTemplate template) {
-        for (Entry<String, ToscaPolicyType> entrySet : template.getPolicyTypes().entrySet()) {
-            ToscaPolicyType policyType = entrySet.getValue();
-            if (entrySet.getKey().equals(policyTypeId.getName())
-                    && policyType.getVersion().equals(policyTypeId.getVersion())) {
-                return policyType;
-            }
-        }
-        return null;
-    }
-
     /**
      * findPolicyType - given the ToscaPolicyTypeIdentifier, finds it in memory, or
      * then tries to find it either locally on disk or pull it from the Policy
@@ -889,8 +537,17 @@ public class StdMatchableTranslator  extends StdBaseTranslator {
         //
         LOGGER.info("Read in local policy type {}", policyTypePath.toAbsolutePath());
         try {
-            return standardYamlCoder.decode(new String(bytes, StandardCharsets.UTF_8),
+            //
+            // Decode the template
+            //
+            ToscaServiceTemplate template = standardYamlCoder.decode(new String(bytes, StandardCharsets.UTF_8),
                     ToscaServiceTemplate.class);
+            //
+            // Ensure all the fields are setup correctly
+            //
+            JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
+            jtst.fromAuthorative(template);
+            return jtst.toAuthorative();
         } catch (CoderException e) {
             LOGGER.error("Failed to decode tosca template for {}", policyTypePath, e);
         }
index 8b85a0d..5d451e2 100644 (file)
@@ -27,7 +27,10 @@ import static org.junit.Assert.assertTrue;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Modifier;
-
+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.MatchType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
 import org.junit.Test;
 
 public class ToscaPolicyTranslatorUtilsTest {
@@ -45,4 +48,24 @@ public class ToscaPolicyTranslatorUtilsTest {
         assertThat(ToscaPolicyTranslatorUtils.generateTimeInRange("T00:00:00Z", "T08:00:00Z")).isNotNull();
     }
 
+    @Test
+    public void testBuildAndAppend() {
+        assertThat(ToscaPolicyTranslatorUtils.buildAndAppendAllof(null, new MatchType())).isInstanceOf(AnyOfType.class);
+        assertThat(ToscaPolicyTranslatorUtils.buildAndAppendAllof(null, new AllOfType())).isInstanceOf(AnyOfType.class);
+        assertThat(ToscaPolicyTranslatorUtils.buildAndAppendAllof(null, new String())).isNull();
+
+        assertThat(ToscaPolicyTranslatorUtils.buildAndAppendTarget(new TargetType(),
+                new AnyOfType()).getAnyOf()).hasSize(1);
+        assertThat(ToscaPolicyTranslatorUtils.buildAndAppendTarget(new TargetType(),
+                new MatchType()).getAnyOf()).hasSize(1);
+        assertThat(ToscaPolicyTranslatorUtils.buildAndAppendTarget(new TargetType(),
+                new String()).getAnyOf()).isEmpty();
+    }
+
+    @Test
+    public void testInteger() {
+        assertThat(ToscaPolicyTranslatorUtils.parseInteger("foo")).isNull();
+        assertThat(ToscaPolicyTranslatorUtils.parseInteger("1")).isEqualTo(1);
+        assertThat(ToscaPolicyTranslatorUtils.parseInteger("1.0")).isEqualTo(1);
+    }
 }
diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePolicyTypeTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePolicyTypeTest.java
new file mode 100644 (file)
index 0000000..c23f702
--- /dev/null
@@ -0,0 +1,300 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.matchable;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.XACML3;
+import com.att.research.xacml.std.IdentifierImpl;
+import com.att.research.xacml.util.XACMLPolicyWriter;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+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.MatchType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardYamlCoder;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntrySchema;
+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.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.ToscaDictionary;
+import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MatchablePolicyTypeTest implements MatchableCallback {
+    private static final Logger LOGGER = LoggerFactory.getLogger(MatchablePolicyTypeTest.class);
+    private static final StandardYamlCoder yamlCoder = new StandardYamlCoder();
+    private static final String TEST_POLICYTYPE_FILE = "src/test/resources/matchable/onap.policies.Test-1.0.0.yaml";
+    private static final String TEST_POLICY_FILE = "src/test/resources/matchable/test.policies.input.tosca.yaml";
+    private static final String TEST_POLICYTYPE = "onap.policies.base.middle.Test";
+    private static ToscaServiceTemplate testTemplate;
+    private static ToscaPolicy testPolicy;
+
+    /**
+     * Loads our resources.
+     *
+     * @throws CoderException object
+     */
+    @BeforeClass
+    public static void setupLoadPolicy() throws CoderException {
+        //
+        // Load our test policy type
+        //
+        String policyType = ResourceUtils.getResourceAsString(TEST_POLICYTYPE_FILE);
+        //
+        // Serialize it into a class
+        //
+        ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyType, ToscaServiceTemplate.class);
+        //
+        // Make sure all the fields are setup properly
+        //
+        JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
+        jtst.fromAuthorative(serviceTemplate);
+        testTemplate = jtst.toAuthorative();
+        //
+        // Make sure the Policy Types are there
+        //
+        assertEquals(3, testTemplate.getPolicyTypes().size());
+        assertNotNull(testTemplate.getPolicyTypes().get("onap.policies.Base"));
+        assertNotNull(testTemplate.getPolicyTypes().get("onap.policies.base.Middle"));
+        assertNotNull(testTemplate.getPolicyTypes().get(TEST_POLICYTYPE));
+        //
+        // Load our test policy
+        //
+        String policy = ResourceUtils.getResourceAsString(TEST_POLICY_FILE);
+        //
+        // Serialize it into a class
+        //
+        serviceTemplate = yamlCoder.decode(policy, ToscaServiceTemplate.class);
+        //
+        // Make sure all the fields are setup properly
+        //
+        jtst = new JpaToscaServiceTemplate();
+        jtst.fromAuthorative(serviceTemplate);
+        ToscaServiceTemplate policyTemplate = jtst.toAuthorative();
+        assertEquals(1, policyTemplate.getToscaTopologyTemplate().getPolicies().size());
+        testPolicy = policyTemplate.getToscaTopologyTemplate().getPolicies().get(0).get("Test.policy");
+        assertNotNull(testPolicy);
+    }
+
+    @Test
+    public void testAllCodeCoverage() {
+        assertThatExceptionOfType(NullPointerException.class).isThrownBy(() ->
+            new MatchablePolicyType(null, null));
+
+        assertThatExceptionOfType(NullPointerException.class).isThrownBy(() ->
+            new MatchablePropertyTypeMap(null));
+        assertThatExceptionOfType(NullPointerException.class).isThrownBy(() ->
+            MatchablePolicyType.isMatchable(null));
+        assertThat(MatchablePolicyType.isMatchable(new ToscaProperty())).isFalse();
+        //
+        // Unlikely these would be called - just get code coverage on them
+        //
+        ToscaEntrySchema schema = new ToscaEntrySchema();
+        schema.setType("integer");
+        assertThat(MatchablePolicyType.handlePrimitive("foo", schema)).isNotNull();
+        schema.setType("float");
+        assertThat(MatchablePolicyType.handlePrimitive("foo", schema)).isNotNull();
+        schema.setType("boolean");
+        assertThat(MatchablePolicyType.handlePrimitive("foo", schema)).isNotNull();
+        schema.setType("timestamp");
+        assertThat(MatchablePolicyType.handlePrimitive("foo", schema)).isNotNull();
+        schema.setType("footype");
+        assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
+            MatchablePolicyType.handlePrimitive("foo", schema)
+        );
+        assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
+            MatchablePolicyType.handlePrimitive("foo", schema)
+        );
+        ToscaProperty toscaProperty = new ToscaProperty();
+        Map<String, String> metadata = new HashMap<>();
+        metadata.put("matchable", "true");
+        toscaProperty.setMetadata(metadata);
+        toscaProperty.setType("garbage");
+        assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
+            MatchablePolicyType.handlePrimitive("foo", toscaProperty)
+        );
+        Map<String, MatchableProperty> matchables = null;
+        assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
+            MatchablePolicyType.handleList("foo", toscaProperty, matchables, this)
+        );
+        assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
+            MatchablePolicyType.handleMap("foo", toscaProperty, matchables, this)
+        );
+    }
+
+    @Test
+    public void testPrimitiveValidation() throws Exception {
+        ToscaProperty property = new ToscaProperty();
+        MatchablePropertyTypeBoolean booleanValue = new MatchablePropertyTypeBoolean(property);
+        assertThat(booleanValue.validate(Boolean.TRUE)).isEqualTo(Boolean.TRUE);
+        assertThat(booleanValue.validate("no")).isEqualTo(Boolean.FALSE);
+        assertThat(booleanValue.validate("foo")).isEqualTo(Boolean.FALSE);
+
+        MatchablePropertyTypeInteger integerValue = new MatchablePropertyTypeInteger(property);
+        assertThat(integerValue.validate("5")).isEqualTo(5);
+        assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> integerValue.validate("foo"));
+
+        MatchablePropertyTypeFloat floatValue = new MatchablePropertyTypeFloat(property);
+        assertThat(floatValue.validate("5")).isEqualTo(5);
+        assertThat(floatValue.validate(Float.MIN_NORMAL)).isEqualTo(Float.MIN_NORMAL);
+        assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> floatValue.validate("foo"));
+
+        MatchablePropertyTypeTimestamp timestampValue = new MatchablePropertyTypeTimestamp(property);
+        assertThat(timestampValue.validate("2018-10-11T22:12:44").getHour()).isEqualTo(22);
+        assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
+            timestampValue.validate("foo"));
+
+        ToscaEntrySchema schema = new ToscaEntrySchema();
+        schema.setType("string");
+        property.setEntrySchema(schema);
+        MatchablePropertyTypeMap mapValue = new MatchablePropertyTypeMap(property);
+        assertThat(mapValue.validate(new String("foo"))).hasSize(0);
+
+        MatchablePropertyTypeList listValue = new MatchablePropertyTypeList(property);
+        assertThat(listValue.validate(new String("foo"))).hasSize(0);
+    }
+
+    @Test
+    public void testMatchables() throws ToscaPolicyConversionException {
+        //
+        // Step 1: Create matchables from the PolicyType
+        //
+        MatchablePolicyType matchablePolicyType = new MatchablePolicyType(testTemplate.getPolicyTypes()
+                .get(TEST_POLICYTYPE), this);
+        assertThat(matchablePolicyType).isNotNull();
+        assertThat(matchablePolicyType.getPolicyId()).isNotNull();
+        assertThat(matchablePolicyType.getPolicyId().getName()).isEqualTo(TEST_POLICYTYPE);
+        //
+        // Dump them out to see what we have
+        //
+        matchablePolicyType.getMatchables().forEach((matchable, property) -> {
+            LOGGER.info("matchable: {}: {}", matchable, property);
+        });
+        //
+        // Sanity check - these are the total possible match types available
+        //
+        assertThat(matchablePolicyType.getMatchables()).hasSize(19);
+        //
+        // Step 2) Go through example policy and generate data for our Target
+        //
+        final TargetType target = new TargetType();
+        target.getAnyOf().add(new AnyOfType());
+        generateTargetType(target, matchablePolicyType, testPolicy.getProperties());
+        //
+        // Stuff results in a simple Policy
+        //
+        final PolicyType policy = new PolicyType();
+        policy.setTarget(target);
+        policy.setPolicyId("foo");
+        policy.setVersion("1");
+        policy.setRuleCombiningAlgId(XACML3.DENY_UNLESS_PERMIT);
+        //
+        // Dump it out so we can see what was created
+        //
+        try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
+            XACMLPolicyWriter.writePolicyFile(os, policy);
+            LOGGER.info("{}", os);
+        } catch (IOException e) {
+            LOGGER.error("Failed to create byte array stream", e);
+        }
+        //
+        // Sanity check - the example policy should have each possible match type plus
+        // an extra one for the list and an extra one for the map.
+        //
+        assertThat(policy.getTarget().getAnyOf()).hasSize(20);
+    }
+
+    @Override
+    public ToscaPolicyType retrievePolicyType(String derivedFrom) {
+        for (Entry<String, ToscaPolicyType> entrySet : testTemplate.getPolicyTypes().entrySet()) {
+            if (entrySet.getValue().getName().equals(derivedFrom)) {
+                return entrySet.getValue();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public ToscaDataType retrieveDataType(String datatype) {
+        return testTemplate.getDataTypes().get(datatype);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void generateTargetType(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) {
+                Identifier id = new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + propertyName);
+                Object object = matchable.getType().generate(propertyValue, id);
+                //
+                // Depending on what type it is, add it into the target
+                //
+                if (object instanceof AnyOfType) {
+                    target.getAnyOf().add((AnyOfType) object);
+                } else if (object instanceof MatchType) {
+                    AllOfType allOf = new AllOfType();
+                    allOf.getMatch().add((MatchType) object);
+                    AnyOfType anyOf = new AnyOfType();
+                    anyOf.getAllOf().add(allOf);
+                    target.getAnyOf().add(anyOf);
+                }
+            } else {
+                //
+                // Here is the special case where we look for a Collection of values that may
+                // contain potential matchables
+                //
+                if (propertyValue instanceof List) {
+                    for (Object listValue : ((List<?>)propertyValue)) {
+                        if (listValue instanceof Map) {
+                            generateTargetType(target, matchablePolicyType, (Map<String, Object>) listValue);
+                        }
+                    }
+                } else if (propertyValue instanceof Map) {
+                    generateTargetType(target, matchablePolicyType, (Map<String, Object>) propertyValue);
+                }
+            }
+        }
+    }
+}
index 584390c..1de1d79 100644 (file)
@@ -160,7 +160,7 @@ public class StdMatchableTranslatorTest {
     }
 
     @Test
-    public void test() throws CoderException, ToscaPolicyConversionException, ParseException {
+    public void testMatchableTranslator() throws CoderException, ToscaPolicyConversionException, ParseException {
         //
         // Create our translator
         //
index 7179c31..f0737b5 100644 (file)
@@ -1,4 +1,4 @@
-tosca_definitions_version: tosca_simple_yaml_1_0_0
+tosca_definitions_version: tosca_simple_yaml_1_1_0
 policy_types:
     onap.policies.Base:
         derived_from: tosca.policies.Root
@@ -12,6 +12,7 @@ policy_types:
                    matchable: true
     onap.policies.base.Middle:
         derived_from: onap.policies.Base
+        type_version: 1.0.0
         version: 1.0.0
         properties:
             middleNoMatch:
@@ -25,47 +26,110 @@ policy_types:
         type_version: 1.0.0
         version: 1.0.0
         properties:
-            nonmatachableString:
+            nonmatchableString:
                 type: string
             matchableString:
                 type: string
                 metadata:
                    matchable: true
-            nonmatachableInteger:
+            nonmatchableInteger:
                 type: integer
                 metadata:
                    matchable: false
-            matachableInteger:
+            matchableInteger:
                 type: integer
                 metadata:
                    matchable: true
-            nonmatachableFloat:
+            nonmatchableFloat:
                 type: float
             matchableFloat:
                 type: float
                 metadata:
                    matchable: true
-            nonmatachableBoolean:
+            nonmatchableBoolean:
                 type: boolean
-            matachableBoolean:
+            matchableBoolean:
                 type: boolean
                 metadata:
                    matchable: true
+            nonmatchableTimestamp:
+                type: timestamp
+            matchableTimestamp:
+                type: timestamp
+                metadata:
+                   matchable: true
             nonmatchableListInteger:
                 type: list
                 entry_schema:
                    type: integer
             matchableListString:
                 type: list
+                description: |
+                    Every entry in the list is matchable, the attribute id will be the same for all value. eg. the
+                    property name.
                 metadata:
                    matchable: true
                 entry_schema:
                    type: string
-            propertyOneMap:
+            matchableMapString:
+               type: map
+               description: |
+                   Every entry in the map is matchable, however the attribute id will be set by the key.
+               metadata:
+                  matchable: true
+               entry_schema:
+                  type: string
+            nonmatchableMapString:
                 type: map
+                description: |
+                    Nothing gets matched - however you have no control over the LHS key. Someone could
+                    easily set that value to a matchable property name defined elsewhere.
                 entry_schema:
-                    type: onap.datatype.one
+                    type: string
+            badDataType:
+               type: i.do.not.exist
+               description: we can only ignore this - should get caught in the API
+            matchableDataType:
+               type: onap.datatype.zero
+               description: |
+                   The matchable field in a datatype must be IGNORED, because this will result in too many assumptions
+                   as we may go down many levels of datatypes, lists of datatypes, maps of datatypes, etc. Does every
+                   field in the datatype become matchable? That does not make sense right now to write a Policy Type
+                   like that.
+               metadata:
+                  matchable: true
 data_types:
+    onap.datatype.zero:
+        derived_from: tosca.datatypes.Root
+        description: Note that we do not have to declare matchable for each property.
+        properties:
+            zeroStringMatchable:
+                type: string
+                metadata:
+                    matchable: true
+            zeroBooleanMatchable:
+                type: boolean
+                metadata:
+                    matchable: true
+            zeroFloatMatchable:
+                type: float
+                metadata:
+                    matchable: true
+            zeroIntegerMatchable:
+                type: integer
+                metadata:
+                    matchable: true
+            zeroTimestampMatchable:
+                type: timestamp
+                metadata:
+                    matchable: true
+            zeroDatatypeOne:
+                type: onap.datatype.one
+            zeroBadDatatype:
+                type: list
+                description: we can only ignore this - should get caught in the API
+                entry_schema:
+                    type: another.missing.datatype
     onap.datatype.one:
         derived_from: tosca.datatypes.Root
         properties:
@@ -75,7 +139,7 @@ data_types:
                 type: string
                 metadata:
                     matchable: true
-            propertyTwoList:
+            propertyTwoListOfDatatype:
                 type: list
                 entry_schema:
                     type: onap.datatype.two
@@ -88,16 +152,22 @@ data_types:
                 type: string
                 metadata:
                     matchable: true
-            propertyThreeMap:
+            twoIntegerMatchable:
+                type: integer
+                metadata:
+                    matchable: true
+            propertyThreeDatatype:
                 type: map
                 entry_schema:
                     type: onap.datatype.three
     onap.datatype.three:
         derived_from: tosca.datatypes.Root
         properties:
-            threeString:
-                type: string
             threeStringMatchable:
                 type: string
+                metadata:
+                    matchable: true
+            threeIntegerMatchable:
+                type: integer
                 metadata:
                     matchable: true
\ No newline at end of file
index 80f72b2..daffc2c 100644 (file)
@@ -1,4 +1,4 @@
-tosca_definitions_version: tosca_simple_yaml_1_0_0
+tosca_definitions_version: tosca_simple_yaml_1_1_0
 topology_template:
     policies:
     -   Test.policy:
@@ -13,24 +13,38 @@ topology_template:
                 baseMatch: base Match
                 middleNoMatch: Do not match the middle
                 middleMatch: middle Match
-                nonmatachableString: I am NON matchable
+                nonmatchableString: I am NON matchable
                 matchableString: I should be matched
-                nonmatachableInteger: 0
-                matachableInteger: 1000
-                nonmatachableFloat: 0.0
+                nonmatchableInteger: 0
+                matchableInteger: 1000
+                nonmatchableFloat: 0.0
                 matchableFloat: 1.1
-                nonmatachableBoolean: false
-                matachableBoolean: true
+                nonmatchableBoolean: false
+                matchableBoolean: true
+                nonmatchableTimestamp: 2019-01-01T00:00:00Z
+                matchableTimestamp: 2020-01-01T00:00:00Z
                 nonmatchableListInteger: {0, 1, 2}
                 matchableListString:
                 - match A
                 - match B
-                propertyOneMap:
+                matchableMapString:
+                    test1: matchableMap1
+                    test2: matchableMap2
+                nonmatchableMapString:
+                    risk: potential risk of matching
+                matchableDataType:
+                    zeroStringMatchable: zero Match
+                    zeroBooleanMatchable: true
+                    zeroFloatMatchable: 9.9
+                    zeroIntegerMatchable: 1000
+                    zeroTimestampMatchable: 2020-01-01T23:59:59Z
                     oneString: One is NOT matchable
                     oneStringMatchable: One should be matched
-                    propertyTwoList:
+                    propertyTwoListOfDatatype:
                     -   twoString: Two is NOT matchable
                         twoStringMatchable: Two should be matched
-                        propertyThreeMap:
-                            threeString: Three is NOT matchable
-                            threeStringMatchable: Three should be matched
\ No newline at end of file
+                        twoIntegerMatchable: 55
+                        propertyThreeDatatype:
+                            myThree:
+                                threeStringMatchable: Three should match
+                                threeIntegerMatchable: 66
\ No newline at end of file
index db638fb..bea94cd 100644 (file)
@@ -1,4 +1,4 @@
-tosca_definitions_version: tosca_simple_yaml_1_0_0
+tosca_definitions_version: tosca_simple_yaml_1_1_0
 topology_template:
   policies:
     -
diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlExceptionMapper.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlExceptionMapper.java
new file mode 100644 (file)
index 0000000..4112e64
--- /dev/null
@@ -0,0 +1,69 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 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.pdpx.main.rest.serialization;
+
+import java.io.IOException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import lombok.Getter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Catches IOException when decoding/encoding a REST xacml request/response and converts them from an HTTP 500
+ * error code to an HTTP 400 error code.
+ *
+ */
+public abstract class XacmlExceptionMapper implements ExceptionMapper<IOException> {
+    private static final Logger LOGGER = LoggerFactory.getLogger(XacmlExceptionMapper.class);
+
+    @Getter
+    String invalidRequest;
+    @Getter
+    String invalidResponse;
+
+    public abstract boolean isInvalidRequest(String message);
+
+    public abstract boolean isInvalidResponse(String message);
+
+    @Override
+    public Response toResponse(IOException exc) {
+        if (isInvalidRequest(exc.getMessage())) {
+            LOGGER.warn(invalidRequest, exc);
+            return Response.status(Response.Status.BAD_REQUEST).entity(new SimpleResponse(invalidRequest)).build();
+        } else if (isInvalidResponse(exc.getMessage())) {
+            LOGGER.warn(invalidResponse, exc);
+            return Response.status(Response.Status.BAD_REQUEST).entity(new SimpleResponse(invalidResponse)).build();
+        } else {
+            // Unexpected 500
+            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+        }
+    }
+
+    @Getter
+    private static class SimpleResponse {
+        private String errorDetails;
+
+        public SimpleResponse(String errorDetails) {
+            this.errorDetails = errorDetails;
+        }
+    }
+}
index 81fc2d2..03f3ddc 100644 (file)
 
 package org.onap.policy.pdpx.main.rest.serialization;
 
-import java.io.IOException;
 import javax.ws.rs.Produces;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.Provider;
-import lombok.Getter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Catches IOException when decoding/encoding a REST xacml request/response and converts them from an HTTP 500
@@ -37,32 +31,20 @@ import org.slf4j.LoggerFactory;
  */
 @Provider
 @Produces(XacmlJsonMessageBodyHandler.APPLICATION_XACML_JSON)
-public class XacmlJsonExceptionMapper implements ExceptionMapper<IOException> {
+public class XacmlJsonExceptionMapper  extends XacmlExceptionMapper {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(XacmlJsonExceptionMapper.class);
-    private static final String INVALID_REQUEST = "invalid JSON xacml request";
-    private static final String INVALID_RESPONSE = "invalid JSON xacml response";
+    public XacmlJsonExceptionMapper() {
+        this.invalidRequest = "invalid JSON xacml request";
+        this.invalidResponse = "invalid JSON xacml response";
+    }
 
     @Override
-    public Response toResponse(IOException exc) {
-        if (exc.getMessage().contains("json request")) {
-            LOGGER.warn(INVALID_REQUEST, exc);
-            return Response.status(Response.Status.BAD_REQUEST).entity(new SimpleResponse(INVALID_REQUEST)).build();
-        } else if (exc.getMessage().contains("json response")) {
-            LOGGER.warn(INVALID_RESPONSE, exc);
-            return Response.status(Response.Status.BAD_REQUEST).entity(new SimpleResponse(INVALID_RESPONSE)).build();
-        } else {
-            // Unexpected 500
-            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
-        }
+    public boolean isInvalidRequest(String message) {
+        return message.contains("json request");
     }
 
-    @Getter
-    private static class SimpleResponse {
-        private String errorDetails;
-
-        public SimpleResponse(String errorDetails) {
-            this.errorDetails = errorDetails;
-        }
+    @Override
+    public boolean isInvalidResponse(String message) {
+        return message.contains("json response");
     }
 }
\ No newline at end of file
index 8e62abe..562c0e9 100644 (file)
 
 package org.onap.policy.pdpx.main.rest.serialization;
 
-import java.io.IOException;
 import javax.ws.rs.Produces;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.Provider;
-import lombok.Getter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Catches IOException when decoding/encoding a REST xacml request/response and converts them from an HTTP 500
@@ -37,32 +31,20 @@ import org.slf4j.LoggerFactory;
  */
 @Provider
 @Produces(XacmlXmlMessageBodyHandler.APPLICATION_XACML_XML)
-public class XacmlXmlExceptionMapper implements ExceptionMapper<IOException> {
+public class XacmlXmlExceptionMapper extends XacmlExceptionMapper {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(XacmlXmlExceptionMapper.class);
-    private static final String INVALID_REQUEST = "invalid XML xacml request";
-    private static final String INVALID_RESPONSE = "invalid XML xacml response";
+    public XacmlXmlExceptionMapper() {
+        this.invalidRequest = "invalid XML xacml request";
+        this.invalidResponse = "invalid XML xacml response";
+    }
 
     @Override
-    public Response toResponse(IOException exc) {
-        if (exc.getMessage().contains("dom request")) {
-            LOGGER.warn(INVALID_REQUEST, exc);
-            return Response.status(Response.Status.BAD_REQUEST).entity(new SimpleResponse(INVALID_REQUEST)).build();
-        } else if (exc.getMessage().contains("dom response")) {
-            LOGGER.warn(INVALID_RESPONSE, exc);
-            return Response.status(Response.Status.BAD_REQUEST).entity(new SimpleResponse(INVALID_RESPONSE)).build();
-        } else {
-            // Unexpected 500
-            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
-        }
+    public boolean isInvalidRequest(String message) {
+        return message.contains("dom request");
     }
 
-    @Getter
-    private static class SimpleResponse {
-        private String errorDetails;
-
-        public SimpleResponse(String errorDetails) {
-            this.errorDetails = errorDetails;
-        }
+    @Override
+    public boolean isInvalidResponse(String message) {
+        return message.contains("dom response");
     }
 }
\ No newline at end of file