Search in sources :

Example 1 with SpelNodeImpl

use of org.springframework.expression.spel.ast.SpelNodeImpl in project spring-framework by spring-projects.

the class SpelCompilationCoverageTests method compiledExpressionShouldWorkWhenUsingCustomFunctionWithVarargs.

@Test
public void compiledExpressionShouldWorkWhenUsingCustomFunctionWithVarargs() throws Exception {
    StandardEvaluationContext context = null;
    // Here the target method takes Object... and we are passing a string
    expression = parser.parseExpression("#doFormat('hey %s', 'there')");
    context = new StandardEvaluationContext();
    context.registerFunction("doFormat", DelegatingStringFormat.class.getDeclaredMethod("format", String.class, Object[].class));
    ((SpelExpression) expression).setEvaluationContext(context);
    assertThat(expression.getValue(String.class)).isEqualTo("hey there");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(String.class)).isEqualTo("hey there");
    expression = parser.parseExpression("#doFormat([0], 'there')");
    context = new StandardEvaluationContext(new Object[] { "hey %s" });
    context.registerFunction("doFormat", DelegatingStringFormat.class.getDeclaredMethod("format", String.class, Object[].class));
    ((SpelExpression) expression).setEvaluationContext(context);
    assertThat(expression.getValue(String.class)).isEqualTo("hey there");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(String.class)).isEqualTo("hey there");
    expression = parser.parseExpression("#doFormat([0], #arg)");
    context = new StandardEvaluationContext(new Object[] { "hey %s" });
    context.registerFunction("doFormat", DelegatingStringFormat.class.getDeclaredMethod("format", String.class, Object[].class));
    context.setVariable("arg", "there");
    ((SpelExpression) expression).setEvaluationContext(context);
    assertThat(expression.getValue(String.class)).isEqualTo("hey there");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(String.class)).isEqualTo("hey there");
}
Also used : StandardEvaluationContext(org.springframework.expression.spel.support.StandardEvaluationContext) SpelNodeImpl(org.springframework.expression.spel.ast.SpelNodeImpl) SpelExpression(org.springframework.expression.spel.standard.SpelExpression) Test(org.junit.jupiter.api.Test)

Example 2 with SpelNodeImpl

use of org.springframework.expression.spel.ast.SpelNodeImpl in project spring-framework by spring-projects.

the class SpelCompilationCoverageTests method functionReferenceVarargs_SPR12359.

