2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * SPDX-License-Identifier: Apache-2.0
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.pdp.xacml.application.common;
25 import com.att.research.xacml.api.Identifier;
26 import com.att.research.xacml.api.XACML3;
28 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
29 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
30 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
31 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
32 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
33 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
34 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
35 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
36 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
37 import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableReferenceType;
38 import org.apache.commons.lang3.StringUtils;
39 import org.onap.policy.common.parameters.BeanValidationResult;
40 import org.onap.policy.common.parameters.BeanValidator;
41 import org.onap.policy.common.utils.coder.CoderException;
42 import org.onap.policy.common.utils.coder.StandardCoder;
45 * This class contains static methods of helper classes to convert TOSCA policies
46 * into XACML policies.
48 * @author pameladragosh
51 public final class ToscaPolicyTranslatorUtils {
52 private static final ObjectFactory factory = new ObjectFactory();
53 private static final StandardCoder CODER = new StandardCoder();
55 private ToscaPolicyTranslatorUtils() {
60 * This method builds a MatchType for TargetType object for AttributeValue and AttributeDesignator
63 * @param <T> Incoming value could be any object
64 * @param function Function for the Match
65 * @param value Attribute value used
66 * @param datatype Datatype for attribute value and AttributeDesignator
67 * @param designatorId ID for the AttributeDesignator
68 * @param designatorCategory Category ID for the AttributeDesignator
69 * @return The MatchType object
71 public static <T> MatchType buildMatchTypeDesignator(Identifier function,
74 Identifier designatorId,
75 Identifier designatorCategory) {
77 // Create the MatchType object and set its function
79 var match = new MatchType();
80 match.setMatchId(function.stringValue());
82 // Add in the AttributeValue object
84 var valueType = new AttributeValueType();
85 valueType.setDataType(datatype.stringValue());
86 valueType.getContent().add(value);
88 match.setAttributeValue(valueType);
90 // Add in the AttributeDesignator object
92 var designator = new AttributeDesignatorType();
93 designator.setAttributeId(designatorId.stringValue());
94 designator.setCategory(designatorCategory.stringValue());
95 designator.setDataType(datatype.stringValue());
97 match.setAttributeDesignator(designator);
105 * Builds an AllOfType (AND) with one or more MatchType objects.
107 * @param matches A list of one or more MatchType
108 * @return The AllOf object
110 public static AllOfType buildAllOf(MatchType... matches) {
111 var allOf = new AllOfType();
112 for (MatchType match : matches) {
113 allOf.getMatch().add(match);
119 * Takes start and end time interval and generates an ApplyType for it.
121 * @param start ISO8601 timestamp
122 * @param end ISO8601 timestamp
125 public static ApplyType generateTimeInRange(String start, String end, boolean useRecurringFunction) {
126 if (StringUtils.isBlank(start) || StringUtils.isBlank(end)) {
130 var designator = new AttributeDesignatorType();
131 designator.setAttributeId(XACML3.ID_ENVIRONMENT_CURRENT_TIME.stringValue());
132 designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT.stringValue());
133 designator.setDataType(XACML3.ID_DATATYPE_TIME.stringValue());
135 var valueStart = new AttributeValueType();
136 valueStart.setDataType(XACML3.ID_DATATYPE_TIME.stringValue());
137 valueStart.getContent().add(start);
139 var valueEnd = new AttributeValueType();
140 valueEnd.setDataType(XACML3.ID_DATATYPE_TIME.stringValue());
141 valueEnd.getContent().add(end);
144 var applyOneAndOnly = new ApplyType();
145 applyOneAndOnly.setDescription("Unbag the current time");
146 applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_TIME_ONE_AND_ONLY.stringValue());
147 applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
149 var applyTimeInRange = new ApplyType();
150 applyTimeInRange.setDescription("return true if current time is in range.");
151 if (useRecurringFunction) {
152 applyTimeInRange.setFunctionId(XACML3.ID_FUNCTION_TIME_IN_RECURRING_RANGE.stringValue());
154 applyTimeInRange.setFunctionId(XACML3.ID_FUNCTION_TIME_IN_RANGE.stringValue());
156 applyTimeInRange.getExpression().add(factory.createApply(applyOneAndOnly));
157 applyTimeInRange.getExpression().add(factory.createAttributeValue(valueStart));
158 applyTimeInRange.getExpression().add(factory.createAttributeValue(valueEnd));
160 return applyTimeInRange;
164 * Parses an integer value from the string.
166 * @param strInteger String representation of integer
167 * @return Integer object
169 public static Integer parseInteger(String strInteger) {
170 Integer theInt = null;
172 theInt = Integer.parseInt(strInteger);
173 } catch (NumberFormatException e) {
175 Double dblLimit = Double.parseDouble(strInteger);
176 theInt = dblLimit.intValue();
177 } catch (NumberFormatException e1) {
185 * For a given MatchType or AnyOfType, builds it and appends it into the
188 * @param anyOf AnyOfType - will create if null
189 * @param type MatchType or AnyOfType
190 * @return returns the given anyOf or new AnyTypeOf if null
192 public static AnyOfType buildAndAppendAllof(AnyOfType anyOf, Object type) {
193 if (type instanceof MatchType) {
194 var allOf = new AllOfType();
195 allOf.getMatch().add((MatchType) type);
197 anyOf = new AnyOfType();
199 anyOf.getAllOf().add(allOf);
200 } else if (type instanceof AllOfType) {
202 anyOf = new AnyOfType();
204 anyOf.getAllOf().add((AllOfType) type);
211 * buildAndAppendTarget - adds in the potential object into TargetType.
213 * @param target TargetType - must exist
214 * @param object AnyOfType or MatchType
217 public static TargetType buildAndAppendTarget(TargetType target, Object object) {
218 if (object instanceof AnyOfType) {
219 target.getAnyOf().add((AnyOfType) object);
220 } else if (object instanceof MatchType) {
221 var allOf = new AllOfType();
222 allOf.getMatch().add((MatchType) object);
223 var anyOf = new AnyOfType();
224 anyOf.getAllOf().add(allOf);
225 target.getAnyOf().add(anyOf);
231 * For an existing ConditionType, this method adds in a check for a variable. You must specify
232 * the function that compares the existing ConditionType's expression against the Variable.
234 * @param condition Existing ConditionType to use
235 * @param variable VariableReferenceType to use
236 * @param functionId XACML 3.0 identifier for the function
237 * @return a new ConditionType
239 public static ConditionType addVariableToCondition(ConditionType condition, VariableReferenceType variable,
240 Identifier functionId) {
241 var applyFunction = new ApplyType();
242 applyFunction.setFunctionId(functionId.stringValue());
243 applyFunction.getExpression().add(condition.getExpression());
244 applyFunction.getExpression().add(factory.createVariableReference(variable));
245 var newCondition = new ConditionType();
246 newCondition.setExpression(factory.createApply(applyFunction));
251 * Decodes TOSCA Policy properties into a particular type and validates the result.
253 * @param <T> desired type
254 * @param properties properties to be decoded
255 * @param clazz desired class
256 * @return the decoded properties
257 * @throws ToscaPolicyConversionException if the properties cannot be decoded or are
260 public static <T> T decodeProperties(Map<String, Object> properties, Class<T> clazz)
261 throws ToscaPolicyConversionException {
263 if (properties == null) {
264 throw new ToscaPolicyConversionException(
265 "Cannot decode " + clazz.getSimpleName() + " from null properties");
269 T data = CODER.convert(properties, clazz);
270 BeanValidationResult result = new BeanValidator().validateTop("properties", data);
271 if (!result.isValid()) {
272 throw new ToscaPolicyConversionException(result.getResult());
275 } catch (CoderException e) {
276 throw new ToscaPolicyConversionException("Cannot decode " + clazz.getSimpleName() + " from properties", e);