Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
0d963a69
S
spring-framework
项目概览
爱吃血肠
/
spring-framework
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-framework
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
0d963a69
编写于
8月 09, 2012
作者:
S
Sam Brannen
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #115 from aclement/SPR-9614
* SPR-9614: Support symbolic boolean operators for OR and AND
上级
62495394
58e6214b
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
56 addition
and
31 deletion
+56
-31
spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java
...xpression/spel/standard/InternalSpelExpressionParser.java
+3
-5
spring-expression/src/main/java/org/springframework/expression/spel/standard/TokenKind.java
...g/springframework/expression/spel/standard/TokenKind.java
+2
-2
spring-expression/src/main/java/org/springframework/expression/spel/standard/Tokenizer.java
...g/springframework/expression/spel/standard/Tokenizer.java
+30
-22
spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java
...ngframework/expression/spel/standard/SpelParserTests.java
+19
-1
src/dist/changelog.txt
src/dist/changelog.txt
+2
-1
未找到文件。
spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java
浏览文件 @
0d963a69
...
...
@@ -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 {
// 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 {
}
}
//startNode
// : parenExpr | literal
// | type
...
...
@@ -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 {
return
t
.
kind
==
TokenKind
.
SELECT
||
t
.
kind
==
TokenKind
.
SELECT_FIRST
||
t
.
kind
==
TokenKind
.
SELECT_LAST
;
}
private
boolean
moreTokens
()
{
return
tokenStreamPointer
<
tokenStream
.
size
();
}
...
...
spring-expression/src/main/java/org/springframework/expression/spel/standard/TokenKind.java
浏览文件 @
0d963a69
/*
* Copyright 2002-20
09
the original author or authors.
* Copyright 2002-20
12
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 {
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
;
...
...
spring-expression/src/main/java/org/springframework/expression/spel/standard/Tokenizer.java
浏览文件 @
0d963a69
...
...
@@ -38,7 +38,7 @@ class Tokenizer {
int
pos
;
int
max
;
List
<
Token
>
tokens
=
new
ArrayList
<
Token
>();
public
Tokenizer
(
String
inputdata
)
{
this
.
expressionString
=
inputdata
;
this
.
toProcess
=
(
inputdata
+
"\0"
).
toCharArray
();
...
...
@@ -46,7 +46,7 @@ class Tokenizer {
this
.
pos
=
0
;
process
();
}
public
void
process
()
{
while
(
pos
<
max
)
{
char
ch
=
toProcess
[
pos
];
...
...
@@ -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
);
...
...
@@ -195,12 +205,11 @@ class Tokenizer {
}
}
}
public
List
<
Token
>
getTokens
()
{
return
tokens
;
}
// STRING_LITERAL: '\''! (APOS|~'\'')* '\''!;
private
void
lexQuotedStringLiteral
()
{
int
start
=
pos
;
...
...
@@ -223,7 +232,7 @@ class Tokenizer {
pos
++;
tokens
.
add
(
new
Token
(
TokenKind
.
LITERAL_STRING
,
subarray
(
start
,
pos
),
start
,
pos
));
}
// DQ_STRING_LITERAL: '"'! (~'"')* '"'!;
private
void
lexDoubleQuotedStringLiteral
()
{
int
start
=
pos
;
...
...
@@ -241,8 +250,7 @@ class Tokenizer {
pos
++;
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)?) |
...
...
@@ -256,7 +264,7 @@ class Tokenizer {
// fragment REAL_TYPE_SUFFIX : 'F' | 'f' | 'D' | 'd';
// INTEGER_LITERAL
// : (DECIMAL_DIGIT)+ (INTEGER_TYPE_SUFFIX)?;
private
void
lexNumericLiteral
(
boolean
firstCharIsZero
)
{
boolean
isReal
=
false
;
int
start
=
pos
;
...
...
@@ -353,10 +361,10 @@ class Tokenizer {
}
}
}
// if this is changed, it must remain sorted
private
static
final
String
[]
alternativeOperatorNames
=
{
"DIV"
,
"EQ"
,
"GE"
,
"GT"
,
"LE"
,
"LT"
,
"MOD"
,
"NE"
,
"NOT"
};
private
void
lexIdentifier
()
{
int
start
=
pos
;
do
{
...
...
@@ -375,7 +383,7 @@ class Tokenizer {
}
tokens
.
add
(
new
Token
(
TokenKind
.
IDENTIFIER
,
subarray
,
start
,
pos
));
}
private
void
pushIntToken
(
char
[]
data
,
boolean
isLong
,
int
start
,
int
end
)
{
if
(
isLong
)
{
tokens
.
add
(
new
Token
(
TokenKind
.
LITERAL_LONG
,
data
,
start
,
end
));
...
...
@@ -398,7 +406,7 @@ class Tokenizer {
tokens
.
add
(
new
Token
(
TokenKind
.
LITERAL_HEXINT
,
data
,
start
,
end
));
}
}
private
void
pushRealToken
(
char
[]
data
,
boolean
isFloat
,
int
start
,
int
end
)
{
if
(
isFloat
)
{
tokens
.
add
(
new
Token
(
TokenKind
.
LITERAL_REAL_FLOAT
,
data
,
start
,
end
));
...
...
@@ -406,13 +414,13 @@ class Tokenizer {
tokens
.
add
(
new
Token
(
TokenKind
.
LITERAL_REAL
,
data
,
start
,
end
));
}
}
private
char
[]
subarray
(
int
start
,
int
end
)
{
char
[]
result
=
new
char
[
end
-
start
];
System
.
arraycopy
(
toProcess
,
start
,
result
,
0
,
end
-
start
);
return
result
;
}
/**
* Check if this might be a two character token.
*/
...
...
@@ -421,7 +429,7 @@ class Tokenizer {
Assert
.
isTrue
(
toProcess
[
pos
]
==
kind
.
tokenChars
[
0
]);
return
toProcess
[
pos
+
1
]
==
kind
.
tokenChars
[
1
];
}
/**
* Push a token of just one character in length.
*/
...
...
@@ -429,7 +437,7 @@ class Tokenizer {
tokens
.
add
(
new
Token
(
kind
,
pos
,
pos
+
1
));
pos
++;
}
/**
* Push a token of two characters in length.
*/
...
...
@@ -437,7 +445,7 @@ class Tokenizer {
tokens
.
add
(
new
Token
(
kind
,
pos
,
pos
+
2
));
pos
+=
2
;
}
private
void
pushOneCharOrTwoCharToken
(
TokenKind
kind
,
int
pos
,
char
[]
data
)
{
tokens
.
add
(
new
Token
(
kind
,
data
,
pos
,
pos
+
kind
.
getLength
()));
}
...
...
@@ -446,7 +454,7 @@ class Tokenizer {
private
boolean
isIdentifier
(
char
ch
)
{
return
isAlphabetic
(
ch
)
||
isDigit
(
ch
)
||
ch
==
'_'
||
ch
==
'$'
;
}
private
boolean
isChar
(
char
a
,
char
b
)
{
char
ch
=
toProcess
[
pos
];
return
ch
==
a
||
ch
==
b
;
...
...
@@ -467,7 +475,7 @@ class Tokenizer {
private
boolean
isSign
(
char
ch
)
{
return
ch
==
'+'
||
ch
==
'-'
;
}
private
boolean
isDigit
(
char
ch
)
{
if
(
ch
>
255
)
{
return
false
;
...
...
@@ -481,14 +489,14 @@ class Tokenizer {
}
return
(
flags
[
ch
]
&
IS_ALPHA
)!=
0
;
}
private
boolean
isHexadecimalDigit
(
char
ch
)
{
if
(
ch
>
255
)
{
return
false
;
}
return
(
flags
[
ch
]
&
IS_HEXDIGIT
)!=
0
;
}
private
static
final
byte
flags
[]
=
new
byte
[
256
];
private
static
final
byte
IS_DIGIT
=
0x01
;
private
static
final
byte
IS_HEXDIGIT
=
0x02
;
...
...
spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java
浏览文件 @
0d963a69
...
...
@@ -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+
\t
3"
);
assertEquals
(
5
,
expr
.
getValue
());
expr
=
parser
.
parseRaw
(
"2\r\n+\t3"
);
assertEquals
(
5
,
expr
.
getValue
());
...
...
@@ -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'"
);
...
...
src/dist/changelog.txt
浏览文件 @
0d963a69
...
...
@@ -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)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录