Author: grobmeier Date: Sat Jun 13 17:45:23 2009 New Revision: 784442 URL: http://svn.apache.org/viewvc?rev=784442&view=rev Log: JEXL-55: Bean & ant-ish like assignment, Ternary operator, Exception handling revisited, ScriptFactory, ExpressionFactory refactored
Contributed by Henri Biestro Added: commons/proper/jexl/branches/2.0/maven-eclipse.xml commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Debugger.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/JexlEngine.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/JexlException.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/logging/ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/logging/LogManager.java commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/AssignTest.java commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/util/ commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/util/introspection/ commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/util/introspection/MethodKeyTest.java Modified: commons/proper/jexl/branches/2.0/build.xml commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Arithmetic.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Expression.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/ExpressionFactory.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/ExpressionImpl.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Interpreter.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/JexlArithmetic.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/ScriptFactory.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/ScriptImpl.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/parser/JEXLNode.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/parser/Parser.jjt commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/parser/VisitorAdapter.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/BooleanPropertyExecutor.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/Coercion.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapGetExecutor.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertyExecutor.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/ClassMap.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/Introspector.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/IntrospectorBase.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/MethodMap.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/Uberspect.java commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/UberspectImpl.java commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/BlockTest.java commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/JexlTest.java commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ParseFailuresTest.java commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ScriptFactoryTest.java commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/ScriptTest.java Modified: commons/proper/jexl/branches/2.0/build.xml URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/build.xml?rev=784442&r1=784441&r2=784442&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/build.xml (original) +++ commons/proper/jexl/branches/2.0/build.xml Sat Jun 13 17:45:23 2009 @@ -1,8 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!--build.xml generated by maven from project.xml version 1.1.1-SNAPSHOT - on date August 12 2006, time 0018--> - <project default="jar" name="commons-jexl" basedir="."> <property name="defaulttargetdir" value="target"> </property> @@ -16,11 +13,15 @@ </property> <property name="testreportdir" value="target/test-reports"> </property> + <property name="gensrcdir" value="target/generated-src"> + </property> <property name="distdir" value="dist"> </property> <property name="javadocdir" value="dist/docs/api"> </property> - <property name="final.name" value="commons-jexl-1.1.1-SNAPSHOT"> + <property name="javaccdir" value="${libdir}"> + </property> + <property name="final.name" value="commons-jexl-2.0-SNAPSHOT"> </property> <path id="build.classpath"> <fileset dir="${libdir}"> @@ -36,10 +37,29 @@ </equals> </condition> <!--Test if JUNIT is present in ANT classpath--> - +<property name="Junit.present" value="true"/> +<!-- <available property="Junit.present" classname="junit.framework.Test"> </available> + --> </target> + +<target name="dojavacc" description="Generate the parser classes"> + <mkdir dir="${gensrcdir}/org/apache/commons/jexl/parser"> + </mkdir> + <jjtree + target="src/java/org/apache/commons/jexl/parser/Parser.jjt" + outputdirectory="${gensrcdir}/org/apache/commons/jexl/parser" + javacchome="${javaccdir}" + nodeusesparser="true"> + </jjtree> + <javacc + target="${gensrcdir}/org/apache/commons/jexl/parser/Parser.jj" + outputdirectory="${gensrcdir}/org/apache/commons/jexl/parser" + javacchome="${javaccdir}"> + </javacc> + </target> + <target name="compile" description="o Compile the code" depends="get-deps"> <mkdir dir="${classesdir}"> </mkdir> @@ -47,6 +67,8 @@ <src> <pathelement location="src/java"> </pathelement> + <pathelement location="${gensrcdir}"> + </pathelement> </src> <classpath refid="build.classpath"> </classpath> @@ -142,7 +164,7 @@ </tstamp> <property name="copyright" value="Copyright &copy; The Apache Software Foundation. All Rights Reserved."> </property> - <property name="title" value="Commons JEXL 1.1.1-SNAPSHOT API"> + <property name="title" value="Commons JEXL 2.0-SNAPSHOT API"> </property> <javadoc use="true" private="true" destdir="${javadocdir}" author="true" version="true" sourcepath="src/java" packagenames="org.apache.commons.jexl.*"> <classpath> @@ -160,6 +182,8 @@ </get> <get dest="${libdir}/junit-3.8.1.jar" usetimestamp="true" ignoreerrors="true" src="http://www.ibiblio.org/maven/junit/jars/junit-3.8.1.jar"> </get> + <get dest="${libdir}/javacc.jar" usetimestamp="true" ignoreerrors="true" src="http://www.ibiblio.org/maven/javacc/jars/javacc-4.0.jar"> + </get> </target> <target name="install-maven"> <get dest="${user.home}/maven-install-latest.jar" usetimestamp="true" src="${repo}/maven/maven-install-latest.jar"> Added: commons/proper/jexl/branches/2.0/maven-eclipse.xml URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/maven-eclipse.xml?rev=784442&view=auto ============================================================================== --- commons/proper/jexl/branches/2.0/maven-eclipse.xml (added) +++ commons/proper/jexl/branches/2.0/maven-eclipse.xml Sat Jun 13 17:45:23 2009 @@ -0,0 +1,8 @@ +<project default="copy-resources"> + <target name="init"/> + <target name="copy-resources" depends="init"> + <copy todir="target/classes/META-INF" filtering="false"> + <fileset dir="." includes="NOTICE.txt|LICENSE.txt"/> + </copy> + </target> +</project> \ No newline at end of file Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Arithmetic.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Arithmetic.java?rev=784442&r1=784441&r2=784442&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Arithmetic.java (original) +++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Arithmetic.java Sat Jun 13 17:45:23 2009 @@ -1,67 +1,167 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.jexl; -/** - * Pluggable arithmetic operators. - */ -interface Arithmetic { - - /** - * Add two values together. - * - * @param left first value - * @param right second value - * @return left + right. - */ - Object add(Object left, Object right); - - /** - * Divide the left value by the right. - * - * @param left first value - * @param right second value - * @return left - right. - */ - Object divide(Object left, Object right); - - /** - * left value mod right. - * - * @param left first value - * @param right second value - * @return left mod right. - */ - Object mod(Object left, Object right); - - /** - * Multiply the left value by the right. - * - * @param left first value - * @param right second value - * @return left * right. - */ - Object multiply(Object left, Object right); - - /** - * Subtract the right value from the left. - * - * @param left first value - * @param right second value - * @return left + right. - */ - Object subtract(Object left, Object right); +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.jexl; +/** + * Pluggable arithmetic, coercion & comparison operators. + */ +public interface Arithmetic { + + /** + * Add two values together. + * + * @param left first value + * @param right second value + * @return left + right. + */ + Object add(Object left, Object right); + + /** + * Divide the left value by the right. + * + * @param left first value + * @param right second value + * @return left - right. + */ + Object divide(Object left, Object right); + + /** + * left value mod right. + * + * @param left first value + * @param right second value + * @return left mod right. + */ + Object mod(Object left, Object right); + + /** + * Multiply the left value by the right. + * + * @param left first value + * @param right second value + * @return left * right. + */ + Object multiply(Object left, Object right); + + /** + * Subtract the right value from the left. + * + * @param left first value + * @param right second value + * @return left + right. + */ + Object subtract(Object left, Object right); + + /** + * Coerce an object into a boolean. + * @param arg the value to convert + * @return a boolean + */ + boolean toBoolean(Object arg); + + /** + * Coerce an object into an integer. + * @param arg the object to coerce + * @return an int + */ + int toInteger(Object arg); + + /** + * Coerce an object into a long. + * @param arg the object to coerce + * @return a long + */ + long toLong(Object arg); + + /** + * Coerce an object into a double. + * @param arg the object to coerce + * @return a double + */ + double toDouble(Object arg); + + /** + * Coerce an object into a big integer. + * @param arg the object to coerce + * @return a big integer + */ + java.math.BigInteger toBigInteger(Object arg); + + /** + * Coerce an object into a big decimal. + * @param arg the object to coerce + * @return a big decimal + */ + java.math.BigDecimal toBigDecimal(Object arg); + + /** + * Given a Number, return back the value using the smallest type the result + * will fit into. This works hand in hand with parameter 'widening' in java + * method calls, e.g. a call to substring(int,int) with an int and a long + * will fail, but a call to substring(int,int) with an int and a short will + * succeed. + * + * @param original the original number. + * @return a value of the smallest type the original number will fit into. + * @since 1.1 + */ + public Number narrow(Number original); + + /** + * Test if left == right. + * + * @param left first value + * @param right second value + * @return test result. + */ + boolean equals(Object left, Object right); + + /** + * Test if left < right. + * + * @param left first value + * @param right second value + * @return test result. + */ + boolean lessThan(Object left, Object right); + + /** + * Test if left > right. + * + * @param left first value + * @param right second value + * @return test result. + */ + boolean greaterThan(Object left, Object right); + + /** + * Test if left <= right. + * + * @param left first value + * @param right second value + * @return test result. + */ + boolean lessThanOrEqual(Object left, Object right); + + /** + * Test if left >= right. + * + * @param left first value + * @param right second value + * @return test result. + */ + boolean greaterThanOrEqual(Object left, Object right); } \ No newline at end of file Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Debugger.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Debugger.java?rev=784442&view=auto ============================================================================== --- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Debugger.java (added) +++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Debugger.java Sat Jun 13 17:45:23 2009 @@ -0,0 +1,517 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.jexl; + +import org.apache.commons.jexl.parser.ASTAddNode; +import org.apache.commons.jexl.parser.ASTAndNode; +import org.apache.commons.jexl.parser.ASTArrayAccess; +import org.apache.commons.jexl.parser.ASTAssignment; +import org.apache.commons.jexl.parser.ASTBitwiseAndNode; +import org.apache.commons.jexl.parser.ASTBitwiseComplNode; +import org.apache.commons.jexl.parser.ASTBitwiseOrNode; +import org.apache.commons.jexl.parser.ASTBitwiseXorNode; +import org.apache.commons.jexl.parser.ASTBlock; +import org.apache.commons.jexl.parser.ASTDivNode; +import org.apache.commons.jexl.parser.ASTEQNode; +import org.apache.commons.jexl.parser.ASTEmptyFunction; +import org.apache.commons.jexl.parser.ASTExpression; +import org.apache.commons.jexl.parser.ASTExpressionExpression; +import org.apache.commons.jexl.parser.ASTFalseNode; +import org.apache.commons.jexl.parser.ASTFloatLiteral; +import org.apache.commons.jexl.parser.ASTForeachStatement; +import org.apache.commons.jexl.parser.ASTGENode; +import org.apache.commons.jexl.parser.ASTGTNode; +import org.apache.commons.jexl.parser.ASTIdentifier; +import org.apache.commons.jexl.parser.ASTIfStatement; +import org.apache.commons.jexl.parser.ASTIntegerLiteral; +import org.apache.commons.jexl.parser.ASTJexlScript; +import org.apache.commons.jexl.parser.ASTLENode; +import org.apache.commons.jexl.parser.ASTLTNode; +import org.apache.commons.jexl.parser.ASTMapEntry; +import org.apache.commons.jexl.parser.ASTMapLiteral; +import org.apache.commons.jexl.parser.ASTMethod; +import org.apache.commons.jexl.parser.ASTModNode; +import org.apache.commons.jexl.parser.ASTMulNode; +import org.apache.commons.jexl.parser.ASTNENode; +import org.apache.commons.jexl.parser.ASTNotNode; +import org.apache.commons.jexl.parser.ASTNullLiteral; +import org.apache.commons.jexl.parser.ASTOrNode; +import org.apache.commons.jexl.parser.ASTReference; +import org.apache.commons.jexl.parser.ASTReferenceExpression; +import org.apache.commons.jexl.parser.ASTSizeFunction; +import org.apache.commons.jexl.parser.ASTSizeMethod; +import org.apache.commons.jexl.parser.ASTStatementExpression; +import org.apache.commons.jexl.parser.ASTStringLiteral; +import org.apache.commons.jexl.parser.ASTSubtractNode; +import org.apache.commons.jexl.parser.ASTTernaryNode; +import org.apache.commons.jexl.parser.ASTTrueNode; +import org.apache.commons.jexl.parser.ASTUnaryMinusNode; +import org.apache.commons.jexl.parser.ASTWhileStatement; +import org.apache.commons.jexl.parser.Node; +import org.apache.commons.jexl.parser.SimpleNode; + +import org.apache.commons.jexl.parser.ParserVisitor; +/** + * Helps pinpoint the cause of problems in expressions that fail during evaluation. + * It rebuilds an expression string from the tree and the start/end offsets of the cause + * in that string (TODO pretty print). + * This implies that exceptions during evaluation should allways carry the node that's causing + * the error. + */ +public class Debugger implements ParserVisitor { + StringBuilder builder; + Node cause; + int start = 0; + int end = 0; + + public Debugger() { + builder = new StringBuilder(); + cause = null; + start = 0; + end = 0; + } + + /** + * Seeks the location of an error cause (a node) in an expression. + * @return true if the cause was located, false otherwise + */ + public boolean debug(Node cause) { + builder = new StringBuilder(); + this.cause = cause; + // make arg cause become the root cause + Node root = cause; + while (root.jjtGetParent() != null) { + root = root.jjtGetParent(); + } + start = 0; + end = 0; + root.jjtAccept(this, null); + return start > 0; + } + + /** + * @return The rebuilt expression + */ + public String data() { + return builder.toString(); + } + + /** + * @return The starting offset location of the cause in the expression + */ + public int start() { + return start; + } + /** + * @return The end offset location of the cause in the expression + */ + public int end() { + return end; + } + + /** + * Checks if a child node is the cause to debug & adds its representation to the rebuilt expression + */ + private Object accept(Node node, Object data) { + if (node == cause) { + start = builder.length(); + } + Object value = node.jjtAccept(this, data); + if (node == cause) { + end = builder.length(); + } + return value; + } + + /** + * Checks if a terminal node is the the cause to debug & adds its representation to the rebuilt expression + */ + private Object check(Node node, String image, Object data) { + if (node == cause) { + start = builder.length(); + } + if (image != null) { + builder.append(image); + } else { + builder.append(node.toString()); + } + if (node == cause) { + end = builder.length(); + } + return data; + } + + /** + * Checks if the children of a node using infix notation is the cause to debug, + * adds their representation to the rebuilt expression + */ + private Object infixChildren(Node node, String infix, Object data) { + int num = node.jjtGetNumChildren(); + for (int i = 0; i < num; ++i) { + if (i > 0) { + builder.append(infix); + } + accept(node.jjtGetChild(i), data); + } + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTAddNode node, Object data) { + return infixChildren(node, " + ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTAndNode node, Object data) { + return infixChildren(node, " && ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTArrayAccess node, Object data) { + accept(node.jjtGetChild(0), data); + int num = node.jjtGetNumChildren(); + for (int i = 1; i < num; ++i) { + builder.append("["); + accept(node.jjtGetChild(i), data); + builder.append("]"); + } + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTAssignment node, Object data) { + return infixChildren(node, " = ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTBitwiseAndNode node, Object data) { + return infixChildren(node, " & ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTBitwiseComplNode node, Object data) { + builder.append("~"); + return accept(node.jjtGetChild(0), data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTBitwiseOrNode node, Object data) { + return infixChildren(node, " | ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTBitwiseXorNode node, Object data) { + return infixChildren(node, " ^ ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTBlock node, Object data) { + builder.append("{ "); + int num = node.jjtGetNumChildren(); + for (int i = 0; i < num; ++i) { + accept(node.jjtGetChild(0), data); + } + builder.append(" }"); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTDivNode node, Object data) { + return infixChildren(node, " / ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTEmptyFunction node, Object data) { + builder.append("empty("); + accept(node.jjtGetChild(0), data); + builder.append(")"); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTEQNode node, Object data) { + return infixChildren(node, " == ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTExpression node, Object data) { + int num = node.jjtGetNumChildren(); + for (int i = 0; i < num; ++i) { + accept(node.jjtGetChild(i), data); + } + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTExpressionExpression node, Object data) { + int num = node.jjtGetNumChildren(); + for (int i = 0; i < num; ++i) { + accept(node.jjtGetChild(i), data); + } + builder.append(";"); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTFalseNode node, Object data) { + return check(node, "false", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTFloatLiteral node, Object data) { + return check(node, node.image, data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTForeachStatement node, Object data) { + builder.append("foreach("); + accept(node.jjtGetChild(0), data); + builder.append(" in "); + accept(node.jjtGetChild(1), data); + builder.append(") "); + accept(node.jjtGetChild(2), data); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTGENode node, Object data) { + return infixChildren(node, " >= ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTGTNode node, Object data) { + return infixChildren(node, " > ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTIdentifier node, Object data) { + return check(node, node.image, data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTIfStatement node, Object data) { + builder.append("if("); + accept(node.jjtGetChild(0), data); + builder.append(") "); + accept(node.jjtGetChild(1), data); + if (node.jjtGetNumChildren() > 2) { + builder.append(" else "); + accept(node.jjtGetChild(2), data); + } + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTIntegerLiteral node, Object data) { + return check(node, node.image, data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTJexlScript node, Object data) { + int num = node.jjtGetNumChildren(); + for (int i = 0; i < num; ++i) { + accept(node.jjtGetChild(i), data); + } + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTLENode node, Object data) { + return infixChildren(node, " <= ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTLTNode node, Object data) { + return infixChildren(node, " < ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTMapEntry node, Object data) { + accept(node.jjtGetChild(0), data); + builder.append(" => "); + accept(node.jjtGetChild(1), data); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTMapLiteral node, Object data) { + int num = node.jjtGetNumChildren(); + builder.append("["); + accept(node.jjtGetChild(0), data); + for (int i = 1; i < num; ++i) { + builder.append(", "); + accept(node.jjtGetChild(i), data); + } + builder.append("]"); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTMethod node, Object data) { + int num = node.jjtGetNumChildren(); + accept(node.jjtGetChild(0), data); + builder.append("("); + for (int i = 1; i < num; ++i) { + if (i > 1) { + builder.append(", "); + } + accept(node.jjtGetChild(i), data); + } + builder.append(")"); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTModNode node, Object data) { + return infixChildren(node, " % ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTMulNode node, Object data) { + return infixChildren(node, " * ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTNENode node, Object data) { + return infixChildren(node, " != ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTNotNode node, Object data) { + builder.append("!"); + accept(node.jjtGetChild(0), data); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTNullLiteral node, Object data) { + check(node, "null", data); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTOrNode node, Object data) { + return infixChildren(node, " ||", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTReference node, Object data) { + int num = node.jjtGetNumChildren(); + accept(node.jjtGetChild(0), data); + for (int i = 1; i < num; ++i) { + builder.append("."); + accept(node.jjtGetChild(i), data); + } + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTReferenceExpression node, Object data) { + int num = node.jjtGetNumChildren(); + accept(node.jjtGetChild(0), data); + for (int i = 1; i < num; ++i) { + builder.append("."); + accept(node.jjtGetChild(i), data); + } + builder.append(";"); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTSizeFunction node, Object data) { + builder.append("size("); + accept(node.jjtGetChild(0), data); + builder.append(")"); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTSizeMethod node, Object data) { + check(node, "size()", data); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTStatementExpression node, Object data) { + int num = node.jjtGetNumChildren(); + for (int i = 0; i < num; ++i) { + accept(node.jjtGetChild(i), data); + if (i > 0) { + builder.append(";"); + } + } + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTStringLiteral node, Object data) { + String img = node.image.replace("'", "\\'"); + return check(node, "'" + img + "'", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTSubtractNode node, Object data) { + return infixChildren(node, " - ", data); + } + + /** {...@inheritdoc} */ + public Object visit(ASTTernaryNode node, Object data) { + accept(node.jjtGetChild(0), data); + if (node.jjtGetNumChildren() > 2) { + builder.append("? "); + accept(node.jjtGetChild(1), data); + builder.append(" : "); + accept(node.jjtGetChild(2), data); + } else { + builder.append("?:"); + accept(node.jjtGetChild(1), data); + + } + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTTrueNode node, Object data) { + check(node, "true", data); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTUnaryMinusNode node, Object data) { + builder.append("-"); + accept(node.jjtGetChild(0), data); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(ASTWhileStatement node, Object data) { + builder.append("while("); + accept(node.jjtGetChild(0), data); + builder.append(") "); + accept(node.jjtGetChild(1), data); + return data; + } + + /** {...@inheritdoc} */ + public Object visit(SimpleNode node, Object data) { + int num = node.jjtGetNumChildren(); + for (int i = 0; i < num; ++i) { + accept(node.jjtGetChild(i), data); + } + return data; + } +} Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Expression.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Expression.java?rev=784442&r1=784441&r2=784442&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Expression.java (original) +++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/Expression.java Sat Jun 13 17:45:23 2009 @@ -52,4 +52,9 @@ */ String getExpression(); + /** + * Returns the JEXL expression by reconstructing it from the parsed tree. + * @return the JEXL expression + */ + String dump(); } Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/ExpressionFactory.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/ExpressionFactory.java?rev=784442&r1=784441&r2=784442&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/ExpressionFactory.java (original) +++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/ExpressionFactory.java Sat Jun 13 17:45:23 2009 @@ -16,16 +16,7 @@ */ package org.apache.commons.jexl; -import java.io.StringReader; - import org.apache.commons.jexl.parser.ParseException; -import org.apache.commons.jexl.parser.Parser; -import org.apache.commons.jexl.parser.SimpleNode; -import org.apache.commons.jexl.parser.TokenMgrError; -import org.apache.commons.jexl.util.Introspector; -import org.apache.commons.jexl.util.introspection.Uberspect; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * <p> @@ -49,48 +40,11 @@ */ public class ExpressionFactory { /** - * The Log to which all ExpressionFactory messages will be logged. - */ - protected static final Log LOG = - LogFactory.getLog("org.apache.commons.jexl.ExpressionFactory"); - - /** - * The singleton ExpressionFactory also holds a single instance of - * {...@link Parser}. - * When parsing expressions, ExpressionFactory synchronizes on Parser. - */ - protected final Parser parser = - new Parser(new StringReader(";")); //$NON-NLS-1$ - - /** - * ExpressionFactory is a singleton and this is the private - * instance fulfilling that pattern. - */ - protected static final ExpressionFactory EF = new ExpressionFactory(); - - /** * Private constructor, the single instance is always obtained * with a call to getInstance(). */ - private ExpressionFactory() { - this(Introspector.getUberspect()); - } + private ExpressionFactory() {} - /** - * Creates an expression factory using the provided {...@link Uberspect}. - * @param uberspect to allow different introspection behaviour - */ - public ExpressionFactory(Uberspect uberspect) { - parser.setUberspect(uberspect); - } - - /** - * Returns the single instance of ExpressionFactory. - * @return the instance of ExpressionFactory. - */ - public static ExpressionFactory getInstance() { - return EF; - } /** * Creates an Expression from a String containing valid @@ -104,65 +58,7 @@ */ public static Expression createExpression(String expression) throws ParseException { - return getInstance().createNewExpression(expression); + return JexlEngine.DEFAULT.createExpression(expression); } - - /** - * Creates a new Expression based on the expression string. - * - * @param expression valid Jexl expression - * @return Expression - * @throws ParseException for malformed Jexl expression - */ - public Expression createNewExpression(final String expression) throws ParseException { - - String expr = cleanExpression(expression); - - // Parse the Expression - SimpleNode tree; - synchronized (parser) { - LOG.debug("Parsing expression: " + expr); - try { - tree = parser.parse(new StringReader(expr)); - } catch (TokenMgrError tme) { - throw new ParseException(tme.getMessage()); - } catch (ParseException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - if (tree.jjtGetNumChildren() > 1 && LOG.isWarnEnabled()) { - LOG.warn("The JEXL Expression created will be a reference" - + " to the first expression from the supplied script: \"" - + expression + "\" "); - } - - // Must be a simple reference, expression, statement or if, otherwise - // throw an exception. - SimpleNode node = (SimpleNode) tree.jjtGetChild(0); - - Interpreter interpreter = new Interpreter( - null, - Introspector.getUberspect(), - new JexlArithmetic()); - // TODO: remove this from the parser. - // interpreter.setUberspect(parser.getUberspect()); - return new ExpressionImpl(expression, node, interpreter); - } - - /** - * Trims the expression and adds a semi-colon if missing. - * @param expression to clean - * @return trimmed expression ending in a semi-colon - */ - private String cleanExpression(String expression) { - String expr = expression.trim(); - if (!expr.endsWith(";")) { - expr += ";"; - } - return expr; - } } Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/ExpressionImpl.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/ExpressionImpl.java?rev=784442&r1=784441&r2=784442&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/ExpressionImpl.java (original) +++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/ExpressionImpl.java Sat Jun 13 17:45:23 2009 @@ -49,6 +49,9 @@ */ protected SimpleNode node; + /** The engine for this expression. */ + protected final JexlEngine jexl; + /** The interpreter of the expression. */ protected Interpreter interpreter; @@ -59,17 +62,23 @@ * @param ref the parsed expression. * @param interp the interpreter to evaluate the expression */ - ExpressionImpl(String expr, SimpleNode ref, Interpreter interp) { + ExpressionImpl(JexlEngine engine, String expr, SimpleNode ref) { expression = expr; node = ref; - interpreter = interp; + jexl = engine; } /** * {...@inheritdoc} */ public Object evaluate(JexlContext context) throws Exception { - return interpreter.interpret(node, context); + Interpreter interpreter = jexl.createInterpreter(context); + return interpreter.interpret(node, jexl.isSilent()); + } + + public String dump() { + Debugger debug = new Debugger(); + return debug.debug(node)? debug.toString() : "/*?*/"; } /**