aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Hahn <jrh3@att.com>2020-03-19 16:23:08 +0000
committerGerrit Code Review <gerrit@onap.org>2020-03-19 16:23:08 +0000
commit3008ca45fb70a4694ba6b9ff69f278ab9484f3e3 (patch)
tree40d73755c08b24d828fa37dda3911f90e0f3e644
parentdf4599f94a4ef319810d3dae91e9bfcbcbc86ad2 (diff)
parent3b755ec2e3d9776980236db6ba754ae6b7cc2402 (diff)
Merge "Re-factor matchable to reduce complexity"
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtils.java48
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchableCallback.java34
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePolicyType.java338
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchableProperty.java36
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyType.java34
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeBase.java42
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeBoolean.java61
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeFloat.java68
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeInteger.java64
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeList.java73
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeMap.java80
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeString.java60
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeTimestamp.java64
-rw-r--r--applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java571
-rw-r--r--applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtilsTest.java25
-rw-r--r--applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePolicyTypeTest.java300
-rw-r--r--applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java2
-rw-r--r--applications/common/src/test/resources/matchable/onap.policies.Test-1.0.0.yaml96
-rw-r--r--applications/common/src/test/resources/matchable/test.policies.input.tosca.yaml38
-rw-r--r--applications/optimization/src/test/resources/bad-subscriber-policies.yaml2
-rw-r--r--applications/optimization/src/test/resources/test-optimization-policies.yaml2
-rw-r--r--main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlExceptionMapper.java69
-rw-r--r--main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlJsonExceptionMapper.java38
-rw-r--r--main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlXmlExceptionMapper.java38
24 files changed, 1641 insertions, 542 deletions
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtils.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtils.java
index f1d3d5e3..796499d4 100644
--- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtils.java
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtils.java
@@ -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
index 00000000..a076929d
--- /dev/null
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchableCallback.java
@@ -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
index 00000000..3bbc6ea5
--- /dev/null
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePolicyType.java
@@ -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
index 00000000..9b5de5c8
--- /dev/null
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchableProperty.java
@@ -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
index 00000000..8f910c4e
--- /dev/null
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyType.java
@@ -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
index 00000000..f93f8a3d
--- /dev/null
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeBase.java
@@ -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
index 00000000..d3b16c21
--- /dev/null
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeBoolean.java
@@ -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
index 00000000..5231ca62
--- /dev/null
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeFloat.java
@@ -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
index 00000000..ea798a5a
--- /dev/null
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeInteger.java
@@ -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
index 00000000..55fea540
--- /dev/null
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeList.java
@@ -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
index 00000000..d5083e1b
--- /dev/null
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeMap.java
@@ -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
index 00000000..4605b845
--- /dev/null
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeString.java
@@ -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
index 00000000..d24147cd
--- /dev/null
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePropertyTypeTimestamp.java
@@ -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);
+ }
+
+}
diff --git a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java
index 690b710f..11a45e0d 100644
--- a/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java
+++ b/applications/common/src/main/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslator.java
@@ -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,497 +374,101 @@ 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
* Lifecycle API the given TOSCA Policy Type.
@@ -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);
}
diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtilsTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtilsTest.java
index 8b85a0df..5d451e2c 100644
--- a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtilsTest.java
+++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/ToscaPolicyTranslatorUtilsTest.java
@@ -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
index 00000000..c23f7028
--- /dev/null
+++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/matchable/MatchablePolicyTypeTest.java
@@ -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);
+ }
+ }
+ }
+ }
+}
diff --git a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java
index 584390cd..1de1d79d 100644
--- a/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java
+++ b/applications/common/src/test/java/org/onap/policy/pdp/xacml/application/common/std/StdMatchableTranslatorTest.java
@@ -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
//
diff --git a/applications/common/src/test/resources/matchable/onap.policies.Test-1.0.0.yaml b/applications/common/src/test/resources/matchable/onap.policies.Test-1.0.0.yaml
index 7179c310..f0737b56 100644
--- a/applications/common/src/test/resources/matchable/onap.policies.Test-1.0.0.yaml
+++ b/applications/common/src/test/resources/matchable/onap.policies.Test-1.0.0.yaml
@@ -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
diff --git a/applications/common/src/test/resources/matchable/test.policies.input.tosca.yaml b/applications/common/src/test/resources/matchable/test.policies.input.tosca.yaml
index 80f72b2f..daffc2cb 100644
--- a/applications/common/src/test/resources/matchable/test.policies.input.tosca.yaml
+++ b/applications/common/src/test/resources/matchable/test.policies.input.tosca.yaml
@@ -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
diff --git a/applications/optimization/src/test/resources/bad-subscriber-policies.yaml b/applications/optimization/src/test/resources/bad-subscriber-policies.yaml
index db638fb8..bea94cdd 100644
--- a/applications/optimization/src/test/resources/bad-subscriber-policies.yaml
+++ b/applications/optimization/src/test/resources/bad-subscriber-policies.yaml
@@ -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/applications/optimization/src/test/resources/test-optimization-policies.yaml b/applications/optimization/src/test/resources/test-optimization-policies.yaml
index f893158b..d4969eb4 100644
--- a/applications/optimization/src/test/resources/test-optimization-policies.yaml
+++ b/applications/optimization/src/test/resources/test-optimization-policies.yaml
@@ -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
index 00000000..4112e64e
--- /dev/null
+++ b/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlExceptionMapper.java
@@ -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;
+ }
+ }
+}
diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlJsonExceptionMapper.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlJsonExceptionMapper.java
index 81fc2d26..03f3ddce 100644
--- a/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlJsonExceptionMapper.java
+++ b/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlJsonExceptionMapper.java
@@ -20,14 +20,8 @@
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
diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlXmlExceptionMapper.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlXmlExceptionMapper.java
index 8e62abec..562c0e91 100644
--- a/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlXmlExceptionMapper.java
+++ b/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlXmlExceptionMapper.java
@@ -20,14 +20,8 @@
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