48861d86bdbfb5254b84e1ab379870be20a7d65a
[policy/xacml-pdp.git] / applications / guard / src / main / java / org / onap / policy / xacml / pdp / application / guard / LegacyGuardTranslator.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2019 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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.xacml.pdp.application.guard;
24
25 import com.att.research.xacml.api.DataTypeException;
26 import com.att.research.xacml.api.Decision;
27 import com.att.research.xacml.api.Identifier;
28 import com.att.research.xacml.api.Request;
29 import com.att.research.xacml.api.Response;
30 import com.att.research.xacml.api.Result;
31 import com.att.research.xacml.api.XACML3;
32 import com.att.research.xacml.std.annotations.RequestParser;
33 import com.att.research.xacml.util.XACMLPolicyWriter;
34
35 import java.io.ByteArrayOutputStream;
36 import java.io.IOException;
37 import java.util.ArrayList;
38 import java.util.Collection;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Map.Entry;
42
43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType;
44 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionsType;
45 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
46 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
47 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
48 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
49 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
50 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
51 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
52 import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
53 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
54 import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
55 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
56 import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
57 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
58
59 import org.onap.policy.models.decisions.concepts.DecisionRequest;
60 import org.onap.policy.models.decisions.concepts.DecisionResponse;
61 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
62 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
63 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator;
64 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslatorUtils;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
67
68 public class LegacyGuardTranslator implements ToscaPolicyTranslator {
69
70     private static final Logger LOGGER = LoggerFactory.getLogger(LegacyGuardTranslator.class);
71
72     private static final String FIELD_POLICIES = "policies";
73     private static final String FIELD_TOPOLOGY_TEMPLATE = "topology_template";
74     private static final String FIELD_GUARD_ACTIVE_START = "guardActiveStart";
75     private static final String FIELD_GUARD_ACTIVE_END = "guardActiveEnd";
76
77     public LegacyGuardTranslator() {
78         super();
79     }
80
81     @SuppressWarnings("unchecked")
82     @Override
83     public List<PolicyType> scanAndConvertPolicies(Map<String, Object> toscaObject)
84             throws ToscaPolicyConversionException {
85         //
86         // Our return object
87         //
88         List<PolicyType> scannedPolicies = new ArrayList<>();
89         //
90         // Find the Policies
91         //
92         List<Object> policies;
93
94         if (toscaObject.containsKey(FIELD_POLICIES)) {
95             policies = (List<Object>) toscaObject.get(FIELD_POLICIES);
96         } else if (toscaObject.containsKey(FIELD_TOPOLOGY_TEMPLATE)) {
97             Map<String, Object> topologyTemplate = (Map<String, Object>) toscaObject.get(FIELD_TOPOLOGY_TEMPLATE);
98             if (topologyTemplate.containsKey(FIELD_POLICIES)) {
99                 policies = (List<Object>) topologyTemplate.get(FIELD_POLICIES);
100             } else {
101                 LOGGER.warn("topologyTemplate does not contain policies");
102                 return scannedPolicies;
103             }
104         } else {
105             LOGGER.warn("Failed to find policies or topologyTemplate");
106             return scannedPolicies;
107         }
108         //
109         // Iterate each of the Policies
110         //
111         for (Object policyObject : policies) {
112             //
113             // Get the contents
114             //
115             LOGGER.debug("Found policy {}", policyObject.getClass());
116             Map<String, Object> policyContents = (Map<String, Object>) policyObject;
117             for (Entry<String, Object> entrySet : policyContents.entrySet()) {
118                 LOGGER.debug("Entry set {}", entrySet);
119                 //
120                 // Convert this policy
121                 //
122                 PolicyType policy = this.convertPolicy(entrySet);
123                 if (policy == null) {
124                     //
125                     // Somehow there wasn't enough information to create
126                     // a policy
127                     //
128                     LOGGER.debug("Failed to convert policy");
129                     continue;
130                 }
131                 //
132                 // Debug dump this
133                 //
134                 try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
135                     XACMLPolicyWriter.writePolicyFile(os, policy);
136                     LOGGER.debug("{}", os);
137                 } catch (IOException e) {
138                     LOGGER.error("Failed to convert {}", e);
139                 }
140                 //
141                 // Convert and add in the new policy
142                 //
143                 scannedPolicies.add(policy);
144             }
145         }
146
147         return scannedPolicies;
148     }
149
150     @Override
151     public Request convertRequest(DecisionRequest request) {
152         LOGGER.debug("Converting Request {}", request);
153         try {
154             return RequestParser.parseRequest(LegacyGuardPolicyRequest.createInstance(request));
155         } catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) {
156             LOGGER.error("Failed to convert DecisionRequest: {}", e);
157         }
158         //
159         // TODO throw exception
160         //
161         return null;
162     }
163
164
165     @Override
166     public DecisionResponse convertResponse(Response xacmlResponse) {
167         LOGGER.debug("Converting Response {}", xacmlResponse);
168         DecisionResponse decisionResponse = new DecisionResponse();
169         //
170         // Iterate through all the results
171         //
172         for (Result xacmlResult : xacmlResponse.getResults()) {
173             //
174             // Check the result
175             //
176             if (xacmlResult.getDecision() == Decision.PERMIT) {
177                 //
178                 // Just simply return a Permit response
179                 //
180                 decisionResponse.setStatus(Decision.PERMIT.toString());
181             }
182             if (xacmlResult.getDecision() == Decision.DENY) {
183                 //
184                 // Just simply return a Deny response
185                 //
186                 decisionResponse.setStatus(Decision.DENY.toString());
187             }
188             if (xacmlResult.getDecision() == Decision.NOTAPPLICABLE) {
189                 //
190                 // There is no guard policy, so we return a permit
191                 //
192                 decisionResponse.setStatus(Decision.PERMIT.toString());
193             }
194         }
195
196         return decisionResponse;
197     }
198
199     @SuppressWarnings("unchecked")
200     private PolicyType convertPolicy(Entry<String, Object> entrySet) throws ToscaPolicyConversionException {
201         //
202         // Policy name should be at the root
203         //
204         String policyName = entrySet.getKey();
205         Map<String, Object> policyDefinition = (Map<String, Object>) entrySet.getValue();
206         //
207         // Set it as the policy ID
208         //
209         PolicyType newPolicyType = new PolicyType();
210         newPolicyType.setPolicyId(policyName);
211         //
212         // Optional description
213         //
214         if (policyDefinition.containsKey("description")) {
215             newPolicyType.setDescription(policyDefinition.get("description").toString());
216         }
217         //
218         // There should be a metadata section
219         //
220         if (! policyDefinition.containsKey("metadata")) {
221             throw new ToscaPolicyConversionException(policyName + " missing metadata section");
222         }
223         this.fillMetadataSection(newPolicyType,
224                 (Map<String, Object>) policyDefinition.get("metadata"));
225         //
226         // Set the combining rule
227         //
228         newPolicyType.setRuleCombiningAlgId(XACML3.ID_RULE_DENY_UNLESS_PERMIT.stringValue());
229         //
230         // Generate the TargetType
231         //
232         if (! policyDefinition.containsKey("properties")) {
233             throw new ToscaPolicyConversionException(policyName + " missing properties section");
234         }
235         newPolicyType.setTarget(this.generateTargetType((Map<String, Object>) policyDefinition.get("properties")));
236         //
237         // Now create the Permit Rule
238         //
239         RuleType rule = generatePermitRule(policyName, policyDefinition.get("type").toString(),
240                 (Map<String, Object>) policyDefinition.get("properties"));
241         //
242         // Check if we were able to create the rule
243         //
244         if (rule == null) {
245             LOGGER.warn("Failed to create rule");
246             return null;
247         }
248         //
249         // Add the rule to the policy
250         //
251         newPolicyType.getCombinerParametersOrRuleCombinerParametersOrVariableDefinition().add(rule);
252         //
253         // Return our new policy
254         //
255         return newPolicyType;
256     }
257
258     /**
259      * From the TOSCA metadata section, pull in values that are needed into the XACML policy.
260      *
261      * @param policy Policy Object to store the metadata
262      * @param metadata The Metadata TOSCA Map
263      * @return Same Policy Object
264      * @throws ToscaPolicyConversionException If there is something missing from the metadata
265      */
266     protected PolicyType fillMetadataSection(PolicyType policy,
267             Map<String, Object> metadata) throws ToscaPolicyConversionException {
268         if (! metadata.containsKey("policy-id")) {
269             throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata policy-id");
270         } else {
271             //
272             // Do nothing here - the XACML PolicyId is used from TOSCA Policy Name field
273             //
274         }
275         if (! metadata.containsKey("policy-version")) {
276             throw new ToscaPolicyConversionException(policy.getPolicyId() + " missing metadata policy-version");
277         } else {
278             //
279             // Add in the Policy Version
280             //
281             policy.setVersion(metadata.get("policy-version").toString());
282         }
283         return policy;
284     }
285
286     protected TargetType generateTargetType(Map<String, Object> properties) {
287         //
288         // Go through potential properties
289         //
290         AllOfType allOf = new AllOfType();
291         if (properties.containsKey("actor")) {
292             addMatch(allOf, properties.get("actor"), ToscaDictionary.ID_RESOURCE_GUARD_ACTOR);
293         }
294         if (properties.containsKey("recipe")) {
295             addMatch(allOf, properties.get("recipe"), ToscaDictionary.ID_RESOURCE_GUARD_RECIPE);
296         }
297         if (properties.containsKey("targets")) {
298             addMatch(allOf, properties.get("targets"), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
299         }
300         if (properties.containsKey("clname")) {
301             addMatch(allOf, properties.get("clname"), ToscaDictionary.ID_RESOURCE_GUARD_CLNAME);
302         }
303         if (properties.containsKey("targets")) {
304             addMatch(allOf, properties.get("targets"), ToscaDictionary.ID_RESOURCE_GUARD_TARGETID);
305         }
306         //
307         // Create target
308         //
309         TargetType target = new TargetType();
310         AnyOfType anyOf = new AnyOfType();
311         anyOf.getAllOf().add(allOf);
312         target.getAnyOf().add(anyOf);
313         return target;
314     }
315
316     private static AllOfType addMatch(AllOfType allOf, Object value, Identifier attributeId) {
317         if (value instanceof String) {
318             if (".*".equals(value.toString())) {
319                 //
320                 // There's no point to even have a match
321                 //
322                 return allOf;
323             } else {
324                 //
325                 // Exact match
326                 //
327                 MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator(
328                     XACML3.ID_FUNCTION_STRING_EQUAL,
329                     value,
330                     XACML3.ID_DATATYPE_STRING,
331                     attributeId,
332                     XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE);
333
334                 allOf.getMatch().add(match);
335             }
336             return allOf;
337         }
338         if (value instanceof Collection) {
339             //
340             // TODO support a collection of that attribute
341             //
342         }
343         return allOf;
344     }
345
346     private static RuleType generatePermitRule(String policyName, String policyType, Map<String, Object> properties) {
347         //
348         // Now determine which policy type we are generating
349         //
350         if ("onap.policies.controlloop.guard.FrequencyLimiter".equals(policyType)) {
351             return generateFrequencyPermit(policyName, properties);
352         } else if ("onap.policies.controlloop.guard.MinMax".equals(policyType)) {
353             return generateMinMaxPermit(policyName, properties);
354         }
355         return null;
356     }
357
358     private static RuleType generateFrequencyPermit(String policyName, Map<String, Object> properties) {
359         //
360         // See if its possible to generate a count
361         //
362         Integer limit = null;
363         if (properties.containsKey("limit")) {
364             limit = Integer.decode(properties.get("limit").toString());
365         }
366         if (limit == null) {
367             LOGGER.debug("Must have a limit value for frequency guard policy to be created");
368             return null;
369         }
370         //
371         // Get the properties that are common among guards
372         //
373         String timeWindow = null;
374         if (properties.containsKey("timeWindow")) {
375             timeWindow = properties.get("timeWindow").toString();
376         }
377         String timeUnits = null;
378         if (properties.containsKey("timeUnits")) {
379             timeUnits = properties.get("timeUnits").toString();
380         }
381         String guardActiveStart = null;
382         if (properties.containsKey(FIELD_GUARD_ACTIVE_START)) {
383             guardActiveStart = properties.get(FIELD_GUARD_ACTIVE_START).toString();
384         }
385         String guardActiveEnd = null;
386         if (properties.containsKey(FIELD_GUARD_ACTIVE_END)) {
387             guardActiveEnd = properties.get(FIELD_GUARD_ACTIVE_END).toString();
388         }
389         //
390         // Generate the time in range
391         //
392         final ApplyType timeRange = generateTimeInRange(guardActiveStart, guardActiveEnd);
393         //
394         // Generate a count
395         //
396         final ApplyType countCheck = generateCountCheck(limit, timeWindow, timeUnits);
397         //
398         // Now combine into an And
399         //
400         ApplyType applyAnd = new ApplyType();
401         applyAnd.setDescription("return true if time range and count checks are true.");
402         applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue());
403         applyAnd.getExpression().add(new ObjectFactory().createApply(timeRange));
404         applyAnd.getExpression().add(new ObjectFactory().createApply(countCheck));
405
406         //
407         // Create our condition
408         //
409         final ConditionType condition = new ConditionType();
410         condition.setExpression(new ObjectFactory().createApply(applyAnd));
411
412         //
413         // Now we can create our rule
414         //
415         RuleType permit = new RuleType();
416         permit.setDescription("Default is to PERMIT if the policy matches.");
417         permit.setRuleId(policyName + ":rule");
418         permit.setEffect(EffectType.PERMIT);
419         permit.setTarget(new TargetType());
420         //
421         // Add the condition
422         //
423         permit.setCondition(condition);
424         //
425         // TODO Add the advice - Is the request id needed to be returned?
426         //
427         // permit.setAdviceExpressions(adviceExpressions);
428         //
429         // Done
430         //
431         return permit;
432     }
433
434     private static RuleType generateMinMaxPermit(String policyName, Map<String, Object> properties) {
435         //
436         // Get the properties that are common among guards
437         //
438         String guardActiveStart = null;
439         if (properties.containsKey(FIELD_GUARD_ACTIVE_START)) {
440             guardActiveStart = properties.get(FIELD_GUARD_ACTIVE_START).toString();
441         }
442         String guardActiveEnd = null;
443         if (properties.containsKey(FIELD_GUARD_ACTIVE_END)) {
444             guardActiveEnd = properties.get(FIELD_GUARD_ACTIVE_END).toString();
445         }
446         //
447         // Generate the time in range
448         //
449         final ApplyType timeRange = generateTimeInRange(guardActiveStart, guardActiveEnd);
450         //
451         // See if its possible to generate a count
452         //
453         Integer min = null;
454         if (properties.containsKey("min")) {
455             min = Integer.decode(properties.get("min").toString());
456         }
457         Integer max = null;
458         if (properties.containsKey("max")) {
459             max = Integer.decode(properties.get("max").toString());
460         }
461         final ApplyType minApply = generateMinCheck(min);
462         final ApplyType maxApply = generateMaxCheck(max);
463         //
464         // Make sure we have at least something to check here,
465         // otherwise there really is no point to this policy.
466         //
467         if (timeRange == null && minApply == null && maxApply == null) {
468             return null;
469         }
470         //
471         // Create our rule
472         //
473         RuleType permit = new RuleType();
474         permit.setDescription("Default is to PERMIT if the policy matches.");
475         permit.setRuleId(policyName + ":rule");
476         permit.setEffect(EffectType.PERMIT);
477         permit.setTarget(new TargetType());
478         //
479         // Create our condition
480         //
481         final ConditionType condition = new ConditionType();
482         //
483         // Check if we have all the fields (this can be a little
484         // ugly) but the ultimate goal is to simplify the policy
485         // condition to only check for necessary attributes.
486         //
487         ObjectFactory factory = new ObjectFactory();
488         if (timeRange != null && minApply != null && maxApply != null) {
489             //
490             // All 3 must apply
491             //
492             ApplyType applyAnd = new ApplyType();
493             applyAnd.setDescription("return true if all the apply's are true.");
494             applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue());
495             applyAnd.getExpression().add(factory.createApply(timeRange));
496             applyAnd.getExpression().add(factory.createApply(minApply));
497             applyAnd.getExpression().add(factory.createApply(maxApply));
498             //
499             // Add into the condition
500             //
501             condition.setExpression(factory.createApply(applyAnd));
502         } else {
503             //
504             // At least one of these applies is null. We need at least
505             // two to require the And apply. Otherwise there is no need
506             // for an outer And apply as the single condition can work
507             // on its own.
508             //
509             if (timeRange != null && minApply == null && maxApply == null) {
510                 //
511                 // Only the time range check is necessary
512                 //
513                 condition.setExpression(factory.createApply(timeRange));
514             } else if (timeRange == null && minApply != null && maxApply == null) {
515                 //
516                 // Only the min check is necessary
517                 //
518                 condition.setExpression(factory.createApply(minApply));
519             } else if (timeRange == null && minApply == null) {
520                 //
521                 // Only the max check is necessary
522                 //
523                 condition.setExpression(factory.createApply(maxApply));
524             } else {
525                 //
526                 // Ok we will need an outer And and have at least the
527                 // time range and either min or max check
528                 //
529                 ApplyType applyAnd = new ApplyType();
530                 applyAnd.setDescription("return true if all the apply's are true.");
531                 applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue());
532                 if (timeRange != null) {
533                     applyAnd.getExpression().add(factory.createApply(timeRange));
534                 }
535                 if (minApply != null) {
536                     applyAnd.getExpression().add(factory.createApply(minApply));
537                 }
538                 if (maxApply != null) {
539                     applyAnd.getExpression().add(factory.createApply(maxApply));
540                 }
541                 //
542                 // Add into the condition
543                 //
544                 condition.setExpression(factory.createApply(applyAnd));
545             }
546         }
547         //
548         // Add the condition
549         //
550         permit.setCondition(condition);
551         //
552         // TODO Add the advice - Is the request id needed to be returned?
553         //
554         // permit.setAdviceExpressions(adviceExpressions);
555         //
556         // Done
557         //
558         return permit;
559     }
560
561     private static ApplyType generateTimeInRange(String start, String end) {
562         if (start == null || end == null) {
563             LOGGER.warn("Missing time range start {} end {}", start, end);
564             return null;
565         }
566         if (start.isEmpty() || end.isEmpty()) {
567             LOGGER.warn("Empty time range start {} end {}", start, end);
568             return null;
569         }
570
571         AttributeDesignatorType designator = new AttributeDesignatorType();
572         designator.setAttributeId(XACML3.ID_ENVIRONMENT_CURRENT_TIME.stringValue());
573         designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT.stringValue());
574         designator.setDataType(XACML3.ID_DATATYPE_TIME.stringValue());
575
576         AttributeValueType valueStart = new AttributeValueType();
577         valueStart.setDataType(XACML3.ID_DATATYPE_TIME.stringValue());
578         valueStart.getContent().add(start);
579
580         AttributeValueType valueEnd = new AttributeValueType();
581         valueEnd.setDataType(XACML3.ID_DATATYPE_TIME.stringValue());
582         valueEnd.getContent().add(end);
583
584         ObjectFactory factory = new ObjectFactory();
585
586         ApplyType applyOneAndOnly = new ApplyType();
587         applyOneAndOnly.setDescription("Unbag the current time");
588         applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_TIME_ONE_AND_ONLY.stringValue());
589         applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
590
591         ApplyType applyTimeInRange = new ApplyType();
592         applyTimeInRange.setDescription("return true if current time is in range.");
593         applyTimeInRange.setFunctionId(XACML3.ID_FUNCTION_TIME_IN_RANGE.stringValue());
594         applyTimeInRange.getExpression().add(factory.createApply(applyOneAndOnly));
595         applyTimeInRange.getExpression().add(factory.createAttributeValue(valueStart));
596         applyTimeInRange.getExpression().add(factory.createAttributeValue(valueEnd));
597
598         return applyTimeInRange;
599     }
600
601     private static ApplyType generateCountCheck(Integer limit, String timeWindow, String timeUnits) {
602         AttributeDesignatorType designator = new AttributeDesignatorType();
603         designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT.stringValue());
604         designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
605         designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
606         //
607         // TODO Add this back in when the operational database PIP is configured.
608         // The issuer indicates that the PIP will be providing this attribute during
609         // the decision making.
610         //
611         // Right now I am faking the count value by re-using the request-id field
612         //
613         String issuer = ToscaDictionary.GUARD_ISSUER + ":tw:" + timeWindow + ":" + timeUnits;
614         designator.setIssuer(issuer);
615
616         AttributeValueType valueLimit = new AttributeValueType();
617         valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
618         //
619         // Yes really use toString(), the marshaller will
620         // throw an exception if this is an integer object
621         // and not a string.
622         //
623         valueLimit.getContent().add(limit.toString());
624
625         ObjectFactory factory = new ObjectFactory();
626
627         ApplyType applyOneAndOnly = new ApplyType();
628         applyOneAndOnly.setDescription("Unbag the limit");
629         applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
630         applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
631
632         ApplyType applyLessThan = new ApplyType();
633         applyLessThan.setDescription("return true if current count is less than.");
634         applyLessThan.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN.stringValue());
635         applyLessThan.getExpression().add(factory.createApply(applyOneAndOnly));
636         applyLessThan.getExpression().add(factory.createAttributeValue(valueLimit));
637
638         return applyLessThan;
639     }
640
641     private static ApplyType generateMinCheck(Integer min) {
642         if (min == null) {
643             return null;
644         }
645         AttributeDesignatorType designator = new AttributeDesignatorType();
646         designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.stringValue());
647         designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
648         designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
649         //
650         //
651         //
652         AttributeValueType valueLimit = new AttributeValueType();
653         valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
654         //
655         // Yes really use toString(), the marshaller will
656         // throw an exception if this is an integer object
657         // and not a string.
658         //
659         valueLimit.getContent().add(min.toString());
660         ObjectFactory factory = new ObjectFactory();
661
662         ApplyType applyOneAndOnly = new ApplyType();
663         applyOneAndOnly.setDescription("Unbag the min");
664         applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
665         applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
666
667         ApplyType applyGreaterThanEqual = new ApplyType();
668         applyGreaterThanEqual.setDescription("return true if current count is greater than or equal.");
669         applyGreaterThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_GREATER_THAN_OR_EQUAL.stringValue());
670         applyGreaterThanEqual.getExpression().add(factory.createApply(applyOneAndOnly));
671         applyGreaterThanEqual.getExpression().add(factory.createAttributeValue(valueLimit));
672
673         return applyGreaterThanEqual;
674     }
675
676     private static ApplyType generateMaxCheck(Integer max) {
677         if (max == null) {
678             return null;
679         }
680         AttributeDesignatorType designator = new AttributeDesignatorType();
681         designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.stringValue());
682         designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
683         designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
684         //
685         //
686         //
687         AttributeValueType valueLimit = new AttributeValueType();
688         valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
689         //
690         // Yes really use toString(), the marshaller will
691         // throw an exception if this is an integer object
692         // and not a string.
693         //
694         valueLimit.getContent().add(max.toString());
695         ObjectFactory factory = new ObjectFactory();
696
697         ApplyType applyOneAndOnly = new ApplyType();
698         applyOneAndOnly.setDescription("Unbag the min");
699         applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
700         applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
701
702         ApplyType applyLessThanEqual = new ApplyType();
703         applyLessThanEqual.setDescription("return true if current count is less than or equal.");
704         applyLessThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN_OR_EQUAL.stringValue());
705         applyLessThanEqual.getExpression().add(factory.createApply(applyOneAndOnly));
706         applyLessThanEqual.getExpression().add(factory.createAttributeValue(valueLimit));
707
708         return applyLessThanEqual;
709     }
710
711     private static AdviceExpressionsType generateRequestIdAdvice() {
712         AdviceExpressionType adviceExpression = new AdviceExpressionType();
713         adviceExpression.setAppliesTo(EffectType.PERMIT);
714         adviceExpression.setAdviceId(ToscaDictionary.ID_ADVICE_GUARD.stringValue());
715
716         AttributeDesignatorType designator = new AttributeDesignatorType();
717         designator.setAttributeId(ToscaDictionary.ID_SUBJECT_GUARD_REQUESTID.stringValue());
718         designator.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue());
719         designator.setDataType(XACML3.ID_DATATYPE_STRING.stringValue());
720
721         AttributeAssignmentExpressionType assignment = new AttributeAssignmentExpressionType();
722         assignment.setAttributeId(ToscaDictionary.ID_ADVICE_GUARD_REQUESTID.stringValue());
723         assignment.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue());
724         assignment.setExpression(new ObjectFactory().createAttributeDesignator(designator));
725
726         adviceExpression.getAttributeAssignmentExpression().add(assignment);
727
728         AdviceExpressionsType adviceExpressions = new AdviceExpressionsType();
729         adviceExpressions.getAdviceExpression().add(adviceExpression);
730
731         return adviceExpressions;
732     }
733 }