Author: markt Date: Wed Jul 17 21:12:22 2013 New Revision: 1504281 URL: http://svn.apache.org/r1504281 Log: More fun and games with nested lambda expressions. Each invocation of a nested expression consumes a set of method parameters. Therefore nested lambda expressions that are invoked immediately (because they have no formal parameetrs) need to inform the outer expression of the invocation so the next invocation uses the correct method parameters.
Modified: tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.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=1504281&r1=1504280&r2=1504281&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java (original) +++ tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java Wed Jul 17 21:12:22 2013 @@ -29,6 +29,8 @@ import org.apache.el.util.MessageFactory public class AstLambdaExpression extends SimpleNode { + private int methodParameterIndex = 0; + public AstLambdaExpression(int id) { super(id); } @@ -73,37 +75,70 @@ public class AstLambdaExpression extends LambdaExpression le = new LambdaExpression(formalParameters, ve); le.setELContext(ctx); - if (formalParameters.isEmpty() && jjtGetNumChildren() == 2) { - // No formal parameters - invoke the expression - return le.invoke(ctx, (Object[]) null); - } - - // If there are method parameters, need to invoke the expression with - // those parameters. 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. - Object result = le; - int i = 2; - while (result instanceof LambdaExpression && i < jjtGetNumChildren()) { - result = ((LambdaExpression) result).invoke( - ((AstMethodParameters) children[i]).getParameters(ctx)); - i++; - while (i < jjtGetNumChildren() && children[i].jjtGetNumChildren() == 0) { - i++; + if (jjtGetNumChildren() == 2) { + if (formalParameters.isEmpty()) { + // No formal parameters or method parameters so invoke the + // expression. If this is a nested expression inform the outer + // expression that an invocation has occurred so the correct set + // of method parameters are used for the next invocation. + incMethodParameterIndex(); + return le.invoke(ctx, (Object[]) null); + } else { + // Has formal parameters but no method parameters so return the + // expression for later evaluation + return le; } } + + // Always have to invoke the outer-most expression + methodParameterIndex = 2; + Object result = le.invoke(((AstMethodParameters) + 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. + * + * When invoking an expression if it has nested expressions that do not + * have formal parameters then they will be evaluated as as part of that + * invocation. In this case the method parameters associated with those + * nested expressions need to be skipped. + */ + while (result instanceof LambdaExpression && + methodParameterIndex < jjtGetNumChildren()) { + result = ((LambdaExpression) result).invoke(((AstMethodParameters) + children[methodParameterIndex]).getParameters(ctx)); + methodParameterIndex++; + } + return result; } + public void incMethodParameterIndex() { + Node parent = jjtGetParent(); + if (parent instanceof AstLambdaExpression) { + // Method parameter index is maintained by outermost lambda + // expressions as that is where the parameters are + ((AstLambdaExpression) parent).incMethodParameterIndex(); + } else { + methodParameterIndex++; + } + } + @Override public String toString() { // Purely for debug purposes. May not be complete or correct. Certainly Modified: tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java?rev=1504281&r1=1504280&r2=1504281&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java (original) +++ tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java Wed Jul 17 21:12:22 2013 @@ -134,4 +134,14 @@ public class TestAstLambdaExpression { Integer.class); Assert.assertEquals(Integer.valueOf(1), result); } + + + @Test + public void testNested06() { + ELProcessor processor = new ELProcessor(); + Object result = + processor.getValue("(()->y->()->()->x->x-y)()(1)()(3)(2)", + Integer.class); + Assert.assertEquals(Integer.valueOf(1), result); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org