diff options
author | Pamela Dragosh <pdragosh@research.att.com> | 2020-03-18 07:50:22 -0400 |
---|---|---|
committer | Pamela Dragosh <pdragosh@research.att.com> | 2020-03-19 08:03:24 -0400 |
commit | 3b755ec2e3d9776980236db6ba754ae6b7cc2402 (patch) | |
tree | d9503508e748d9b6f516a2665461b32c66ee2ac0 /applications/common/src/main | |
parent | 6b4f9b69bc4acec28da8ef50b8f234d0182f0d78 (diff) |
Re-factor matchable to reduce complexity
This solution is much cleaner than what is in StdMatchableTranslator.
Over 90% code coverage on it - utilizes a callback to retrieve DataType
and PolicyTypes. Support for missing timestamp TOSCA type. Also can
do a better job differentiating between a property contained in the policy
vs a schema.
Changed StdMatchableTranslator to utilize these classes. And removed the
old spaghetti.
Added some JUnit coverage for ToscaPolicyTranslatorUtils.
Removed duplicate code in the XACML Native Exception classes.
Issue-ID: POLICY-2242
Change-Id: I18f898d9e65f6da28e3b27517d40f8d389de18a0
Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
Diffstat (limited to 'applications/common/src/main')
14 files changed, 1116 insertions, 457 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); } |