View Javadoc

1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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.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(";")); //$NON-NLS-1$
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         // Parse the Expression
112         SimpleNode tree;
113         synchronized(parser)
114         {
115             log.debug( "Parsing expression: " + expr );
116             tree = parser.parse(new StringReader(expr));
117         }
118 
119         // Must be a simple reference or expression, otherwise
120         // throw an exception.
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 }