Browse Source

Merge pull request #115 from aclement/SPR-9614

* SPR-9614:
  Support symbolic boolean operators for OR and AND
pull/115/merge
Sam Brannen 12 years ago
parent
commit
0d963a690b
  1. 8
      spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java
  2. 4
      spring-expression/src/main/java/org/springframework/expression/spel/standard/TokenKind.java
  3. 12
      spring-expression/src/main/java/org/springframework/expression/spel/standard/Tokenizer.java
  4. 20
      spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java
  5. 3
      src/dist/changelog.txt

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

@ -169,7 +169,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -169,7 +169,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
//logicalOrExpression : logicalAndExpression (OR^ logicalAndExpression)*;
private SpelNodeImpl eatLogicalOrExpression() {
SpelNodeImpl expr = eatLogicalAndExpression();
while (peekIdentifierToken("or")) {
while (peekIdentifierToken("or") || peekToken(TokenKind.SYMBOLIC_OR)) {
Token t = nextToken(); //consume OR
SpelNodeImpl rhExpr = eatLogicalAndExpression();
checkRightOperand(t,rhExpr);
@ -181,7 +181,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -181,7 +181,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
// logicalAndExpression : relationalExpression (AND^ relationalExpression)*;
private SpelNodeImpl eatLogicalAndExpression() {
SpelNodeImpl expr = eatRelationalExpression();
while (peekIdentifierToken("and")) {
while (peekIdentifierToken("and") || peekToken(TokenKind.SYMBOLIC_AND)) {
Token t = nextToken();// consume 'AND'
SpelNodeImpl rhExpr = eatRelationalExpression();
checkRightOperand(t,rhExpr);
@ -432,7 +432,6 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -432,7 +432,6 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
}
}
//startNode
// : parenExpr | literal
// | type
@ -513,7 +512,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -513,7 +512,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
private boolean maybeEatNullReference() {
if (peekToken(TokenKind.IDENTIFIER)) {
Token nullToken = peekToken();
if (!nullToken.stringValue().toLowerCase().equals("null")) {
if (!nullToken.stringValue().equalsIgnoreCase("null")) {
return false;
}
nextToken();
@ -805,7 +804,6 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -805,7 +804,6 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
return t.kind==TokenKind.SELECT || t.kind==TokenKind.SELECT_FIRST || t.kind==TokenKind.SELECT_LAST;
}
private boolean moreTokens() {
return tokenStreamPointer<tokenStream.size();
}

4
spring-expression/src/main/java/org/springframework/expression/spel/standard/TokenKind.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.
@ -29,7 +29,7 @@ enum TokenKind { @@ -29,7 +29,7 @@ enum TokenKind {
DIV("/"), GE(">="), GT(">"), LE("<="), LT("<"), EQ("=="), NE("!="),
MOD("%"), NOT("!"), ASSIGN("="), INSTANCEOF("instanceof"), MATCHES("matches"), BETWEEN("between"),
SELECT("?["), POWER("^"),
ELVIS("?:"), SAFE_NAVI("?."), BEAN_REF("@")
ELVIS("?:"), SAFE_NAVI("?."), BEAN_REF("@"), SYMBOLIC_OR("||"), SYMBOLIC_AND("&&")
;
char[] tokenChars;

12
spring-expression/src/main/java/org/springframework/expression/spel/standard/Tokenizer.java

@ -128,6 +128,16 @@ class Tokenizer { @@ -128,6 +128,16 @@ class Tokenizer {
pushCharToken(TokenKind.ASSIGN);
}
break;
case '&':
if (isTwoCharToken(TokenKind.SYMBOLIC_AND)) {
pushPairToken(TokenKind.SYMBOLIC_AND);
}
break;
case '|':
if (isTwoCharToken(TokenKind.SYMBOLIC_OR)) {
pushPairToken(TokenKind.SYMBOLIC_OR);
}
break;
case '?':
if (isTwoCharToken(TokenKind.SELECT)) {
pushPairToken(TokenKind.SELECT);
@ -200,7 +210,6 @@ class Tokenizer { @@ -200,7 +210,6 @@ class Tokenizer {
return tokens;
}
// STRING_LITERAL: '\''! (APOS|~'\'')* '\''!;
private void lexQuotedStringLiteral() {
int start = pos;
@ -242,7 +251,6 @@ class Tokenizer { @@ -242,7 +251,6 @@ class Tokenizer {
tokens.add(new Token(TokenKind.LITERAL_STRING, subarray(start,pos), start, pos));
}
// REAL_LITERAL :
// ('.' (DECIMAL_DIGIT)+ (EXPONENT_PART)? (REAL_TYPE_SUFFIX)?) |
// ((DECIMAL_DIGIT)+ '.' (DECIMAL_DIGIT)+ (EXPONENT_PART)? (REAL_TYPE_SUFFIX)?) |

20
spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java

@ -70,7 +70,7 @@ public class SpelParserTests { @@ -70,7 +70,7 @@ public class SpelParserTests {
assertEquals(5, expr.getValue());
expr = parser.parseRaw("2 + 3");
assertEquals(5, expr.getValue());
expr = parser.parseRaw("2\n+ 3");
expr = parser.parseRaw("2\n+\t3");
assertEquals(5, expr.getValue());
expr = parser.parseRaw("2\r\n+\t3");
assertEquals(5, expr.getValue());
@ -229,6 +229,24 @@ public class SpelParserTests { @@ -229,6 +229,24 @@ public class SpelParserTests {
assertEquals(Boolean.FALSE, expr.getValue(Boolean.class));
}
@Test
public void booleanOperators_symbolic_spr9614() throws EvaluationException, ParseException {
SpelExpression expr = new SpelExpressionParser().parseRaw("true");
assertEquals(Boolean.TRUE, expr.getValue(Boolean.class));
expr = new SpelExpressionParser().parseRaw("false");
assertEquals(Boolean.FALSE, expr.getValue(Boolean.class));
expr = new SpelExpressionParser().parseRaw("false && false");
assertEquals(Boolean.FALSE, expr.getValue(Boolean.class));
expr = new SpelExpressionParser().parseRaw("true && (true || false)");
assertEquals(Boolean.TRUE, expr.getValue(Boolean.class));
expr = new SpelExpressionParser().parseRaw("true && true || false");
assertEquals(Boolean.TRUE, expr.getValue(Boolean.class));
expr = new SpelExpressionParser().parseRaw("!true");
assertEquals(Boolean.FALSE, expr.getValue(Boolean.class));
expr = new SpelExpressionParser().parseRaw("!(false || true)");
assertEquals(Boolean.FALSE, expr.getValue(Boolean.class));
}
@Test
public void stringLiterals() throws EvaluationException, ParseException {
SpelExpression expr = new SpelExpressionParser().parseRaw("'howdy'");

3
src/dist/changelog.txt vendored

@ -8,7 +8,8 @@ Changes in version 3.2 M2 (2012-08-xx) @@ -8,7 +8,8 @@ Changes in version 3.2 M2 (2012-08-xx)
* spring-test module now depends on junit:junit-dep (SPR-6966)
* now inferring return type of generic factory methods (SPR-9493)
* SpEL Tokenizer now supports methods on integers (SPR-9612)
* SpEL now supports method invocations on integers (SPR-9612)
* SpEL now supports symbolic boolean operators for OR and AND (SPR-9614)
* introduced support for case-insensitive null literals in SpEL expressions (SPR-9613)
* now using BufferedInputStream in SimpleMetaDataReader to double performance (SPR-9528)
* introduced "repeatCount" property in Quartz SimpleTriggerFactoryBean (SPR-9521)

Loading…
Cancel
Save