Author: markt
Date: Fri Jul 19 11:23:37 2013
New Revision: 1504834

URL: http://svn.apache.org/r1504834
Log:
Do the scanning to count nesting levels and presence of formal parameters just 
once.
Simplify the checks during getValue() using the results of this new scan.

Modified:
    tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java

Modified: tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java?rev=1504834&r1=1504833&r2=1504834&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java (original)
+++ tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java Fri Jul 19 
11:23:37 2013
@@ -29,6 +29,8 @@ import org.apache.el.util.MessageFactory
 
 public class AstLambdaExpression extends SimpleNode {
 
+    private NestedState nestedState = null;
+
     public AstLambdaExpression(int id) {
         super(id);
     }
@@ -36,40 +38,17 @@ public class AstLambdaExpression extends
     @Override
     public Object getValue(EvaluationContext ctx) throws ELException {
 
-        // Check;
-        // - that there are not more sets of method parameters than there are
-        //   nested lambda expressions
-        // - if any of the nested expressions declare formal parameters
+        // Correct evaluation requires knowledge of the whole set of nested
+        // expressions, not just the current expression
+        NestedState state = getNestedState();
+
+        // Check that there are not more sets of parameters than there are
+        // nested expressions.
         int methodParameterSetCount = jjtGetNumChildren() - 2;
-        boolean declaresParameters = false;
-        // We know this node is an expression
-        int lambdaExpressionCount = 1;
-        // child at index 1 is the expression
-        Node n = jjtGetChild(1);
-        while (n instanceof AstLambdaExpression) {
-            lambdaExpressionCount++;
-            if (n.jjtGetChild(0) instanceof AstLambdaParameters) {
-                if (!declaresParameters &&
-                        n.jjtGetChild(0).jjtGetNumChildren() > 0) {
-                    declaresParameters = true;
-                }
-                n = n.jjtGetChild(1);
-            } else {
-                n = null;
-            }
-        }
-        if (methodParameterSetCount > lambdaExpressionCount) {
+        if (methodParameterSetCount > state.getNestingCount()) {
             throw new ELException(MessageFactory.get(
                     "error.lambda.tooManyMethodParameterSets"));
         }
-        // Also need to check parents for declaration of formal parameters
-        n = parent;
-        while (!declaresParameters && n instanceof AstLambdaExpression) {
-            if (n.jjtGetChild(0).jjtGetNumChildren() > 0) {
-                declaresParameters = true;
-            }
-            n = n.jjtGetParent();
-        }
 
         // First child is always parameters even if there aren't any
         AstLambdaParameters formalParametersNode =
@@ -91,17 +70,27 @@ public class AstLambdaExpression extends
         le.setELContext(ctx);
 
         if (jjtGetNumChildren() == 2) {
-            if (formalParameters.isEmpty() && !declaresParameters) {
-                // No formal parameters or method parameters and not nested
-                // inside another lambda expression so invoke the expression.
-                return le.invoke(ctx, (Object[]) null);
-            } else {
-                // Has formal parameters but no method parameters or is a 
nested
-                // expression so return the expression for later evaluation
+            // No method parameters
+            // Can only invoke the expression if none of the lambda expressions
+            // in the nesting declare parameters
+            if (state.getHasFormalParameters()) {
                 return le;
+            } else {
+                return le.invoke(ctx, (Object[]) null);
             }
         }
 
+        /*
+         * This is a (possibly nested) lambda expression with one or more sets
+         * of parameters provided.
+         *
+         * If there are more nested expressions than sets of parameters this 
may
+         * return a LambdaExpression.
+         *
+         * If there are more sets of parameters than nested expressions an
+         * ELException will have been thrown by the check at the start of this
+         * method.
+         */
 
         // Always have to invoke the outer-most expression
         int methodParameterIndex = 2;
@@ -109,21 +98,6 @@ public class AstLambdaExpression extends
                 children[methodParameterIndex]).getParameters(ctx));
         methodParameterIndex++;
 
-        /*
-         * If there are multiple sets of method parameters there should be at
-         * least that many nested expressions.
-         *
-         * If there are more nested expressions than sets of method parameters
-         * this may return a LambdaExpression.
-         *
-         * If there are more sets of method parameters than nested expressions
-         * an ELException will have been thrown by the check at the start of
-         * this method.
-         *
-         * If the inner most expression(s) do not require parameters then a
-         * value will be returned once the outermost expression that does
-         * require a parameter has been evaluated.
-         */
         while (result instanceof LambdaExpression &&
                 methodParameterIndex < jjtGetNumChildren()) {
             result = ((LambdaExpression) result).invoke(((AstMethodParameters)
@@ -135,6 +109,42 @@ public class AstLambdaExpression extends
     }
 
 
+    private NestedState getNestedState() {
+        if (nestedState == null) {
+            setNestedState(new NestedState());
+        }
+        return nestedState;
+    }
+
+
+    private void setNestedState(NestedState nestedState) {
+        if (this.nestedState != null) {
+            // Should never happen
+            throw new IllegalStateException("nestedState may only be set 
once");
+        }
+        this.nestedState = nestedState;
+
+        // Increment the nesting count for the current expression
+        nestedState.incrementNestingCount();
+
+        if (jjtGetNumChildren() > 1) {
+            Node firstChild = jjtGetChild(0);
+            if (firstChild instanceof AstLambdaParameters) {
+                if (firstChild.jjtGetNumChildren() > 0) {
+                    nestedState.setHasFormalParameters();
+                }
+            } else {
+                // Can't be a lambda expression
+                return;
+            }
+            Node secondChild = jjtGetChild(1);
+            if (secondChild instanceof AstLambdaExpression) {
+                ((AstLambdaExpression) 
secondChild).setNestedState(nestedState);
+            }
+        }
+    }
+
+
     @Override
     public String toString() {
         // Purely for debug purposes. May not be complete or correct. Certainly
@@ -145,5 +155,28 @@ public class AstLambdaExpression extends
         }
         return result.toString();
     }
+
+
+    private static class NestedState {
+
+        private int nestingCount = 0;
+        private boolean hasFormalParameters = false;
+
+        private void incrementNestingCount() {
+            nestingCount++;
+        }
+
+        private int getNestingCount() {
+            return nestingCount;
+        }
+
+        private void setHasFormalParameters() {
+            hasFormalParameters = true;
+        }
+
+        private boolean getHasFormalParameters() {
+            return hasFormalParameters;
+        }
+    }
 }
 /* JavaCC - OriginalChecksum=071159eff10c8e15ec612c765ae4480a (do not edit 
this line) */



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to