Browse Source

Allow NEW and T to be used as unquoted map keys in SpEL

This change provides support for map[NEW], map[new], map[T]
and map[t]. Prior to this change the 'new' and 't' had to
be quoted because they were keywords in SpEL for a constructor
reference and type reference respectively.

Issue: SPR-11783
pull/566/merge
Andy Clement 10 years ago
parent
commit
c382b6f059
  1. 16
      spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java
  2. 66
      spring-expression/src/test/java/org/springframework/expression/spel/MapTests.java

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -556,7 +556,13 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -556,7 +556,13 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
if (!typeName.stringValue().equals("T")) {
return false;
}
nextToken();
// It looks like a type reference but is T being used as a map key?
Token t = nextToken();
if (peekToken(TokenKind.RSQUARE)) {
// looks like 'T]' (T is map key)
push(new PropertyOrFieldReference(false,t.data,toPos(t)));
return true;
}
eatToken(TokenKind.LPAREN);
SpelNodeImpl node = eatPossiblyQualifiedId();
// dotted qualified id
@ -754,6 +760,12 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -754,6 +760,12 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
private boolean maybeEatConstructorReference() {
if (peekIdentifierToken("new")) {
Token newToken = nextToken();
// 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.data,toPos(newToken)));
return true;
}
SpelNodeImpl possiblyQualifiedConstructorName = eatPossiblyQualifiedId();
List<SpelNodeImpl> nodes = new ArrayList<SpelNodeImpl>();
nodes.add(possiblyQualifiedConstructorName);

66
spring-expression/src/test/java/org/springframework/expression/spel/MapTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2015 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.
@ -20,9 +20,9 @@ import java.util.ArrayList; @@ -20,9 +20,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.junit.Test;
import org.springframework.expression.spel.ast.InlineMap;
import org.springframework.expression.spel.standard.SpelExpression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
@ -136,4 +136,66 @@ public class MapTests extends AbstractExpressionTests { @@ -136,4 +136,66 @@ public class MapTests extends AbstractExpressionTests {
// list should be unmodifiable
evaluate("{a:1, b:2, c:3, d:4, e:5}[a]=6", "[a:1,b: 2,c: 3,d: 4,e: 5]", unmodifiableClass);
}
@Test
public void testMapKeysThatAreAlsoSpELKeywords() {
SpelExpressionParser parser = new SpelExpressionParser();
SpelExpression expression = null;
Object o = null;
// expression = (SpelExpression) parser.parseExpression("foo['NEW']");
// o = expression.getValue(new MapHolder());
// assertEquals("VALUE",o);
expression = (SpelExpression) parser.parseExpression("foo[T]");
o = expression.getValue(new MapHolder());
assertEquals("TV", o);
expression = (SpelExpression) parser.parseExpression("foo[t]");
o = expression.getValue(new MapHolder());
assertEquals("tv", o);
expression = (SpelExpression) parser.parseExpression("foo[NEW]");
o = expression.getValue(new MapHolder());
assertEquals("VALUE", o);
expression = (SpelExpression) parser.parseExpression("foo[new]");
o = expression.getValue(new MapHolder());
assertEquals("value", o);
expression = (SpelExpression) parser.parseExpression("foo['abc.def']");
o = expression.getValue(new MapHolder());
assertEquals("value", o);
expression = (SpelExpression)parser.parseExpression("foo[foo[NEW]]");
o = expression.getValue(new MapHolder());
assertEquals("37",o);
expression = (SpelExpression)parser.parseExpression("foo[foo[new]]");
o = expression.getValue(new MapHolder());
assertEquals("38",o);
expression = (SpelExpression)parser.parseExpression("foo[foo[foo[T]]]");
o = expression.getValue(new MapHolder());
assertEquals("value",o);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static class MapHolder {
public Map foo;
public MapHolder() {
foo = new HashMap();
foo.put("NEW", "VALUE");
foo.put("new", "value");
foo.put("T", "TV");
foo.put("t", "tv");
foo.put("abc.def", "value");
foo.put("VALUE","37");
foo.put("value","38");
foo.put("TV","new");
}
}
}

Loading…
Cancel
Save