001    /**
002     * Copyright 2005-2013 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.kew.rule;
017    
018    import org.apache.log4j.Logger;
019    import org.kuali.rice.kew.api.exception.WorkflowException;
020    import org.kuali.rice.kew.engine.RouteContext;
021    
022    import javax.script.ScriptEngine;
023    import javax.script.ScriptException;
024    import java.util.ArrayList;
025    import java.util.List;
026    
027    /**
028     * An extension of BSFRuleExpression that makes it easier to accumulate a list of responsibilities
029     * to emit. 
030     * 
031     * @author Kuali Rice Team (rice.collab@kuali.org)
032     */
033    public class AccumulatingBSFRuleExpression extends BSFRuleExpression {
034        private static final Logger LOG = Logger.getLogger(AccumulatingBSFRuleExpression.class);
035    
036        @Override
037        protected void declareBeans(ScriptEngine engine, Rule rule, RouteContext context) throws ScriptException {
038            // define the standard beans
039            super.declareBeans(engine, rule, context);
040            // define our special rule helper class
041            RuleHelper rh = new RuleHelper(rule, context);
042            engine.put("metarule", rh); // backwards compatibility with existing KRAMetaRuleExpression usage
043            engine.put("rulehelper", rh);
044        }
045    
046        /**
047         * Helper class that is exposed to groovy scripts
048         */
049        private static final class RuleHelper {
050            private Rule rule;
051            private WorkflowRuleAPI workflow;
052            /**
053             * Responsibilities accumulated during the evaluation
054             */
055            private List<org.kuali.rice.kew.api.rule.RuleResponsibility> responsibilities = new ArrayList<org.kuali.rice.kew.api.rule.RuleResponsibility>();
056            private int responsibilityPriority = 0;
057    
058            private RuleHelper(Rule rule, RouteContext context) {
059                this.workflow = new WorkflowRuleAPI(context);
060                this.rule = rule;
061            }
062    
063            /**
064             * @return the accumulated responsibilities
065             */
066            public List<org.kuali.rice.kew.api.rule.RuleResponsibility> getResponsibilities() {
067                return responsibilities;
068            }
069    
070            /**
071             * @param success whether the result should be successful
072             * @return the RuleExpressionResult with success flag and accumulated responsibilities
073             */
074            public RuleExpressionResult getResult(boolean success) {
075                return new RuleExpressionResult(rule, success, responsibilities);
076            }
077    
078            /**
079             * Adds the responsibilities in the result to the list of accumulated responsibilities 
080             * @param result a RuleExpressionResult whose responsibilities to accumulate
081             */
082            public void accumulate(RuleExpressionResult result) {
083                if (result.getResponsibilities() == null || result.getResponsibilities().size() == 0) return;
084    
085                Integer curPriority = Integer.valueOf(responsibilityPriority);
086                for (org.kuali.rice.kew.api.rule.RuleResponsibility responsibility: result.getResponsibilities()) {
087                    org.kuali.rice.kew.api.rule.RuleResponsibility.Builder builder =
088                            org.kuali.rice.kew.api.rule.RuleResponsibility.Builder.create(responsibility);
089                    builder.setPriority(curPriority);
090                    responsibilities.add(builder.build());
091                }
092                // increment responsibilityPriority for next rule expression result responsibilities
093                responsibilityPriority++;
094            }
095    
096            /**
097             * Evaluates a named rule accumulating responsibilities regardless of rule success
098             * @param ruleName the name of the rule to evaluate
099             * @return whether the rule was successful
100             */
101            public boolean evalRule(String ruleName) throws WorkflowException {
102                RuleExpressionResult result = workflow.invokeRule(ruleName);
103                accumulate(result);
104                return result.isSuccess();
105            }
106    
107            /**
108             * Evaluates a named rule and if it is successful accumulates the rule responsibilities
109             * @param ruleName the name of the rule to evaluate
110             * @param accumOnSuccess whether to accumulate the rules responsibilities on success (true), or on failure (false)
111             * @return whether the rule was successful
112             */
113            public boolean evalRule(String ruleName, boolean accumOnSuccess) throws WorkflowException {
114                RuleExpressionResult result = workflow.invokeRule(ruleName);
115                if (accumOnSuccess == result.isSuccess()) {
116                    accumulate(result);
117                }
118                return result.isSuccess();
119            }
120    
121        }
122    }