@Test
public void functionReferenceVarargs_SPR12359() throws Exception {
    StandardEvaluationContext context = new StandardEvaluationContext();
    context.registerFunction("append", SomeCompareMethod2.class.getDeclaredMethod("append", String[].class));
    context.registerFunction("append2", SomeCompareMethod2.class.getDeclaredMethod("append2", Object[].class));
    context.registerFunction("append3", SomeCompareMethod2.class.getDeclaredMethod("append3", String[].class));
    context.registerFunction("append4", SomeCompareMethod2.class.getDeclaredMethod("append4", String.class, String[].class));
    context.registerFunction("appendChar", SomeCompareMethod2.class.getDeclaredMethod("appendChar", char[].class));
    context.registerFunction("sum", SomeCompareMethod2.class.getDeclaredMethod("sum", int[].class));
    context.registerFunction("sumDouble", SomeCompareMethod2.class.getDeclaredMethod("sumDouble", double[].class));
    context.registerFunction("sumFloat", SomeCompareMethod2.class.getDeclaredMethod("sumFloat", float[].class));
    context.setVariable("stringArray", new String[] { "x", "y", "z" });
    context.setVariable("intArray", new int[] { 5, 6, 9 });
    context.setVariable("doubleArray", new double[] { 5.0d, 6.0d, 9.0d });
    context.setVariable("floatArray", new float[] { 5.0f, 6.0f, 9.0f });
    expression = parser.parseExpression("#append('a','b','c')");
    assertThat(expression.getValue(context).toString()).isEqualTo("abc");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context).toString()).isEqualTo("abc");
    expression = parser.parseExpression("#append('a')");
    assertThat(expression.getValue(context).toString()).isEqualTo("a");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context).toString()).isEqualTo("a");
    expression = parser.parseExpression("#append()");
    assertThat(expression.getValue(context).toString()).isEqualTo("");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context).toString()).isEqualTo("");
    expression = parser.parseExpression("#append(#stringArray)");
    assertThat(expression.getValue(context).toString()).isEqualTo("xyz");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context).toString()).isEqualTo("xyz");
    // This is a methodreference invocation, to compare with functionreference
    expression = parser.parseExpression("append(#stringArray)");
    assertThat(expression.getValue(context, new SomeCompareMethod2()).toString()).isEqualTo("xyz");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context, new SomeCompareMethod2()).toString()).isEqualTo("xyz");
    expression = parser.parseExpression("#append2('a','b','c')");
    assertThat(expression.getValue(context).toString()).isEqualTo("abc");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context).toString()).isEqualTo("abc");
    expression = parser.parseExpression("append2('a','b')");
    assertThat(expression.getValue(context, new SomeCompareMethod2()).toString()).isEqualTo("ab");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context, new SomeCompareMethod2()).toString()).isEqualTo("ab");
    expression = parser.parseExpression("#append2('a','b')");
    assertThat(expression.getValue(context).toString()).isEqualTo("ab");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context).toString()).isEqualTo("ab");
    expression = parser.parseExpression("#append2()");
    assertThat(expression.getValue(context).toString()).isEqualTo("");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context).toString()).isEqualTo("");
    expression = parser.parseExpression("#append3(#stringArray)");
    assertThat(expression.getValue(context, new SomeCompareMethod2()).toString()).isEqualTo("xyz");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context, new SomeCompareMethod2()).toString()).isEqualTo("xyz");
    // TODO fails due to conversionservice handling of String[] to Object...
    // expression = parser.parseExpression("#append2(#stringArray)");
    // assertEquals("xyz", expression.getValue(context).toString());
    // assertTrue(((SpelNodeImpl)((SpelExpression) expression).getAST()).isCompilable());
    // assertCanCompile(expression);
    // assertEquals("xyz", expression.getValue(context).toString());
    expression = parser.parseExpression("#sum(1,2,3)");
    assertThat(expression.getValue(context)).isEqualTo(6);
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo(6);
    expression = parser.parseExpression("#sum(2)");
    assertThat(expression.getValue(context)).isEqualTo(2);
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo(2);
    expression = parser.parseExpression("#sum()");
    assertThat(expression.getValue(context)).isEqualTo(0);
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo(0);
    expression = parser.parseExpression("#sum(#intArray)");
    assertThat(expression.getValue(context)).isEqualTo(20);
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo(20);
    expression = parser.parseExpression("#sumDouble(1.0d,2.0d,3.0d)");
    assertThat(expression.getValue(context)).isEqualTo(6);
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo(6);
    expression = parser.parseExpression("#sumDouble(2.0d)");
    assertThat(expression.getValue(context)).isEqualTo(2);
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo(2);
    expression = parser.parseExpression("#sumDouble()");
    assertThat(expression.getValue(context)).isEqualTo(0);
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo(0);
    expression = parser.parseExpression("#sumDouble(#doubleArray)");
    assertThat(expression.getValue(context)).isEqualTo(20);
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo(20);
    expression = parser.parseExpression("#sumFloat(1.0f,2.0f,3.0f)");
    assertThat(expression.getValue(context)).isEqualTo(6);
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo(6);
    expression = parser.parseExpression("#sumFloat(2.0f)");
    assertThat(expression.getValue(context)).isEqualTo(2);
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo(2);
    expression = parser.parseExpression("#sumFloat()");
    assertThat(expression.getValue(context)).isEqualTo(0);
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo(0);
    expression = parser.parseExpression("#sumFloat(#floatArray)");
    assertThat(expression.getValue(context)).isEqualTo(20);
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo(20);
    expression = parser.parseExpression("#appendChar('abc'.charAt(0),'abc'.charAt(1))");
    assertThat(expression.getValue(context)).isEqualTo("ab");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context)).isEqualTo("ab");
    expression = parser.parseExpression("#append4('a','b','c')");
    assertThat(expression.getValue(context).toString()).isEqualTo("a::bc");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context).toString()).isEqualTo("a::bc");
    expression = parser.parseExpression("#append4('a','b')");
    assertThat(expression.getValue(context).toString()).isEqualTo("a::b");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context).toString()).isEqualTo("a::b");
    expression = parser.parseExpression("#append4('a')");
    assertThat(expression.getValue(context).toString()).isEqualTo("a::");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context).toString()).isEqualTo("a::");
    expression = parser.parseExpression("#append4('a',#stringArray)");
    assertThat(expression.getValue(context).toString()).isEqualTo("a::xyz");
    assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
    assertCanCompile(expression);
    assertThat(expression.getValue(context).toString()).isEqualTo("a::xyz");
}
Also used : StandardEvaluationContext(org.springframework.expression.spel.support.StandardEvaluationContext) SpelNodeImpl(org.springframework.expression.spel.ast.SpelNodeImpl) Test(org.junit.jupiter.api.Test)

