81340b4d00ebeab6f003ac7c7795e04c63677e92
[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 all the apply's 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         // And create an outer negation of the And
407         //
408         ApplyType applyNot = new ApplyType();
409         applyNot.setDescription("Negate the and");
410         applyNot.setFunctionId(XACML3.ID_FUNCTION_NOT.stringValue());
411         applyNot.getExpression().add(new ObjectFactory().createApply(applyAnd));
412
413         //
414         // Create our condition
415         //
416         final ConditionType condition = new ConditionType();
417         condition.setExpression(new ObjectFactory().createApply(applyNot));
418
419         //
420         // Now we can create our rule
421         //
422         RuleType permit = new RuleType();
423         permit.setDescription("Default is to PERMIT if the policy matches.");
424         permit.setRuleId(policyName + ":rule");
425         permit.setEffect(EffectType.PERMIT);
426         permit.setTarget(new TargetType());
427         //
428         // Add the condition
429         //
430         permit.setCondition(condition);
431         //
432         // TODO Add the advice - Is the request id needed to be returned?
433         //
434         // permit.setAdviceExpressions(adviceExpressions);
435         //
436         // Done
437         //
438         return permit;
439     }
440
441     private static RuleType generateMinMaxPermit(String policyName, Map<String, Object> properties) {
442         //
443         // Get the properties that are common among guards
444         //
445         String guardActiveStart = null;
446         if (properties.containsKey(FIELD_GUARD_ACTIVE_START)) {
447             guardActiveStart = properties.get(FIELD_GUARD_ACTIVE_START).toString();
448         }
449         String guardActiveEnd = null;
450         if (properties.containsKey(FIELD_GUARD_ACTIVE_END)) {
451             guardActiveEnd = properties.get(FIELD_GUARD_ACTIVE_END).toString();
452         }
453         //
454         // Generate the time in range
455         //
456         final ApplyType timeRange = generateTimeInRange(guardActiveStart, guardActiveEnd);
457         //
458         // See if its possible to generate a count
459         //
460         Integer min = null;
461         if (properties.containsKey("min")) {
462             min = Integer.decode(properties.get("min").toString());
463         }
464         Integer max = null;
465         if (properties.containsKey("max")) {
466             max = Integer.decode(properties.get("max").toString());
467         }
468         final ApplyType minApply = generateMinCheck(min);
469         final ApplyType maxApply = generateMaxCheck(max);
470         //
471         // Make sure we have at least something to check here,
472         // otherwise there really is no point to this policy.
473         //
474         if (timeRange == null && minApply == null && maxApply == null) {
475             return null;
476         }
477         //
478         // Create our rule
479         //
480         RuleType permit = new RuleType();
481         permit.setDescription("Default is to PERMIT if the policy matches.");
482         permit.setRuleId(policyName + ":rule");
483         permit.setEffect(EffectType.PERMIT);
484         permit.setTarget(new TargetType());
485         //
486         // Create our condition
487         //
488         final ConditionType condition = new ConditionType();
489         //
490         // Check if we have all the fields (this can be a little
491         // ugly) but the ultimate goal is to simplify the policy
492         // condition to only check for necessary attributes.
493         //
494         ObjectFactory factory = new ObjectFactory();
495         if (timeRange != null && minApply != null && maxApply != null) {
496             //
497             // All 3 must apply
498             //
499             ApplyType applyAnd = new ApplyType();
500             applyAnd.setDescription("return true if all the apply's are true.");
501             applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue());
502             applyAnd.getExpression().add(factory.createApply(timeRange));
503             applyAnd.getExpression().add(factory.createApply(minApply));
504             applyAnd.getExpression().add(factory.createApply(maxApply));
505             //
506             // Add into the condition
507             //
508             condition.setExpression(factory.createApply(applyAnd));
509         } else {
510             //
511             // At least one of these applies is null. We need at least
512             // two to require the And apply. Otherwise there is no need
513             // for an outer And apply as the single condition can work
514             // on its own.
515             //
516             if (timeRange != null && minApply == null && maxApply == null) {
517                 //
518                 // Only the time range check is necessary
519                 //
520                 condition.setExpression(factory.createApply(timeRange));
521             } else if (timeRange == null && minApply != null && maxApply == null) {
522                 //
523                 // Only the min check is necessary
524                 //
525                 condition.setExpression(factory.createApply(minApply));
526             } else if (timeRange == null && minApply == null) {
527                 //
528                 // Only the max check is necessary
529                 //
530                 condition.setExpression(factory.createApply(maxApply));
531             } else {
532                 //
533                 // Ok we will need an outer And and have at least the
534                 // time range and either min or max check
535                 //
536                 ApplyType applyAnd = new ApplyType();
537                 applyAnd.setDescription("return true if all the apply's are true.");
538                 applyAnd.setFunctionId(XACML3.ID_FUNCTION_AND.stringValue());
539                 if (timeRange != null) {
540                     applyAnd.getExpression().add(factory.createApply(timeRange));
541                 }
542                 if (minApply != null) {
543                     applyAnd.getExpression().add(factory.createApply(minApply));
544                 }
545                 if (maxApply != null) {
546                     applyAnd.getExpression().add(factory.createApply(maxApply));
547                 }
548                 //
549                 // Add into the condition
550                 //
551                 condition.setExpression(factory.createApply(applyAnd));
552             }
553         }
554         //
555         // Add the condition
556         //
557         permit.setCondition(condition);
558         //
559         // TODO Add the advice - Is the request id needed to be returned?
560         //
561         // permit.setAdviceExpressions(adviceExpressions);
562         //
563         // Done
564         //
565         return permit;
566     }
567
568     private static ApplyType generateTimeInRange(String start, String end) {
569         if (start == null || end == null) {
570             LOGGER.warn("Missing time range start {} end {}", start, end);
571             return null;
572         }
573         if (start.isEmpty() || end.isEmpty()) {
574             LOGGER.warn("Empty time range start {} end {}", start, end);
575             return null;
576         }
577
578         AttributeDesignatorType designator = new AttributeDesignatorType();
579         designator.setAttributeId(XACML3.ID_ENVIRONMENT_CURRENT_TIME.stringValue());
580         designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT.stringValue());
581         designator.setDataType(XACML3.ID_DATATYPE_TIME.stringValue());
582
583         AttributeValueType valueStart = new AttributeValueType();
584         valueStart.setDataType(XACML3.ID_DATATYPE_TIME.stringValue());
585         valueStart.getContent().add(start);
586
587         AttributeValueType valueEnd = new AttributeValueType();
588         valueEnd.setDataType(XACML3.ID_DATATYPE_TIME.stringValue());
589         valueEnd.getContent().add(end);
590
591         ObjectFactory factory = new ObjectFactory();
592
593         ApplyType applyOneAndOnly = new ApplyType();
594         applyOneAndOnly.setDescription("Unbag the current time");
595         applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_TIME_ONE_AND_ONLY.stringValue());
596         applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
597
598         ApplyType applyTimeInRange = new ApplyType();
599         applyTimeInRange.setDescription("return true if current time is in range.");
600         applyTimeInRange.setFunctionId(XACML3.ID_FUNCTION_TIME_IN_RANGE.stringValue());
601         applyTimeInRange.getExpression().add(factory.createApply(applyOneAndOnly));
602         applyTimeInRange.getExpression().add(factory.createAttributeValue(valueStart));
603         applyTimeInRange.getExpression().add(factory.createAttributeValue(valueEnd));
604
605         return applyTimeInRange;
606     }
607
608     private static ApplyType generateCountCheck(Integer limit, String timeWindow, String timeUnits) {
609         AttributeDesignatorType designator = new AttributeDesignatorType();
610         designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT.stringValue());
611         designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
612         designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
613         //
614         // TODO Add this back in when the operational database PIP is configured.
615         // The issuer indicates that the PIP will be providing this attribute during
616         // the decision making.
617         //
618         // Right now I am faking the count value by re-using the request-id field
619         //
620         //String issuer = "org:onap:xacml:guard:historydb:tw:" + timeWindow + ":" + timeUnits;
621         //designator.setIssuer(issuer);
622
623         AttributeValueType valueLimit = new AttributeValueType();
624         valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
625         //
626         // Yes really use toString(), the marshaller will
627         // throw an exception if this is an integer object
628         // and not a string.
629         //
630         valueLimit.getContent().add(limit.toString());
631
632         ObjectFactory factory = new ObjectFactory();
633
634         ApplyType applyOneAndOnly = new ApplyType();
635         applyOneAndOnly.setDescription("Unbag the limit");
636         applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
637         applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
638
639         ApplyType applyGreaterThanEqual = new ApplyType();
640         applyGreaterThanEqual.setDescription("return true if current count is greater than or equal.");
641         applyGreaterThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_GREATER_THAN_OR_EQUAL.stringValue());
642         applyGreaterThanEqual.getExpression().add(factory.createApply(applyOneAndOnly));
643         applyGreaterThanEqual.getExpression().add(factory.createAttributeValue(valueLimit));
644
645         return applyGreaterThanEqual;
646     }
647
648     private static ApplyType generateMinCheck(Integer min) {
649         if (min == null) {
650             return null;
651         }
652         AttributeDesignatorType designator = new AttributeDesignatorType();
653         designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.stringValue());
654         designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
655         designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
656         //
657         //
658         //
659         AttributeValueType valueLimit = new AttributeValueType();
660         valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
661         //
662         // Yes really use toString(), the marshaller will
663         // throw an exception if this is an integer object
664         // and not a string.
665         //
666         valueLimit.getContent().add(min.toString());
667         ObjectFactory factory = new ObjectFactory();
668
669         ApplyType applyOneAndOnly = new ApplyType();
670         applyOneAndOnly.setDescription("Unbag the min");
671         applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
672         applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
673
674         ApplyType applyGreaterThanEqual = new ApplyType();
675         applyGreaterThanEqual.setDescription("return true if current count is greater than or equal.");
676         applyGreaterThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_GREATER_THAN_OR_EQUAL.stringValue());
677         applyGreaterThanEqual.getExpression().add(factory.createApply(applyOneAndOnly));
678         applyGreaterThanEqual.getExpression().add(factory.createAttributeValue(valueLimit));
679
680         return applyGreaterThanEqual;
681     }
682
683     private static ApplyType generateMaxCheck(Integer max) {
684         if (max == null) {
685             return null;
686         }
687         AttributeDesignatorType designator = new AttributeDesignatorType();
688         designator.setAttributeId(ToscaDictionary.ID_RESOURCE_GUARD_VFCOUNT.stringValue());
689         designator.setCategory(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE.stringValue());
690         designator.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
691         //
692         //
693         //
694         AttributeValueType valueLimit = new AttributeValueType();
695         valueLimit.setDataType(XACML3.ID_DATATYPE_INTEGER.stringValue());
696         //
697         // Yes really use toString(), the marshaller will
698         // throw an exception if this is an integer object
699         // and not a string.
700         //
701         valueLimit.getContent().add(max.toString());
702         ObjectFactory factory = new ObjectFactory();
703
704         ApplyType applyOneAndOnly = new ApplyType();
705         applyOneAndOnly.setDescription("Unbag the min");
706         applyOneAndOnly.setFunctionId(XACML3.ID_FUNCTION_INTEGER_ONE_AND_ONLY.stringValue());
707         applyOneAndOnly.getExpression().add(factory.createAttributeDesignator(designator));
708
709         ApplyType applyGreaterThanEqual = new ApplyType();
710         applyGreaterThanEqual.setDescription("return true if current count is less than or equal.");
711         applyGreaterThanEqual.setFunctionId(XACML3.ID_FUNCTION_INTEGER_LESS_THAN_OR_EQUAL.stringValue());
712         applyGreaterThanEqual.getExpression().add(factory.createApply(applyOneAndOnly));
713         applyGreaterThanEqual.getExpression().add(factory.createAttributeValue(valueLimit));
714
715         return applyGreaterThanEqual;
716     }
717
718     private static AdviceExpressionsType generateRequestIdAdvice() {
719         AdviceExpressionType adviceExpression = new AdviceExpressionType();
720         adviceExpression.setAppliesTo(EffectType.PERMIT);
721         adviceExpression.setAdviceId(ToscaDictionary.ID_ADVICE_GUARD.stringValue());
722
723         AttributeDesignatorType designator = new AttributeDesignatorType();
724         designator.setAttributeId(ToscaDictionary.ID_SUBJECT_GUARD_REQUESTID.stringValue());
725         designator.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue());
726         designator.setDataType(XACML3.ID_DATATYPE_STRING.stringValue());
727
728         AttributeAssignmentExpressionType assignment = new AttributeAssignmentExpressionType();
729         assignment.setAttributeId(ToscaDictionary.ID_ADVICE_GUARD_REQUESTID.stringValue());
730         assignment.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue());
731         assignment.setExpression(new ObjectFactory().createAttributeDesignator(designator));
732
733         adviceExpression.getAttributeAssignmentExpression().add(assignment);
734
735         AdviceExpressionsType adviceExpressions = new AdviceExpressionsType();
736         adviceExpressions.getAdviceExpression().add(adviceExpression);
737
738         return adviceExpressions;
739     }
740 }