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 2007 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.kew.engine.RouteContext;
 23  
 import org.kuali.rice.kew.exception.WorkflowException;
 24  
 import org.kuali.rice.kew.service.KEWServiceLocator;
 25  
 
 26  
 
 27  
 /**
 28  
  * Implements the KRA meta-rule processing and state machine engine 
 29  
  * 
 30  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 31  
  */
 32  
 public class KRAMetaRuleEngine {
 33  0
     private static final Logger LOG = Logger.getLogger(KRAMetaRuleEngine.class);
 34  
 
 35  
     /**
 36  
      * KRA meta-rule processing flag
 37  
      */
 38  0
     private static enum KRA_RULE_FLAG {
 39  0
         NEXT, TRUE, FALSE
 40  
     }
 41  
 
 42  
     private final String expression;
 43  
     private final String[] statements;
 44  0
     private int curStatement = 0;
 45  
     /**
 46  
      * Whether processing has indicated that we should stop
 47  
      */
 48  0
     private boolean stop = false;
 49  
     
 50  0
     public KRAMetaRuleEngine(String expression) throws ParseException {
 51  0
         this.expression = expression;
 52  0
         statements = expression.split("\\s*[;\r\n]\\s*");
 53  
         
 54  0
         if (statements.length == 0) {
 55  0
             throw new ParseException("No statements parsed in expression: " + expression, 0);
 56  
         }
 57  0
     }
 58  
 
 59  
     /**
 60  
      * @return the expression the engine was initialized with
 61  
      */
 62  
     public String getExpression() {
 63  0
         return expression;
 64  
     }
 65  
 
 66  
     /**
 67  
      * @return the parsed statements
 68  
      */
 69  
     public String[] getStatements() {
 70  0
         return statements;
 71  
     }
 72  
 
 73  
     /**
 74  
      * @return the next statement the engine will process
 75  
      */
 76  
     public int getCurStatement() {
 77  0
         return curStatement;
 78  
     }
 79  
 
 80  
     /**
 81  
      * @param statementNo the statement index at which to resume processing 
 82  
      */
 83  
     public void setCurStatement(int statementNo) {
 84  0
         this.curStatement = statementNo;
 85  0
     }
 86  
 
 87  
     /**
 88  
      * @return whether we are done processing
 89  
      */
 90  
     public boolean isDone() {
 91  0
         return curStatement >= statements.length || stop;
 92  
     }
 93  
 
 94  
     /**
 95  
      * Processes a single statement and returns the result
 96  
      * @param context the current RouteContext
 97  
      * @return the expression result that resulted from the evaluation of a single statement
 98  
      * @throws ParseException if the statement could not be parsed
 99  
      */
 100  
     public RuleExpressionResult processSingleStatement(RouteContext context) throws ParseException, WorkflowException {
 101  0
         if (isDone()) {
 102  0
             return null;
 103  
         }
 104  
 
 105  0
         int stmtNum = curStatement + 1;
 106  0
         String statement = statements[curStatement];
 107  0
         LOG.debug("Processing statement: " + statement);
 108  0
         String[] words = statement.split("\\s*:\\s*");
 109  0
         if (words.length < 2) {
 110  0
             throw new ParseException("Invalid statement (#" + stmtNum + "): " + statement, 0);
 111  
         }
 112  0
         String ruleName = words[0];
 113  0
         if (StringUtils.isEmpty(ruleName)) {
 114  0
             throw new ParseException("Invalid rule in statement (#" + stmtNum + "): " + statement, 0);
 115  
         }
 116  0
         String flag = words[1];
 117  0
         LOG.debug(flag.toUpperCase());
 118  0
         KRA_RULE_FLAG flagCode = KRA_RULE_FLAG.valueOf(flag.toUpperCase());
 119  0
         if (flagCode == null) {
 120  0
             throw new ParseException("Invalid flag in statement (#" + stmtNum + "): " + statement, 0);
 121  
         }
 122  0
         RuleBaseValues nestedRule = KEWServiceLocator.getRuleService().getRuleByName(ruleName);
 123  0
         if (nestedRule == null) {
 124  0
             throw new ParseException("Rule '" + ruleName + "' in statement (#" + stmtNum + ") not found: " + statement, 0);
 125  
         }
 126  
 
 127  0
         Rule rule = new RuleImpl(nestedRule);
 128  
         RuleExpressionResult result;
 129  0
         switch (flagCode) {
 130  
             case NEXT:
 131  0
                 result = rule.evaluate(rule, context);
 132  0
                 break;
 133  
             case TRUE:
 134  0
                 result = rule.evaluate(rule, context);
 135  0
                 if (!result.isSuccess()) {
 136  0
                     stop = true;
 137  
                 }
 138  
                 break;
 139  
             case FALSE:
 140  0
                 result = rule.evaluate(rule, context);
 141  0
                 if (result.isSuccess()) {
 142  0
                     stop = true;
 143  
                     // we need to just invert the ultimate expression result success, because in this case
 144  
                     // we wanted the expression to fail but it didn't
 145  0
                     result = new RuleExpressionResult(rule, false, result.getResponsibilities());
 146  
                 }
 147  
                 break;
 148  
             default:
 149  0
                 throw new WorkflowException("Unhandled statement flag: " + flagCode);
 150  
         }
 151  
 
 152  0
         curStatement++;
 153  0
         LOG.debug("Result of statement '" + statement + "': " + result);
 154  0
         return result;
 155  
     }
 156  
 }