Example 3 with SpelNodeImpl

use of org.springframework.expression.spel.ast.SpelNodeImpl in project spring-framework by spring-projects.

the class InternalSpelExpressionParser method maybeEatInlineListOrMap.

// list = LCURLY (element (COMMA element)*) RCURLY
// map  = LCURLY (key ':' value (COMMA key ':' value)*) RCURLY
private boolean maybeEatInlineListOrMap() {
    Token t = peekToken();
    if (!peekToken(TokenKind.LCURLY, true)) {
        return false;
    }
    Assert.state(t != null, "No token");
    SpelNodeImpl expr = null;
    Token closingCurly = peekToken();
    if (peekToken(TokenKind.RCURLY, true)) {
        // empty list '{}'
        Assert.state(closingCurly != null, "No token");
        expr = new InlineList(t.startPos, closingCurly.endPos);
    } else if (peekToken(TokenKind.COLON, true)) {
        closingCurly = eatToken(TokenKind.RCURLY);
        // empty map '{:}'
        expr = new InlineMap(t.startPos, closingCurly.endPos);
    } else {
        SpelNodeImpl firstExpression = eatExpression();
        // ':' - this is a map!
        if (peekToken(TokenKind.RCURLY)) {
            // list with one item in it
            List<SpelNodeImpl> elements = new ArrayList<>();
            elements.add(firstExpression);
            closingCurly = eatToken(TokenKind.RCURLY);
            expr = new InlineList(t.startPos, closingCurly.endPos, elements.toArray(new SpelNodeImpl[0]));
        } else if (peekToken(TokenKind.COMMA, true)) {
            // multi-item list
            List<SpelNodeImpl> elements = new ArrayList<>();
            elements.add(firstExpression);
            do {
                elements.add(eatExpression());
            } while (peekToken(TokenKind.COMMA, true));
            closingCurly = eatToken(TokenKind.RCURLY);
            expr = new InlineList(t.startPos, closingCurly.endPos, elements.toArray(new SpelNodeImpl[0]));
        } else if (peekToken(TokenKind.COLON, true)) {
            // map!
            List<SpelNodeImpl> elements = new ArrayList<>();
            elements.add(firstExpression);
            elements.add(eatExpression());
            while (peekToken(TokenKind.COMMA, true)) {
                elements.add(eatExpression());
                eatToken(TokenKind.COLON);
                elements.add(eatExpression());
            }
            closingCurly = eatToken(TokenKind.RCURLY);
            expr = new InlineMap(t.startPos, closingCurly.endPos, elements.toArray(new SpelNodeImpl[0]));
        } else {
            throw internalException(t.startPos, SpelMessage.OOD);
        }
    }
    this.constructedNodes.push(expr);
    return true;
}
Also used : SpelNodeImpl(org.springframework.expression.spel.ast.SpelNodeImpl) ArrayList(java.util.ArrayList) InlineList(org.springframework.expression.spel.ast.InlineList) List(java.util.List) InlineList(org.springframework.expression.spel.ast.InlineList) ArrayList(java.util.ArrayList) InlineMap(org.springframework.expression.spel.ast.InlineMap)

Example 4 with SpelNodeImpl

use of org.springframework.expression.spel.ast.SpelNodeImpl in project spring-framework by spring-projects.

the class InternalSpelExpressionParser method maybeEatMethodOrProperty.

