1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
29
30
31
32 public class KRAMetaRuleEngine {
33 private static final Logger LOG = Logger.getLogger(KRAMetaRuleEngine.class);
34
35
36
37
38 private static enum KRA_RULE_FLAG {
39 NEXT, TRUE, FALSE
40 }
41
42 private final String expression;
43 private final String[] statements;
44 private int curStatement = 0;
45
46
47
48 private boolean stop = false;
49
50 public KRAMetaRuleEngine(String expression) throws ParseException {
51 this.expression = expression;
52 statements = expression.split("\\s*[;\r\n]\\s*");
53
54 if (statements.length == 0) {
55 throw new ParseException("No statements parsed in expression: " + expression, 0);
56 }
57 }
58
59
60
61
62 public String getExpression() {
63 return expression;
64 }
65
66
67
68
69 public String[] getStatements() {
70 return statements;
71 }
72
73
74
75
76 public int getCurStatement() {
77 return curStatement;
78 }
79
80
81
82
83 public void setCurStatement(int statementNo) {
84 this.curStatement = statementNo;
85 }
86
87
88
89
90 public boolean isDone() {
91 return curStatement >= statements.length || stop;
92 }
93
94
95
96
97
98
99
100 public RuleExpressionResult processSingleStatement(RouteContext context) throws ParseException, WorkflowException {
101 if (isDone()) {
102 return null;
103 }
104
105 int stmtNum = curStatement + 1;
106 String statement = statements[curStatement];
107 LOG.debug("Processing statement: " + statement);
108 String[] words = statement.split("\\s*:\\s*");
109 if (words.length < 2) {
110 throw new ParseException("Invalid statement (#" + stmtNum + "): " + statement, 0);
111 }
112 String ruleName = words[0];
113 if (StringUtils.isEmpty(ruleName)) {
114 throw new ParseException("Invalid rule in statement (#" + stmtNum + "): " + statement, 0);
115 }
116 String flag = words[1];
117 LOG.debug(flag.toUpperCase());
118 KRA_RULE_FLAG flagCode = KRA_RULE_FLAG.valueOf(flag.toUpperCase());
119 if (flagCode == null) {
120 throw new ParseException("Invalid flag in statement (#" + stmtNum + "): " + statement, 0);
121 }
122 RuleBaseValues nestedRule = KEWServiceLocator.getRuleService().getRuleByName(ruleName);
123 if (nestedRule == null) {
124 throw new ParseException("Rule '" + ruleName + "' in statement (#" + stmtNum + ") not found: " + statement, 0);
125 }
126
127 Rule rule = new RuleImpl(nestedRule);
128 RuleExpressionResult result;
129 switch (flagCode) {
130 case NEXT:
131 result = rule.evaluate(rule, context);
132 break;
133 case TRUE:
134 result = rule.evaluate(rule, context);
135 if (!result.isSuccess()) {
136 stop = true;
137 }
138 break;
139 case FALSE:
140 result = rule.evaluate(rule, context);
141 if (result.isSuccess()) {
142 stop = true;
143
144
145 result = new RuleExpressionResult(rule, false, result.getResponsibilities());
146 }
147 break;
148 default:
149 throw new WorkflowException("Unhandled statement flag: " + flagCode);
150 }
151
152 curStatement++;
153 LOG.debug("Result of statement '" + statement + "': " + result);
154 return result;
155 }
156 }