commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hen...@apache.org
Subject svn commit: r927903 - in /commons/proper/jexl/trunk/src: main/java/org/apache/commons/jexl2/ main/java/org/apache/commons/jexl2/parser/ test/java/org/apache/commons/jexl2/
Date Fri, 26 Mar 2010 15:08:12 GMT
Author: henrib
Date: Fri Mar 26 15:08:12 2010
New Revision: 927903

URL: http://svn.apache.org/viewvc?rev=927903&view=rev
Log:
Fix JEXL-100;
Added JexlNode.Literal<T> to improve cache abilities and usage, used as base for AST{Integer,String}Literal;
Reviewed assignment and reference related code to improve antish variable handling;
Added related tests and improve coverage

Added:
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTIntegerLiteral.java
  (with props)
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTStringLiteral.java
  (with props)
Modified:
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/JexlNode.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArrayAccessTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/AssignTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/IssuesTest.java

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java?rev=927903&r1=927902&r2=927903&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java Fri
Mar 26 15:08:12 2010
@@ -348,8 +348,12 @@ public class Interpreter implements Pars
         int numChildren = node.jjtGetNumChildren();
         for (int i = 1; i < numChildren; i++) {
             JexlNode nindex = node.jjtGetChild(i);
-            Object index = nindex.jjtAccept(this, null);
-            object = getAttribute(object, index, nindex);
+            if (nindex instanceof JexlNode.Literal<?>) {
+                object = nindex.jjtAccept(this, object);
+            } else {
+                Object index = nindex.jjtAccept(this, null);
+                object = getAttribute(object, index, nindex);
+            }
         }
 
         return object;
@@ -415,34 +419,13 @@ public class Interpreter implements Pars
         }
         // 2: last objectNode will perform assignement in all cases
         propertyNode = left.jjtGetChild(last);
+        boolean antVar = false;
         if (propertyNode instanceof ASTIdentifier) {
             property = ((ASTIdentifier) propertyNode).image;
-            // deal with ant variable
-            if (isVariable && object == null) {
-                if (variableName != null) {
-                    if (last > 0) {
-                        variableName.append('.');
-                    }
-                    variableName.append(property);
-                    property = variableName.toString();
-                }
-                context.set(String.valueOf(property), right);
-                return right;
-            }
+            antVar = true;
         } else if (propertyNode instanceof ASTIntegerLiteral) {
-            property = visit((ASTIntegerLiteral) propertyNode, null);
-            // deal with ant variable
-            if (isVariable && object == null) {
-                if (variableName != null) {
-                    if (last > 0) {
-                        variableName.append('.');
-                    }
-                    variableName.append(property);
-                    property = variableName.toString();
-                }
-                context.set(String.valueOf(property), right);
-                return right;
-            }
+            property = ((ASTIntegerLiteral) propertyNode).getLiteral();
+            antVar = true;
         } else if (propertyNode instanceof ASTArrayAccess) {
             // first objectNode is the identifier
             objectNode = propertyNode;
@@ -458,13 +441,31 @@ public class Interpreter implements Pars
             last = narray.jjtGetNumChildren() - 1;
             for (int i = 1; i < last; i++) {
                 objectNode = narray.jjtGetChild(i);
-                Object index = objectNode.jjtAccept(this, null);
-                object = getAttribute(object, index, objectNode);
+                if (objectNode instanceof JexlNode.Literal<?>) {
+                    object = objectNode.jjtAccept(this, object);
+                } else {
+                    Object index = objectNode.jjtAccept(this, null);
+                    object = getAttribute(object, index, objectNode);
+                }
             }
             property = narray.jjtGetChild(last).jjtAccept(this, null);
         } else {
             throw new JexlException(objectNode, "illegal assignment form");
         }
