Author: henrib
Date: Sun Aug 30 11:29:27 2009
New Revision: 809315
URL: http://svn.apache.org/viewvc?rev=809315&view=rev
Log:
Made ExpressionImpl implement both Script and Expression (will delete ScripImpl.java).
Use ASTJexlScript as root of Expression; implies it's also used as cached object by JexlEngine
cache (thus the modifications in JexlEngine and JexlTestCase)
Modified:
commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/ExpressionImpl.java
commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/JexlEngine.java
commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/JexlTestCase.java
Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/ExpressionImpl.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/ExpressionImpl.java?rev=809315&r1=809314&r2=809315&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/ExpressionImpl.java
(original)
+++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/ExpressionImpl.java
Sun Aug 30 11:29:27 2009
@@ -17,29 +17,28 @@
package org.apache.commons.jexl;
-import org.apache.commons.jexl.parser.JexlNode;
+import org.apache.commons.jexl.parser.ASTJexlScript;
/**
* Instances of ExpressionImpl are created by the {@link JexlEngine},
- * and this is the default implementation of the {@link Expression} interface.
+ * and this is the default implementation of the {@link Expression} and
+ * {@link Script} interface.
*
* @since 1.0
* @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
* @version $Id$
*/
-class ExpressionImpl implements Expression {
+class ExpressionImpl implements Expression, Script {
/** The engine for this expression. */
protected final JexlEngine jexl;
/**
- * Original expression. This is just a 'snippet', not a valid statement
- * (i.e. foo.bar() vs foo.bar();
+ * Original expression stripped from leading & trailing spaces.
*/
protected final String expression;
-
/**
* The resulting AST we can interpret.
*/
- protected final JexlNode node;
+ protected final ASTJexlScript script;
/**
@@ -49,9 +48,9 @@
* @param expr the expression.
* @param ref the parsed expression.
*/
- ExpressionImpl(JexlEngine engine, String expr, JexlNode ref) {
+ ExpressionImpl(JexlEngine engine, String expr, ASTJexlScript ref) {
expression = expr;
- node = ref;
+ script = ref;
jexl = engine;
}
@@ -59,8 +58,11 @@
* {@inheritDoc}
*/
public Object evaluate(JexlContext context) {
+ if (script.jjtGetNumChildren() < 1) {
+ return null;
+ }
Interpreter interpreter = jexl.createInterpreter(context);
- return interpreter.interpret(node);
+ return interpreter.interpret(script.jjtGetChild(0));
}
/**
@@ -68,7 +70,7 @@
*/
public String dump() {
Debugger debug = new Debugger();
- return debug.debug(node)? debug.toString() : "/*?*/";
+ return debug.debug(script)? debug.toString() : "/*?*/";
}
/**
@@ -89,4 +91,19 @@
return expr == null ? "" : expr;
}
+ /**
+ * {@inheritDoc}
+ */
+ public String getText() {
+ return toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object execute(JexlContext context) throws Exception {
+ Interpreter interpreter = jexl.createInterpreter(context);
+ return interpreter.interpret(script);
+ }
+
}
\ No newline at end of file
Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/JexlEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/JexlEngine.java?rev=809315&r1=809314&r2=809315&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/JexlEngine.java
(original)
+++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/JexlEngine.java
Sun Aug 30 11:29:27 2009
@@ -117,7 +117,7 @@
/**
* The expression cache.
*/
- protected Map<String, JexlNode> cache = null;
+ protected Map<String, ASTJexlScript> cache = null;
/**
* An empty/static/non-mutable JexlContext used instead of null context.
*/
@@ -298,13 +298,12 @@
public Expression createExpression(String expression, Info info)
throws ParseException {
// Parse the expression
- JexlNode tree = parse(expression, info);
+ ASTJexlScript tree = parse(expression, info);
if (tree.jjtGetNumChildren() > 1) {
logger.warn("The JEXL Expression created will be a reference"
+ " to the first expression from the supplied script: \"" + expression
+ "\" ");
}
- JexlNode node = tree.jjtGetChild(0);
- return new ExpressionImpl(this, expression, node);
+ return new ExpressionImpl(this, expression, tree);
}
/**
@@ -332,12 +331,9 @@
if (scriptText == null) {
throw new NullPointerException("scriptText is null");
}
- JexlNode script = parse(scriptText, info);
- if (script instanceof ASTJexlScript) {
- return new ScriptImpl(this, scriptText, (ASTJexlScript) script);
- } else {
- throw new IllegalStateException("Parsed script is not an ASTJexlScript");
- }
+ // Parse the expression
+ ASTJexlScript tree = parse(scriptText, info);
+ return new ExpressionImpl(this, scriptText, tree);
}
/**
@@ -540,12 +536,12 @@
* @param cacheSize the cache size, must be > 0
* @return a Map usable as a cache bounded to the given size
*/
- protected Map<String, JexlNode> createCache(final int cacheSize) {
- return new java.util.LinkedHashMap<String, JexlNode>(cacheSize, LOAD_FACTOR,
true) {
+ protected Map<String, ASTJexlScript> createCache(final int cacheSize) {
+ return new java.util.LinkedHashMap<String, ASTJexlScript>(cacheSize, LOAD_FACTOR,
true) {
/** Serial version UID. */
private static final long serialVersionUID = 3801124242820219131L;
@Override
- protected boolean removeEldestEntry(Map.Entry<String, JexlNode> eldest)
{
+ protected boolean removeEldestEntry(Map.Entry<String, ASTJexlScript> eldest)
{
return size() > cacheSize;
}
};
@@ -558,9 +554,9 @@
* @return the parsed tree
* @throws ParseException if any error occured during parsing
*/
- protected JexlNode parse(CharSequence expression, Info info) throws ParseException {
+ protected ASTJexlScript parse(CharSequence expression, Info info) throws ParseException
{
String expr = cleanExpression(expression);
- JexlNode tree = null;
+ ASTJexlScript tree = null;
synchronized (parser) {
logger.debug("Parsing expression: " + expression);
if (cache != null) {
Modified: commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/JexlTestCase.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/JexlTestCase.java?rev=809315&r1=809314&r2=809315&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/JexlTestCase.java
(original)
+++ commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/JexlTestCase.java
Sun Aug 30 11:29:27 2009
@@ -17,6 +17,7 @@
package org.apache.commons.jexl;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
@@ -24,17 +25,21 @@
import java.util.ArrayList;
import org.apache.commons.jexl.parser.JexlNode;
+import org.apache.commons.jexl.parser.ASTJexlScript;
import org.apache.commons.jexl.parser.ParseException;
import junit.framework.TestCase;
+
/**
- * Implements a runTest method to dynamically invoke a test,
+ * Implements runTest methods to dynamically instantiate and invoke a test,
* wrapping the call with setUp(), tearDown() calls.
* Eases the implementation of main methods to debug.
*/
public class JexlTestCase extends TestCase {
/** No parameters signature for test run. */
private static final Class<?>[] noParms = {};
+ /** String parameter signature for test run. */
+ private static final Class<?>[] stringParm = {String.class};
/** A default Jexl engine instance. */
protected final JexlEngine JEXL = new JexlEngine();
@@ -67,9 +72,9 @@
JexlEngine jdbg = new JexlEngine();
Debugger dbg = new Debugger();
// iterate over all expression in cache
- Iterator<Map.Entry<String,JexlNode>> inodes = jexl.cache.entrySet().iterator();
+ Iterator<Map.Entry<String,ASTJexlScript>> inodes = jexl.cache.entrySet().iterator();
while (inodes.hasNext()) {
- Map.Entry<String,JexlNode> entry = inodes.next();
+ Map.Entry<String,ASTJexlScript> entry = inodes.next();
JexlNode node = entry.getValue();
// recreate expr string from AST
dbg.debug(node);
@@ -78,7 +83,7 @@
// recreate expr from string
Expression exprdbg = jdbg.createExpression(expressiondbg);
// make arg cause become the root cause
- JexlNode root = ((ExpressionImpl) exprdbg).node;
+ JexlNode root = ((ExpressionImpl) exprdbg).script;
while (root.jjtGetParent() != null) {
root = root.jjtGetParent();
}
@@ -101,8 +106,8 @@
}
/**
- * Creates a list of all descendants of a node including itself.
- * @param node the node to flatten
+ * Creates a list of all descendants of a script including itself.
+ * @param script the script to flatten
* @return the descendants-and-self list
*/
private static ArrayList<JexlNode> flatten(JexlNode node) {
@@ -112,9 +117,9 @@
}
/**
- * Recursively adds all children of a node to the list of descendants.
+ * Recursively adds all children of a script to the list of descendants.
* @param list the list of descendants to add to
- * @param node the node & descendants to add
+ * @param script the script & descendants to add
*/
private static void flatten(List<JexlNode> list, JexlNode node) {
int nc = node.jjtGetNumChildren();
@@ -127,8 +132,8 @@
/**
* Checks the equality of 2 nodes by comparing all their descendants.
* Descendants must have the same class and same image if non null.
- * @param lhs the left node
- * @param rhs the right node
+ * @param lhs the left script
+ * @param rhs the right script
* @return null if true, a reason otherwise
*/
private static String checkEquals(JexlNode lhs, JexlNode rhs) {
@@ -156,6 +161,11 @@
return null;
}
+ /**
+ * Dynamically runs a test method.
+ * @param name the test method to run
+ * @throws Exception if anything goes wrong
+ */
public void runTest(String name) throws Exception {
if ("runTest".equals(name)) {
return;
@@ -176,8 +186,52 @@
}
}
- /*public void testRunTest() throws Exception {
- new JexlTestCase().runTest("runTest");
- }*/
+ /**
+ * Instantiate and runs a test method; useful for debugging purpose.
+ * For instance:
+ * <code>
+ * public static void main(String[] args) throws Exception {
+ * runTest("BitwiseOperatorTest","testAndVariableNumberCoercion");
+ * }
+ * </code>
+ * @param tname the test class name
+ * @param mname the test class method
+ * @throws Exception
+ */
+ public static void runTest(String tname, String mname) throws Exception {
+ String testClassName = "org.apache.commons.jexl."+tname;
+ Class<JexlTestCase> clazz = null;
+ JexlTestCase test = null;
+ // find the class
+ try {
+ clazz = (Class<JexlTestCase>) Class.forName(testClassName);
+ }
+ catch(ClassNotFoundException xclass) {
+ fail("no such class: " + testClassName);
+ return;
+ }
+ // find ctor & instantiate
+ Constructor<JexlTestCase> ctor = null;
+ try {
+ ctor = clazz.getConstructor(stringParm);
+ test = ctor.newInstance("debug");
+ }
+ catch(NoSuchMethodException xctor) {
+ // instantiate default class ctor
+ try {
+ test = clazz.newInstance();
+ }
+ catch(Exception xany) {
+ fail("cant instantiate test: " + xany);
+ return;
+ }
+ }
+ catch(Exception xany) {
+ fail("cant instantiate test: " + xany);
+ return;
+ }
+ // Run the test
+ test.runTest(mname);
+ }
}
|