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