+        // deal with ant variable; set context
+        if (antVar) {
+            if (isVariable && object == null) {
+                if (variableName != null) {
+                    if (last > 0) {
+                        variableName.append('.');
+                    }
+                    variableName.append(property);
+                    property = variableName.toString();
+                }
+                context.set(String.valueOf(property), right);
+                return right;
+            }
+        }
         if (property == null) {
             // no property, we fail
             throw new JexlException(propertyNode, "property is null");
@@ -574,12 +575,12 @@ public class Interpreter implements Pars
         if (o.getClass().isArray() && ((Object[]) o).length == 0) {
             return Boolean.TRUE;
         }
-        if (o instanceof Collection<?> && ((Collection<?>) o).isEmpty())
{
-            return Boolean.TRUE;
+        if (o instanceof Collection<?>) {
+            return ((Collection<?>) o).isEmpty()? Boolean.TRUE : Boolean.FALSE;
         }
         // Map isn't a collection
-        if (o instanceof Map<?, ?> && ((Map<?, ?>) o).isEmpty()) {
-            return Boolean.TRUE;
+        if (o instanceof Map<?, ?>) {
+            return ((Map<?,?>) o).isEmpty()? Boolean.TRUE : Boolean.FALSE;
         }
         return Boolean.FALSE;
     }
@@ -602,8 +603,8 @@ public class Interpreter implements Pars
 
     /** {@inheritDoc} */
     public Object visit(ASTFloatLiteral node, Object data) {
-        Float value = (Float) node.jjtGetValue();
-        if (value == null) {
+        Object value = node.jjtGetValue();
+        if (!(value instanceof Float)) {
             value = Float.valueOf(node.image);
             node.jjtSetValue(value);
         }
@@ -726,15 +727,9 @@ public class Interpreter implements Pars
     /** {@inheritDoc} */
     public Object visit(ASTIntegerLiteral node, Object data) {
         if (data != null) {
-            Integer value = Integer.valueOf(node.image);
-            return getAttribute(data, value, node);
-        }
-        Integer value = (Integer) node.jjtGetValue();
-        if (value == null) {
-            value = Integer.valueOf(node.image);
-            node.jjtSetValue(value);
+            return getAttribute(data, node.getLiteral(), node);
         }
-        return value;
+        return node.getLiteral();
     }
 
     /** {@inheritDoc} */
@@ -1044,15 +1039,20 @@ public class Interpreter implements Pars
         int v = 0;
         for (int c = 0; c < numChildren; c++) {
             JexlNode theNode = node.jjtGetChild(c);
-            isVariable &= (theNode instanceof ASTIdentifier);
-            result = theNode.jjtAccept(this, result);
+            // integer literals may be part of an antish var name only if no bean was found
so far
+            if (result == null && theNode instanceof ASTIntegerLiteral) {
+                isVariable &= v > 0;
+            } else {
+                isVariable &= (theNode instanceof ASTIdentifier);
+                result = theNode.jjtAccept(this, result);
+            }
             // if we get null back a result, check for an ant variable
             if (result == null && isVariable) {
                 if (v == 0) {
                     variableName = new StringBuilder(node.jjtGetChild(0).image);
                     v = 1;
                 }
-                for(; v <= c; ++v) {
+                for (; v <= c; ++v) {
                     variableName.append('.');
                     variableName.append(node.jjtGetChild(v).image);
                 }
@@ -1061,8 +1061,8 @@ public class Interpreter implements Pars
         }
         if (result == null) {
             if (isVariable
-                && !(node.jjtGetParent() instanceof ASTTernaryNode)
-                && !context.has(variableName.toString())) {
+                    && !(node.jjtGetParent() instanceof ASTTernaryNode)
+                    && !context.has(variableName.toString())) {
                 JexlException xjexl = new JexlException(node, "undefined variable " + variableName.toString());
                 return unknownVariable(xjexl);
             }
@@ -1088,6 +1088,9 @@ public class Interpreter implements Pars
 
     /** {@inheritDoc} */
     public Object visit(ASTStringLiteral node, Object data) {
+        if (data != null) {
+            return getAttribute(data, node.getLiteral(), node);
+        }
         return node.image;
     }
 

Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTIntegerLiteral.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTIntegerLiteral.java?rev=927903&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTIntegerLiteral.java
(added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTIntegerLiteral.java
Fri Mar 26 15:08:12 2010
@@ -0,0 +1,42 @@
+/*
+ * 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.jexl2.parser;
+
+public class ASTIntegerLiteral extends JexlNode implements JexlNode.Literal<Integer>
{
+    /** The type literal value. */
+    private Integer literal;
+
+    public ASTIntegerLiteral(int id) {
+        super(id);
+    }
+
+    public ASTIntegerLiteral(Parser p, int id) {
+        super(p, id);
+    }
+
+    public Integer getLiteral() {
+        if (literal == null) {
+            literal = Integer.valueOf(image);
+        }
+        return literal;
+    }
+
+    /** Accept the visitor. **/
+    public Object jjtAccept(ParserVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}

Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTIntegerLiteral.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTStringLiteral.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTStringLiteral.java?rev=927903&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTStringLiteral.java
(added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTStringLiteral.java
Fri Mar 26 15:08:12 2010
@@ -0,0 +1,37 @@
+/*
+ * 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.jexl2.parser;
+
+public class ASTStringLiteral extends JexlNode implements JexlNode.Literal<String>
{
+    
+    public ASTStringLiteral(int id) {
+        super(id);
+    }
+
+    public ASTStringLiteral(Parser p, int id) {
+        super(p, id);
+    }
+
+    public String getLiteral() {
+        return image;
+    }
+
+    /** Accept the visitor. **/
+    public Object jjtAccept(ParserVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}

Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/ASTStringLiteral.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/JexlNode.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/JexlNode.java?rev=927903&r1=927902&r2=927903&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/JexlNode.java
(original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/JexlNode.java
Fri Mar 26 15:08:12 2010
@@ -24,6 +24,13 @@ import org.apache.commons.jexl2.JexlInfo
  * @since 2.0
  */
 public abstract class JexlNode extends SimpleNode implements JexlInfo {
+    /** A marker interface for literals.
+     * @param <T> the literal type
+     */
+    public interface Literal<T> {
+        T getLiteral();
+    }
+
     /** token value. */
     public String image;
 

Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArrayAccessTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArrayAccessTest.java?rev=927903&r1=927902&r2=927903&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArrayAccessTest.java
(original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArrayAccessTest.java
Fri Mar 26 15:08:12 2010
@@ -123,7 +123,7 @@ public class ArrayAccessTest extends Jex
         asserter.assertExpression("foo.array[1]", GET_METHOD_ARRAY[1]);
         asserter.assertExpression("foo.array.1", GET_METHOD_ARRAY[1]);
         asserter.assertExpression("foo.array2[1][1]", GET_METHOD_ARRAY2[1][1]);
-        // asserter.assertExpression("foo.array2.1.1", GET_METHOD_ARRAY2[1][1]);
+        asserter.assertExpression("foo.array2[1].1", GET_METHOD_ARRAY2[1][1]);
     }
     
     // This is JEXL-26
@@ -133,9 +133,11 @@ public class ArrayAccessTest extends Jex
         asserter.setVariable("objects", objects);
         asserter.setVariable("status", "Enabled");
         asserter.assertExpression("objects[1].status", null);
+        asserter.assertExpression("objects.1.status", null);
         
         asserter.setVariable("base.status", "Ok");
         asserter.assertExpression("base.objects[1].status", null);
+        asserter.assertExpression("base.objects.1.status", null);
     }
 
     public void testArrayMethods() throws Exception {
@@ -148,4 +150,70 @@ public class ArrayAccessTest extends Jex
         asserter.assertExpression("objects.set(1, 'dion')", "array");
         asserter.assertExpression("objects[1]", "dion");
     }
+
+    public void testArrayArray() throws Exception {
+        Integer i42 = Integer.valueOf(42);
+        Integer i43 = Integer.valueOf(43);
+        String s42 = "fourty-two";
+        String s43 = "fourty-three";
+        Object[] foo = new Object[3];
+        foo[0] = foo;
+        foo[1] = i42;
+        foo[2] = s42;
+        asserter.setVariable("foo", foo);
+        asserter.setVariable("zero", 0);
+        asserter.setVariable("one", 1);
+        asserter.setVariable("two", 2);
+        for(int l = 0; l < 2; ++l) {
+            asserter.assertExpression("foo[0]", foo);
+            asserter.assertExpression("foo[0][0]", foo);
+            asserter.assertExpression("foo[1]", foo[1]);
+            asserter.assertExpression("foo[0][1]", foo[1]);
+            asserter.assertExpression("foo[0][1] = 43", i43);
+            asserter.assertExpression("foo[0][1]", i43);
+            asserter.assertExpression("foo[0][1] = 42", i42);
+            asserter.assertExpression("foo[0][1]", i42);
+            asserter.assertExpression("foo[0][0][1]", foo[1]);
+            asserter.assertExpression("foo[0][0][1] = 43", i43);
+            asserter.assertExpression("foo[0][0][1]", i43);
+            asserter.assertExpression("foo[0][0][1] = 42", i42);
+            asserter.assertExpression("foo[0][0][1]", i42);
+            asserter.assertExpression("foo[2]", foo[2]);
+            asserter.assertExpression("foo[0][2]", foo[2]);
+            asserter.assertExpression("foo[0][2] = 'fourty-three'", s43);
+            asserter.assertExpression("foo[0][2]", s43);
+            asserter.assertExpression("foo[0][2] = 'fourty-two'", s42);
+            asserter.assertExpression("foo[0][2]", s42);
+            asserter.assertExpression("foo[0][0][2]", foo[2]);
+            asserter.assertExpression("foo[0][0][2] = 'fourty-three'", s43);
+            asserter.assertExpression("foo[0][0][2]", s43);
+            asserter.assertExpression("foo[0][0][2] = 'fourty-two'", s42);
+            asserter.assertExpression("foo[0][0][2]", s42);
+
+            asserter.assertExpression("foo[zero]", foo);
+            asserter.assertExpression("foo[zero][zero]", foo);
+            asserter.assertExpression("foo[one]", foo[1]);
+            asserter.assertExpression("foo[zero][one]", foo[1]);
+            asserter.assertExpression("foo[zero][one] = 43", i43);
+            asserter.assertExpression("foo[zero][one]", i43);
+            asserter.assertExpression("foo[zero][one] = 42", i42);
+            asserter.assertExpression("foo[zero][one]", i42);
+            asserter.assertExpression("foo[zero][zero][one]", foo[1]);
+            asserter.assertExpression("foo[zero][zero][one] = 43", i43);
+            asserter.assertExpression("foo[zero][zero][one]", i43);
+            asserter.assertExpression("foo[zero][zero][one] = 42", i42);
+            asserter.assertExpression("foo[zero][zero][one]", i42);
+            asserter.assertExpression("foo[two]", foo[2]);
+            asserter.assertExpression("foo[zero][two]", foo[2]);
+            asserter.assertExpression("foo[zero][two] = 'fourty-three'", s43);
+            asserter.assertExpression("foo[zero][two]", s43);
+            asserter.assertExpression("foo[zero][two] = 'fourty-two'", s42);
+            asserter.assertExpression("foo[zero][two]", s42);
+            asserter.assertExpression("foo[zero][zero][two]", foo[2]);
+            asserter.assertExpression("foo[zero][zero][two] = 'fourty-three'", s43);
+            asserter.assertExpression("foo[zero][zero][two]", s43);
+            asserter.assertExpression("foo[zero][zero][two] = 'fourty-two'", s42);
+            asserter.assertExpression("foo[zero][zero][two]", s42);
+        }
+    }
 }
\ No newline at end of file

Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/AssignTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/AssignTest.java?rev=927903&r1=927902&r2=927903&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/AssignTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/AssignTest.java Fri Mar
26 15:08:12 2010
@@ -85,6 +85,16 @@ public class AssignTest extends JexlTest
         o = check.evaluate(jc);
         assertEquals("Result is not 10", new Integer(10), o);
     }
+
+    public void testAntishInteger() throws Exception {
+        Expression assign = ENGINE.createExpression("froboz.0 = 10");
+        Expression check = ENGINE.createExpression("froboz.0");
+        JexlContext jc = new MapContext();
+        Object o = assign.evaluate(jc);
+        assertEquals("Result is not 10", new Integer(10), o);
+        o = check.evaluate(jc);
+        assertEquals("Result is not 10", new Integer(10), o);
+    }
     
     public void testBeanish() throws Exception {
         Expression assign = ENGINE.createExpression("froboz.value = 10");

Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/IssuesTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/IssuesTest.java?rev=927903&r1=927902&r2=927903&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/IssuesTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/IssuesTest.java Fri Mar
26 15:08:12 2010
@@ -376,13 +376,18 @@ public class IssuesTest extends JexlTest
     public void test100() throws Exception {
         JexlEngine jexl = new JexlEngine();
         jexl.setCache(4);
-        String expr = "foo[0]";
         JexlContext ctxt = new MapContext();
         int[] foo = { 42 };
         ctxt.set("foo", foo);
-
+        Object value ;
         for(int l = 0; l < 2; ++l) {
-            Object value = jexl.createExpression(expr).evaluate(ctxt);
+            value = jexl.createExpression("foo[0]").evaluate(ctxt);
+            assertEquals(42, value);
+            value = jexl.createExpression("foo[0] = 43").evaluate(ctxt);
+            assertEquals(43, value);
+            value = jexl.createExpression("foo.0").evaluate(ctxt);
+            assertEquals(43, value);
+            value = jexl.createExpression("foo.0 = 42").evaluate(ctxt);
             assertEquals(42, value);
         }
     }



Mime
View raw message