1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.scxml.env.jexl;
18
19 import java.io.Serializable;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.regex.Pattern;
25
26 import org.apache.commons.jexl.Expression;
27 import org.apache.commons.jexl.ExpressionFactory;
28 import org.apache.commons.scxml.Context;
29 import org.apache.commons.scxml.Evaluator;
30 import org.apache.commons.scxml.SCXMLExpressionException;
31 import org.w3c.dom.Node;
32
33
34
35
36
37
38 public class JexlEvaluator implements Evaluator, Serializable {
39
40
41 private static final long serialVersionUID = 1L;
42
43
44 private static final String ERR_CTX_TYPE = "Error evaluating JEXL "
45 + "expression, Context must be a org.apache.commons.jexl.JexlContext";
46
47
48 private static Pattern inFct = Pattern.compile("In\\(");
49
50 private static Pattern dataFct = Pattern.compile("Data\\(");
51
52
53 public JexlEvaluator() {
54 super();
55 }
56
57
58
59
60
61
62
63
64
65
66 public Object eval(final Context ctx, final String expr)
67 throws SCXMLExpressionException {
68 if (expr == null) {
69 return null;
70 }
71 JexlContext jexlCtx = null;
72 if (ctx instanceof JexlContext) {
73 jexlCtx = (JexlContext) ctx;
74 } else {
75 throw new SCXMLExpressionException(ERR_CTX_TYPE);
76 }
77 Expression exp = null;
78 try {
79 String evalExpr = inFct.matcher(expr).
80 replaceAll("_builtin.isMember(_ALL_STATES, ");
81 evalExpr = dataFct.matcher(evalExpr).
82 replaceAll("_builtin.data(_ALL_NAMESPACES, ");
83 exp = ExpressionFactory.createExpression(evalExpr);
84 return exp.evaluate(getEffectiveContext(jexlCtx));
85 } catch (Exception e) {
86 throw new SCXMLExpressionException("eval('" + expr + "'):"
87 + e.getMessage(), e);
88 }
89 }
90
91
92
93
94 public Boolean evalCond(final Context ctx, final String expr)
95 throws SCXMLExpressionException {
96 if (expr == null) {
97 return null;
98 }
99 JexlContext jexlCtx = null;
100 if (ctx instanceof JexlContext) {
101 jexlCtx = (JexlContext) ctx;
102 } else {
103 throw new SCXMLExpressionException(ERR_CTX_TYPE);
104 }
105 Expression exp = null;
106 try {
107 String evalExpr = inFct.matcher(expr).
108 replaceAll("_builtin.isMember(_ALL_STATES, ");
109 evalExpr = dataFct.matcher(evalExpr).
110 replaceAll("_builtin.data(_ALL_NAMESPACES, ");
111 exp = ExpressionFactory.createExpression(evalExpr);
112 return (Boolean) exp.evaluate(getEffectiveContext(jexlCtx));
113 } catch (Exception e) {
114 throw new SCXMLExpressionException("eval('" + expr + "'):"
115 + e.getMessage(), e);
116 }
117 }
118
119
120
121
122 public Node evalLocation(final Context ctx, final String expr)
123 throws SCXMLExpressionException {
124 if (expr == null) {
125 return null;
126 }
127 JexlContext jexlCtx = null;
128 if (ctx instanceof JexlContext) {
129 jexlCtx = (JexlContext) ctx;
130 } else {
131 throw new SCXMLExpressionException(ERR_CTX_TYPE);
132 }
133 Expression exp = null;
134 try {
135 String evalExpr = inFct.matcher(expr).
136 replaceAll("_builtin.isMember(_ALL_STATES, ");
137 evalExpr = dataFct.matcher(evalExpr).
138 replaceFirst("_builtin.dataNode(_ALL_NAMESPACES, ");
139 evalExpr = dataFct.matcher(evalExpr).
140 replaceAll("_builtin.data(_ALL_NAMESPACES, ");
141 exp = ExpressionFactory.createExpression(evalExpr);
142 return (Node) exp.evaluate(getEffectiveContext(jexlCtx));
143 } catch (Exception e) {
144 throw new SCXMLExpressionException("eval('" + expr + "'):"
145 + e.getMessage(), e);
146 }
147 }
148
149
150
151
152
153
154
155
156 public Context newContext(final Context parent) {
157 return new JexlContext(parent);
158 }
159
160
161
162
163
164
165
166
167
168
169 private JexlContext getEffectiveContext(final JexlContext nodeCtx) {
170 List contexts = new ArrayList();
171
172 JexlContext currentCtx = nodeCtx;
173 while (currentCtx != null) {
174 contexts.add(currentCtx);
175 currentCtx = (JexlContext) currentCtx.getParent();
176 }
177 Map vars = new HashMap();
178
179 for (int i = contexts.size() - 1; i > -1; i--) {
180 vars.putAll(((JexlContext) contexts.get(i)).getVars());
181 }
182 return new JexlContext(vars);
183 }
184
185 }
186