// This is complicated due to the support for dollars in identifiers.
// Dollars are normally separate tokens but there we want to combine
// a series of identifiers and dollars into a single identifier.
private boolean maybeEatMethodOrProperty(boolean nullSafeNavigation) {
    if (peekToken(TokenKind.IDENTIFIER)) {
        Token methodOrPropertyName = takeToken();
        SpelNodeImpl[] args = maybeEatMethodArgs();
        if (args == null) {
            // property
            push(new PropertyOrFieldReference(nullSafeNavigation, methodOrPropertyName.stringValue(), methodOrPropertyName.startPos, methodOrPropertyName.endPos));
            return true;
        }
        // method reference
        push(new MethodReference(nullSafeNavigation, methodOrPropertyName.stringValue(), methodOrPropertyName.startPos, methodOrPropertyName.endPos, args));
        // TODO what is the end position for a method reference? the name or the last arg?
        return true;
    }
    return false;
}
Also used : SpelNodeImpl(org.springframework.expression.spel.ast.SpelNodeImpl) MethodReference(org.springframework.expression.spel.ast.MethodReference) PropertyOrFieldReference(org.springframework.expression.spel.ast.PropertyOrFieldReference)

Example 5 with SpelNodeImpl

use of org.springframework.expression.spel.ast.SpelNodeImpl in project spring-framework by spring-projects.

the class InternalSpelExpressionParser method maybeEatConstructorReference.

// constructor
// :	('new' qualifiedId LPAREN) => 'new' qualifiedId ctorArgs -> ^(CONSTRUCTOR qualifiedId ctorArgs)
private boolean maybeEatConstructorReference() {
    if (peekIdentifierToken("new")) {
        Token newToken = takeToken();
        // It looks like a constructor reference but is NEW being used as a map key?
        if (peekToken(TokenKind.RSQUARE)) {
            // looks like 'NEW]' (so NEW used as map key)
            push(new PropertyOrFieldReference(false, newToken.stringValue(), newToken.startPos, newToken.endPos));
            return true;
        }
        SpelNodeImpl possiblyQualifiedConstructorName = eatPossiblyQualifiedId();
        List<SpelNodeImpl> nodes = new ArrayList<>();
        nodes.add(possiblyQualifiedConstructorName);
        if (peekToken(TokenKind.LSQUARE)) {
            // array initializer
            List<SpelNodeImpl> dimensions = new ArrayList<>();
            while (peekToken(TokenKind.LSQUARE, true)) {
                if (!peekToken(TokenKind.RSQUARE)) {
                    dimensions.add(eatExpression());
                } else {
                    dimensions.add(null);
                }
                eatToken(TokenKind.RSQUARE);
            }
            if (maybeEatInlineListOrMap()) {
                nodes.add(pop());
            }
            push(new ConstructorReference(newToken.startPos, newToken.endPos, dimensions.toArray(new SpelNodeImpl[0]), nodes.toArray(new SpelNodeImpl[0])));
        } else {
            // regular constructor invocation
            eatConstructorArgs(nodes);
            // TODO correct end position?
            push(new ConstructorReference(newToken.startPos, newToken.endPos, nodes.toArray(new SpelNodeImpl[0])));
        }
        return true;
    }
    return false;
}
Also used : SpelNodeImpl(org.springframework.expression.spel.ast.SpelNodeImpl) ArrayList(java.util.ArrayList) PropertyOrFieldReference(org.springframework.expression.spel.ast.PropertyOrFieldReference) ConstructorReference(org.springframework.expression.spel.ast.ConstructorReference)

Aggregations

SpelNodeImpl (org.springframework.expression.spel.ast.SpelNodeImpl)24 Nullable (org.springframework.lang.Nullable)9 Test (org.junit.jupiter.api.Test)3 PropertyOrFieldReference (org.springframework.expression.spel.ast.PropertyOrFieldReference)3 StandardEvaluationContext (org.springframework.expression.spel.support.StandardEvaluationContext)3 ArrayList (java.util.ArrayList)2 OpDec (org.springframework.expression.spel.ast.OpDec)2 OpInc (org.springframework.expression.spel.ast.OpInc)2 OpMinus (org.springframework.expression.spel.ast.OpMinus)2 OpPlus (org.springframework.expression.spel.ast.OpPlus)2 SpelExpression (org.springframework.expression.spel.standard.SpelExpression)2 ArrayDeque (java.util.ArrayDeque)1 List (java.util.List)1 InternalParseException (org.springframework.expression.spel.InternalParseException)1 SpelParseException (org.springframework.expression.spel.SpelParseException)1 Assign (org.springframework.expression.spel.ast.Assign)1 CompoundExpression (org.springframework.expression.spel.ast.CompoundExpression)1 ConstructorReference (org.springframework.expression.spel.ast.ConstructorReference)1 Elvis (org.springframework.expression.spel.ast.Elvis)1 FunctionReference (org.springframework.expression.spel.ast.FunctionReference)1