1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jexl;
17
18 import java.io.StringReader;
19
20 import org.apache.commons.jexl.parser.ASTExpressionExpression;
21 import org.apache.commons.jexl.parser.ASTReferenceExpression;
22 import org.apache.commons.jexl.parser.Parser;
23 import org.apache.commons.jexl.parser.SimpleNode;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26
27 /***
28 * <p>
29 * Creates Expression objects. To create a JEXL Expression object, pass
30 * valid JEXL syntax to the static createExpression() method:
31 * </p>
32 *
33 * <pre>
34 * String jexl = "array[1]";
35 * Expression expression = ExpressionFactory.createExpression( jexl );
36 * </pre>
37 *
38 * <p>
39 * When an {@link Expression} object is created, the JEXL syntax is
40 * parsed and verified. If the supplied expression is neither an
41 * expression not a reference, an exception is thrown from createException().
42 * </p>
43 * @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
44 * @version $Id: ExpressionFactory.java,v 1.7 2004/08/23 13:50:00 dion Exp $
45 */
46 public class ExpressionFactory
47 {
48 /***
49 * The Log to which all ExpressionFactory messages will be logged.
50 */
51 protected static Log log =
52 LogFactory.getLog("org.apache.commons.jexl.ExpressionFactory");
53
54 /***
55 * The singleton ExpressionFactory also holds a single instance of {@link Parser}.
56 * When parsing expressions, ExpressionFactory synchronizes on Parser.
57 */
58 protected static Parser parser = new Parser(new StringReader(";"));
59
60 /***
61 * ExpressionFactory is a single and this is the private
62 * status instance fufilling that pattern.
63 */
64 protected static ExpressionFactory ef = new ExpressionFactory();
65
66 /***
67 * Private constructor, the single instance is always obtained
68 * with a call to getInstance().
69 */
70 private ExpressionFactory(){}
71
72 /***
73 * Returns the single instance of ExpressionFactory.
74 * @return the instance of ExpressionFactory.
75 */
76 protected static ExpressionFactory getInstance()
77 {
78 return ef;
79 }
80
81 /***
82 * Creates an Expression from a String containing valid
83 * JEXL syntax. This method parses the expression which
84 * must contain either a reference or an expression.
85 * @param expression A String containing valid JEXL syntax
86 * @return An Expression object which can be evaluated with a JexlContext
87 * @throws Exception An exception can be thrown if there is a problem parsing
88 * his expression, or if the expression is neither an
89 * expression or a reference.
90 */
91 public static Expression createExpression(String expression)
92 throws Exception
93 {
94 return getInstance().createNewExpression(expression);
95 }
96
97
98 /***
99 * Creates a new Expression based on the expression string.
100 *
101 * @param expression valid Jexl expression
102 * @return Expression
103 * @throws Exception for a variety of reasons - mostly malformed
104 * Jexl expression
105 */
106 protected Expression createNewExpression(String expression)
107 throws Exception {
108
109 String expr = cleanExpression(expression);
110
111
112 SimpleNode tree;
113 synchronized(parser)
114 {
115 log.debug( "Parsing expression: " + expr );
116 tree = parser.parse(new StringReader(expr));
117 }
118
119
120
121 SimpleNode node = (SimpleNode) tree.jjtGetChild(0);
122
123 if( (node instanceof ASTReferenceExpression) ||
124 (node instanceof ASTExpressionExpression) )
125 {
126 node = (SimpleNode) node.jjtGetChild(0);
127 Expression e = new ExpressionImpl(expression, node);
128
129 return e;
130 }
131 else
132 {
133 log.error( "Invalid Expression, node of type: " + node.getClass().getName() );
134 throw new Exception("Invalid Expression: neither Reference nor Expression");
135 }
136 }
137
138 /***
139 * Trims the expression and adds a semi-colon if missing.
140 * @param expression to clean
141 * @return trimmed expression ending in a semi-colon
142 */
143 private String cleanExpression(String expression) {
144 String expr = expression.trim();
145 if (!expr.endsWith(";"))
146 {
147 expr += ";";
148 }
149 return expr;
150 }
151 }