Browse Source

Merge pull request #53 from aclement/SPR-9203

* SPR-9203:
  Eliminate trailing whitespace in SpEL classes
  Support [] array ref syntax in SpEL T() construct
pull/42/merge
Chris Beams 13 years ago
parent
commit
e68b563626
  1. 36
      spring-expression/src/main/java/org/springframework/expression/spel/ast/TypeReference.java
  2. 156
      spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java
  3. 31
      spring-expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java

36
spring-expression/src/main/java/org/springframework/expression/spel/ast/TypeReference.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,19 +16,28 @@ @@ -16,19 +16,28 @@
package org.springframework.expression.spel.ast;
import java.lang.reflect.Array;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.TypedValue;
import org.springframework.expression.spel.ExpressionState;
/**
* Represents a reference to a type, for example "T(String)" or "T(com.somewhere.Foo)"
*
*
* @author Andy Clement
*/
public class TypeReference extends SpelNodeImpl {
private int dimensions;
public TypeReference(int pos,SpelNodeImpl qualifiedId) {
this(pos,qualifiedId,0);
}
public TypeReference(int pos,SpelNodeImpl qualifiedId,int dims) {
super(pos,qualifiedId);
this.dimensions = dims;
}
@Override
@ -39,10 +48,24 @@ public class TypeReference extends SpelNodeImpl { @@ -39,10 +48,24 @@ public class TypeReference extends SpelNodeImpl {
TypeCode tc = TypeCode.valueOf(typename.toUpperCase());
if (tc != TypeCode.OBJECT) {
// it is a primitive type
return new TypedValue(tc.getType());
Class<?> clazz = tc.getType();
clazz = makeArrayIfNecessary(clazz);
return new TypedValue(clazz);
}
}
return new TypedValue(state.findType(typename));
Class<?> clazz = state.findType(typename);
clazz = makeArrayIfNecessary(clazz);
return new TypedValue(clazz);
}
private Class makeArrayIfNecessary(Class clazz) {
if (dimensions!=0) {
for (int i=0;i<dimensions;i++) {
Object o = Array.newInstance(clazz, 0);
clazz = o.getClass();
}
}
return clazz;
}
@Override
@ -50,8 +73,11 @@ public class TypeReference extends SpelNodeImpl { @@ -50,8 +73,11 @@ public class TypeReference extends SpelNodeImpl {
StringBuilder sb = new StringBuilder();
sb.append("T(");
sb.append(getChild(0).toStringAST());
for (int d=0;d<dimensions;d++) {
sb.append("[]");
}
sb.append(")");
return sb.toString();
}
}

156
spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -70,27 +70,27 @@ import org.springframework.util.Assert; @@ -70,27 +70,27 @@ import org.springframework.util.Assert;
/**
* Hand written SpEL parser. Instances are reusable but are not thread safe.
*
*
* @author Andy Clement
* @since 3.0
*/
class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
// The expression being parsed
private String expressionString;
private String expressionString;
// The token stream constructed from that expression string
private List<Token> tokenStream;
// length of a populated token stream
private int tokenStreamLength;
// Current location in the token stream when processing tokens
private int tokenStreamPointer;
// For rules that build nodes, they are stacked here for return
private Stack<SpelNodeImpl> constructedNodes = new Stack<SpelNodeImpl>();
private SpelParserConfiguration configuration;
@ -118,17 +118,17 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -118,17 +118,17 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
throw new SpelParseException(peekToken().startpos,SpelMessage.MORE_INPUT,toString(nextToken()));
}
Assert.isTrue(constructedNodes.isEmpty());
return new SpelExpression(expressionString, ast, configuration);
return new SpelExpression(expressionString, ast, configuration);
}
catch (InternalParseException ipe) {
throw ipe.getCause();
}
}
// expression
// : logicalOrExpression
// ( (ASSIGN^ logicalOrExpression)
// | (DEFAULT^ logicalOrExpression)
// ( (ASSIGN^ logicalOrExpression)
// | (DEFAULT^ logicalOrExpression)
// | (QMARK^ expression COLON! expression)
// | (ELVIS^ expression))?;
private SpelNodeImpl eatExpression() {
@ -157,15 +157,15 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -157,15 +157,15 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
expr = new NullLiteral(toPos(t.startpos-1,t.endpos-1));
}
nextToken();
SpelNodeImpl ifTrueExprValue = eatExpression();
SpelNodeImpl ifTrueExprValue = eatExpression();
eatToken(TokenKind.COLON);
SpelNodeImpl ifFalseExprValue = eatExpression();
SpelNodeImpl ifFalseExprValue = eatExpression();
return new Ternary(toPos(t),expr,ifTrueExprValue,ifFalseExprValue);
}
}
return expr;
}
//logicalOrExpression : logicalAndExpression (OR^ logicalAndExpression)*;
private SpelNodeImpl eatLogicalOrExpression() {
SpelNodeImpl expr = eatLogicalAndExpression();
@ -189,7 +189,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -189,7 +189,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
}
return expr;
}
// relationalExpression : sumExpression (relationalOperator^ sumExpression)?;
private SpelNodeImpl eatRelationalExpression() {
SpelNodeImpl expr = eatSumExpression();
@ -227,10 +227,10 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -227,10 +227,10 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
}
return expr;
}
//sumExpression: productExpression ( (PLUS^ | MINUS^) productExpression)*;
private SpelNodeImpl eatSumExpression() {
SpelNodeImpl expr = eatProductExpression();
SpelNodeImpl expr = eatProductExpression();
while (peekToken(TokenKind.PLUS,TokenKind.MINUS)) {
Token t = nextToken();//consume PLUS or MINUS
SpelNodeImpl rhExpr = eatProductExpression();
@ -244,7 +244,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -244,7 +244,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
}
return expr;
}
// productExpression: powerExpr ((STAR^ | DIV^| MOD^) powerExpr)* ;
private SpelNodeImpl eatProductExpression() {
SpelNodeImpl expr = eatPowerExpression();
@ -263,7 +263,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -263,7 +263,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
}
return expr;
}
// powerExpr : unaryExpression (POWER^ unaryExpression)? ;
private SpelNodeImpl eatPowerExpression() {
SpelNodeImpl expr = eatUnaryExpression();
@ -293,7 +293,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -293,7 +293,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
return eatPrimaryExpression();
}
}
// primaryExpression : startNode (node)? -> ^(EXPRESSION startNode (node)?);
private SpelNodeImpl eatPrimaryExpression() {
List<SpelNodeImpl> nodes = new ArrayList<SpelNodeImpl>();
@ -308,7 +308,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -308,7 +308,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
return new CompoundExpression(toPos(start.getStartPosition(),nodes.get(nodes.size()-1).getEndPosition()),nodes.toArray(new SpelNodeImpl[nodes.size()]));
}
}
// node : ((DOT dottedNode) | (SAFE_NAVI dottedNode) | nonDottedNode)+;
private boolean maybeEatNode() {
SpelNodeImpl expr = null;
@ -324,7 +324,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -324,7 +324,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
return true;
}
}
// nonDottedNode: indexer;
private SpelNodeImpl maybeEatNonDottedNode() {
if (peekToken(TokenKind.LSQUARE)) {
@ -334,14 +334,14 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -334,14 +334,14 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
}
return null;
}
//dottedNode
// : ((methodOrProperty
// | functionOrVar
// | projection
// | selection
// | firstSelection
// | lastSelection
// | projection
// | selection
// | firstSelection
// | lastSelection
// ))
// ;
private SpelNodeImpl eatDottedNode() {
@ -351,20 +351,20 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -351,20 +351,20 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
return pop();
}
if (peekToken()==null) {
// unexpectedly ran out of data
// unexpectedly ran out of data
raiseInternalException(t.startpos,SpelMessage.OOD);
} else {
raiseInternalException(t.startpos,SpelMessage.UNEXPECTED_DATA_AFTER_DOT,toString(peekToken()));
}
return null;
}
// functionOrVar
// functionOrVar
// : (POUND ID LPAREN) => function
// | var
//
// function : POUND id=ID methodArgs -> ^(FUNCTIONREF[$id] methodArgs);
// var : POUND id=ID -> ^(VARIABLEREF[$id]);
//
// function : POUND id=ID methodArgs -> ^(FUNCTIONREF[$id] methodArgs);
// var : POUND id=ID -> ^(VARIABLEREF[$id]);
private boolean maybeEatFunctionOrVar() {
if (!peekToken(TokenKind.HASH)) {
return false;
@ -380,7 +380,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -380,7 +380,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
return true;
}
}
// methodArgs : LPAREN! (argument (COMMA! argument)* (COMMA!)?)? RPAREN!;
private SpelNodeImpl[] maybeEatMethodArgs() {
if (!peekToken(TokenKind.LPAREN)) {
@ -391,7 +391,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -391,7 +391,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
eatToken(TokenKind.RPAREN);
return args.toArray(new SpelNodeImpl[args.size()]);
}
private void eatConstructorArgs(List<SpelNodeImpl> accumulatedArguments) {
if (!peekToken(TokenKind.LPAREN)) {
throw new InternalParseException(new SpelParseException(expressionString,positionOf(peekToken()),SpelMessage.MISSING_CONSTRUCTOR_ARGS));
@ -399,7 +399,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -399,7 +399,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
consumeArguments(accumulatedArguments);
eatToken(TokenKind.RPAREN);
}
/**
* Used for consuming arguments for either a method or a constructor call
*/
@ -421,25 +421,25 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -421,25 +421,25 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
raiseInternalException(pos,SpelMessage.RUN_OUT_OF_ARGUMENTS);
}
}
private int positionOf(Token t) {
if (t==null) {
// if null assume the problem is because the right token was
// if null assume the problem is because the right token was
// not found at the end of the expression
return expressionString.length();
} else {
return t.startpos;
}
}
//startNode
//startNode
// : parenExpr | literal
// | type
// | methodOrProperty
// | methodOrProperty
// | functionOrVar
// | projection
// | selection
// | projection
// | selection
// | firstSelection
// | lastSelection
// | indexer
@ -461,7 +461,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -461,7 +461,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
return null;
}
}
// parse: @beanname @'bean.name'
// quoted if dotted
private boolean maybeEatBeanReference() {
@ -479,7 +479,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -479,7 +479,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
} else {
raiseInternalException(beanRefToken.startpos,SpelMessage.INVALID_BEAN_REFERENCE);
}
BeanReference beanReference = new BeanReference(toPos(beanNameToken),beanname);
constructedNodes.push(beanReference);
return true;
@ -497,8 +497,14 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -497,8 +497,14 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
eatToken(TokenKind.LPAREN);
SpelNodeImpl node = eatPossiblyQualifiedId();
// dotted qualified id
// Are there array dimensions?
int dims = 0;
while (peekToken(TokenKind.LSQUARE,true)) {
eatToken(TokenKind.RSQUARE);
dims++;
}
eatToken(TokenKind.RPAREN);
constructedNodes.push(new TypeReference(toPos(typeName),node));
constructedNodes.push(new TypeReference(toPos(typeName),node,dims));
return true;
}
return false;
@ -528,7 +534,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -528,7 +534,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
constructedNodes.push(new Projection(nullSafeNavigation, toPos(t), expr));
return true;
}
// list = LCURLY (element (COMMA element)*) RCURLY
private boolean maybeEatInlineList() {
Token t = peekToken();
@ -544,14 +550,14 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -544,14 +550,14 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
List<SpelNodeImpl> listElements = new ArrayList<SpelNodeImpl>();
do {
listElements.add(eatExpression());
} while (peekToken(TokenKind.COMMA,true));
} while (peekToken(TokenKind.COMMA,true));
closingCurly = eatToken(TokenKind.RCURLY);
expr = new InlineList(toPos(t.startpos,closingCurly.endpos),listElements.toArray(new SpelNodeImpl[listElements.size()]));
}
constructedNodes.push(expr);
return true;
}
private boolean maybeEatIndexer() {
Token t = peekToken();
if (!peekToken(TokenKind.LSQUARE,true)) {
@ -562,7 +568,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -562,7 +568,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
constructedNodes.push(new Indexer(toPos(t),expr));
return true;
}
private boolean maybeEatSelection(boolean nullSafeNavigation) {
Token t = peekToken();
if (!peekSelectToken()) {
@ -571,7 +577,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -571,7 +577,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
nextToken();
SpelNodeImpl expr = eatExpression();
eatToken(TokenKind.RSQUARE);
if (t.kind==TokenKind.SELECT_FIRST) {
if (t.kind==TokenKind.SELECT_FIRST) {
constructedNodes.push(new Selection(nullSafeNavigation,Selection.FIRST,toPos(t),expr));
} else if (t.kind==TokenKind.SELECT_LAST) {
constructedNodes.push(new Selection(nullSafeNavigation,Selection.LAST,toPos(t),expr));
@ -591,11 +597,11 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -591,11 +597,11 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
qualifiedIdPieces.add(new Identifier(startnode.stringValue(),toPos(startnode)));
while (peekToken(TokenKind.DOT,true)) {
Token node = eatToken(TokenKind.IDENTIFIER);
qualifiedIdPieces.add(new Identifier(node.stringValue(),toPos(node)));
qualifiedIdPieces.add(new Identifier(node.stringValue(),toPos(node)));
}
return new QualifiedIdentifier(toPos(startnode.startpos,qualifiedIdPieces.get(qualifiedIdPieces.size()-1).getEndPosition()),qualifiedIdPieces.toArray(new SpelNodeImpl[qualifiedIdPieces.size()]));
}
// 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) {
@ -616,8 +622,8 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -616,8 +622,8 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
return false;
}
//constructor
//constructor
//: ('new' qualifiedId LPAREN) => 'new' qualifiedId ctorArgs -> ^(CONSTRUCTOR qualifiedId ctorArgs)
private boolean maybeEatConstructorReference() {
if (peekIdentifierToken("new")) {
@ -659,12 +665,12 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -659,12 +665,12 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
private SpelNodeImpl pop() {
return constructedNodes.pop();
}
// literal
// : INTEGER_LITERAL
// literal
// : INTEGER_LITERAL
// | boolLiteral
// | STRING_LITERAL
// | HEXADECIMAL_INTEGER_LITERAL
// | STRING_LITERAL
// | HEXADECIMAL_INTEGER_LITERAL
// | REAL_LITERAL
// | DQ_STRING_LITERAL
// | NULL_LITERAL
@ -685,14 +691,14 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -685,14 +691,14 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
push(Literal.getRealLiteral(t.data, toPos(t),false));
} else if (t.kind==TokenKind.LITERAL_REAL_FLOAT) {
push(Literal.getRealLiteral(t.data, toPos(t), true));
} else if (peekIdentifierToken("true")) {
} else if (peekIdentifierToken("true")) {
push(new BooleanLiteral(t.data,toPos(t),true));
} else if (peekIdentifierToken("false")) {
push(new BooleanLiteral(t.data,toPos(t),false));
} else if (t.kind==TokenKind.LITERAL_STRING) {
push(new StringLiteral(t.data,toPos(t),t.data));
} else {
return false;
return false;
}
nextToken();
return true;
@ -713,11 +719,11 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -713,11 +719,11 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
// relationalOperator
// : EQUAL | NOT_EQUAL | LESS_THAN | LESS_THAN_OR_EQUAL | GREATER_THAN
// | GREATER_THAN_OR_EQUAL | INSTANCEOF | BETWEEN | MATCHES
// | GREATER_THAN_OR_EQUAL | INSTANCEOF | BETWEEN | MATCHES
private Token maybeEatRelationalOperator() {
Token t = peekToken();
if (t==null) {
return null;
return null;
}
if (t.isNumericRelationalOperator()) {
return t;
@ -730,7 +736,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -730,7 +736,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
return t.asMatchesToken();
} else if (idString.equalsIgnoreCase("between")) {
return t.asBetweenToken();
}
}
}
return null;
}
@ -740,7 +746,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -740,7 +746,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
if (t==null) {
raiseInternalException( expressionString.length(), SpelMessage.OOD);
}
if (t.kind!=expectedKind) {
if (t.kind!=expectedKind) {
raiseInternalException(t.startpos,SpelMessage.NOT_EXPECTED_TOKEN, expectedKind.toString().toLowerCase(),t.getKind().toString().toLowerCase());
}
return t;
@ -792,18 +798,18 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -792,18 +798,18 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
Token t = peekToken();
return t.kind==TokenKind.IDENTIFIER && t.stringValue().equalsIgnoreCase(identifierString);
}
private boolean peekSelectToken() {
if (!moreTokens()) return false;
Token t = peekToken();
return t.kind==TokenKind.SELECT || t.kind==TokenKind.SELECT_FIRST || t.kind==TokenKind.SELECT_LAST;
}
private boolean moreTokens() {
return tokenStreamPointer<tokenStream.size();
}
private Token nextToken() {
if (tokenStreamPointer>=tokenStreamLength) {
return null;
@ -819,9 +825,9 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -819,9 +825,9 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
}
private void raiseInternalException(int pos, SpelMessage message,Object... inserts) {
throw new InternalParseException(new SpelParseException(expressionString,pos,message,inserts));
throw new InternalParseException(new SpelParseException(expressionString,pos,message,inserts));
}
public String toString(Token t) {
if (t.getKind().hasPayload()) {
return t.stringValue();
@ -829,7 +835,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -829,7 +835,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
return t.kind.toString().toLowerCase();
}
}
private void checkRightOperand(Token token, SpelNodeImpl operandExpression) {
if (operandExpression==null) {
raiseInternalException(token.startpos,SpelMessage.RIGHT_OPERAND_PROBLEM);
@ -846,5 +852,5 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -846,5 +852,5 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
private int toPos(int start,int end) {
return (start<<16)+end;
}
}

31
spring-expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -1175,6 +1175,35 @@ public class SpringEL300Tests extends ExpressionTestCase { @@ -1175,6 +1175,35 @@ public class SpringEL300Tests extends ExpressionTestCase {
}
}
@Test
public void testArray() {
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
Expression expression = null;
Object result = null;
expression = parser.parseExpression("new java.lang.Long[0].class");
result = expression.getValue(context, "");
assertEquals("Equal assertion failed: ", "class [Ljava.lang.Long;", result.toString());
expression = parser.parseExpression("T(java.lang.Long[])");
result = expression.getValue(context, "");
assertEquals("Equal assertion failed: ", "class [Ljava.lang.Long;", result.toString());
expression = parser.parseExpression("T(java.lang.String[][][])");
result = expression.getValue(context, "");
assertEquals("Equal assertion failed: ", "class [[[Ljava.lang.String;", result.toString());
assertEquals("T(java.lang.String[][][])",((SpelExpression)expression).toStringAST());
expression = parser.parseExpression("new int[0].class");
result = expression.getValue(context, "");
assertEquals("Equal assertion failed: ", "class [I", result.toString());
expression = parser.parseExpression("T(int[][])");
result = expression.getValue(context, "");
assertEquals("Equal assertion failed: ", "class [[I", result.toString());
}
}

Loading…
Cancel
Save