Coverage Report - org.kuali.rice.kew.rule.KRAMetaRuleEngine
 
Classes in this File Line Coverage Branch Coverage Complexity
KRAMetaRuleEngine
0%
0/49
0%
0/24
3.714
KRAMetaRuleEngine$1
0%
0/1
N/A
3.714
KRAMetaRuleEngine$KRA_RULE_FLAG
0%
0/2
N/A
3.714
 
 1  
 /**
 2  
  * Copyright 2005-2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.kew.rule;
 17  
 
 18  
 import java.text.ParseException;
 19  
 
 20  
 import org.apache.commons.lang.StringUtils;
 21  
 import org.apache.log4j.Logger;
 22  
 import org.kuali.rice.core.api.exception.RiceIllegalStateException;
 23  
 import org.kuali.rice.kew.api.KewApiServiceLocator;
 24  
 import org.kuali.rice.kew.engine.RouteContext;
 25  
 
 26  
 /**
 27  
  * Implements the KRA meta-rule processing and state machine engine 
 28  
  * 
 29  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 30  
  */
 31  
 public class KRAMetaRuleEngine {
 32  0
     private static final Logger LOG = Logger.getLogger(KRAMetaRuleEngine.class);
 33  
 
 34  
     /**
 35  
      * KRA meta-rule processing flag
 36  
      */
 37  0
     private static enum KRA_RULE_FLAG {
 38  0
         NEXT, TRUE, FALSE
 39  
     }
 40  
 
 41  
     private final String expression;
 42  
     private final String[] statements;
 43  0
     private int curStatement = 0;
 44  
     /**
 45  
      * Whether processing has indicated that we should stop
 46  
      */
 47  0
     private boolean stop = false;
 48  
     
 49  0
     public KRAMetaRuleEngine(String expression) throws ParseException {
 50  0
         this.expression = expression;
 51  0
         statements = expression.split("\\s*[;\r\n]\\s*");
 52  
         
 53  0
         if (statements.length == 0) {
 54  0
             throw new ParseException("No statements parsed in expression: " + expression, 0);
 55  
         }
 56  0
     }
 57  
 
 58  
     /**
 59  
      * @return the expression the engine was initialized with
 60  
      */
 61  
     public String getExpression() {
 62  0
         return expression;
 63  
     }
 64  
 
 65  
     /**
 66  
      * @return the parsed statements
 67  
      */
 68  
     public String[] getStatements() {
 69  0
         return statements;
 70  
     }
 71  
 
 72  
     /**
 73  
      * @return the next statement the engine will process
 74  
      */
 75  
     public int getCurStatement() {
 76  0
         return curStatement;
 77  
     }
 78  
 
 79  
     /**
 80  
      * @param statementNo the statement index at which to resume processing 
 81  
      */
 82  
     public void setCurStatement(int statementNo) {
 83  0
         this.curStatement = statementNo;
 84  0
     }
 85  
 
 86  
     /**
 87  
      * @return whether we are done processing
 88  
      */
 89  
     public boolean isDone() {
 90  0
         return curStatement >= statements.length || stop;
 91  
     }
 92  
 
 93  
     /**
 94  
      * Processes a single statement and returns the result
 95  
      * @param context the current RouteContext
 96  
      * @return the expression result that resulted from the evaluation of a single statement
 97  
      * @throws ParseException if the statement could not be parsed
 98  
      */
 99  
     public RuleExpressionResult processSingleStatement(RouteContext context) throws ParseException {
 100  0
         if (isDone()) {
 101  0
             return null;
 102  
         }
 103  
 
 104  0
         int stmtNum = curStatement + 1;
 105  0
         String statement = statements[curStatement];
 106  0
         LOG.debug("Processing statement: " + statement);
 107  0
         String[] words = statement.split("\\s*:\\s*");
 108  0
         if (words.length < 2) {
 109  0
             throw new ParseException("Invalid statement (#" + stmtNum + "): " + statement, 0);
 110  
         }
 111  0
         String ruleName = words[0];
 112  0
         if (StringUtils.isEmpty(ruleName)) {
 113  0
             throw new ParseException("Invalid rule in statement (#" + stmtNum + "): " + statement, 0);
 114  
         }
 115  0
         String flag = words[1];
 116  0
         LOG.debug(flag.toUpperCase());
 117  0
         KRA_RULE_FLAG flagCode = KRA_RULE_FLAG.valueOf(flag.toUpperCase());
 118  0
         if (flagCode == null) {
 119  0
             throw new ParseException("Invalid flag in statement (#" + stmtNum + "): " + statement, 0);
 120  
         }
 121  0
         org.kuali.rice.kew.api.rule.Rule nestedRule = KewApiServiceLocator.getRuleService().getRuleByName(ruleName);
 122  0
         if (nestedRule == null) {
 123  0
             throw new ParseException("Rule '" + ruleName + "' in statement (#" + stmtNum + ") not found: " + statement, 0);
 124  
         }
 125  
 
 126  0
         Rule rule = new RuleImpl(nestedRule);
 127  
         RuleExpressionResult result;
 128  0
         switch (flagCode) {
 129  
             case NEXT:
 130  0
                 result = rule.evaluate(rule, context);
 131  0
                 break;
 132  
             case TRUE:
 133  0
                 result = rule.evaluate(rule, context);
 134  0
                 if (!result.isSuccess()) {
 135  0
                     stop = true;
 136  
                 }
 137  
                 break;
 138  
             case FALSE:
 139  0
                 result = rule.evaluate(rule, context);
 140  0
                 if (result.isSuccess()) {
 141  0
                     stop = true;
 142  
                     // we need to just invert the ultimate expression result success, because in this case
 143  
                     // we wanted the expression to fail but it didn't
 144  0
                     result = new RuleExpressionResult(rule, false, result.getResponsibilities());
 145  
                 }
 146  
                 break;
 147  
             default:
 148  0
                 throw new RiceIllegalStateException("Unhandled statement flag: " + flagCode);
 149  
         }
 150  
 
 151  0
         curStatement++;
 152  0
         LOG.debug("Result of statement '" + statement + "': " + result);
 153  0
         return result;
 154  
     }
 155  
 }