starting to sort out like/matches. Matches is the java regex related one. Like is the SQL related one. But the spring .net 'like' doesn't seem to be the same as the SQL doc I found for like...
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@78 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
c7be5092e1
commit
de965b88ea
|
|
@ -23,4 +23,6 @@ Syntax
|
||||||
So 'l'.charAt(0) was required - wonder if we can build in a converter for a single length string to char?
|
So 'l'.charAt(0) was required - wonder if we can build in a converter for a single length string to char?
|
||||||
Can't do that as equals take Object and so we don't know to do a cast in order to pass a char into equals
|
Can't do that as equals take Object and so we don't know to do a cast in order to pass a char into equals
|
||||||
We certainly cannot do a cast (unless casts are added to the syntax). See MethodInvocationTest.testStringClass()
|
We certainly cannot do a cast (unless casts are added to the syntax). See MethodInvocationTest.testStringClass()
|
||||||
|
- MATCHES is now the thing that takes a java regex. What does 'like' do? right now it is the SQL LIKE that supports
|
||||||
|
wildcards % and _. It has a poor implementation but I need to know whether to keep it in the language before
|
||||||
|
fixing that.
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,9 @@ public enum SpelMessages {
|
||||||
Kind.ERROR, 1063, "A problem occurred whilst attempting to set the property ''{0}'': ''{1}''"), NOT_AN_INTEGER(
|
Kind.ERROR, 1063, "A problem occurred whilst attempting to set the property ''{0}'': ''{1}''"), NOT_AN_INTEGER(
|
||||||
Kind.ERROR, 1064, "The value ''{0}'' cannot be parsed as an int"), NOT_A_LONG(Kind.ERROR, 1065,
|
Kind.ERROR, 1064, "The value ''{0}'' cannot be parsed as an int"), NOT_A_LONG(Kind.ERROR, 1065,
|
||||||
"The value ''{0}'' cannot be parsed as a long"), PARSE_PROBLEM(Kind.ERROR, 1066,
|
"The value ''{0}'' cannot be parsed as a long"), PARSE_PROBLEM(Kind.ERROR, 1066,
|
||||||
"Error occurred during expression parse: {0}"), ;
|
"Error occurred during expression parse: {0}"), INVALID_FIRST_OPERAND_FOR_MATCHES_OPERATOR(Kind.ERROR,
|
||||||
|
1067, "First operand to matches operator must be a string. ''{0}'' is not"), INVALID_SECOND_OPERAND_FOR_MATCHES_OPERATOR(
|
||||||
|
Kind.ERROR, 1068, "Second operand to matches operator must be a string. ''{0}'' is not");
|
||||||
|
|
||||||
private Kind kind;
|
private Kind kind;
|
||||||
private int code;
|
private int code;
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,14 @@ import java.util.regex.PatternSyntaxException;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the like operator. The expected operands for like are a string and a pattern (JDK regex). The operator
|
* Implements the like operator. The like operator behaves the same as the SQL LIKE operator. The first operand is
|
||||||
* will return true if the string matches the regex.
|
* compared against the expression supplied as the second operand. This expression supports two wildcards: % meaning any
|
||||||
|
* string of any length, and _ meaning any single character.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*/
|
*/
|
||||||
|
|
@ -43,10 +44,10 @@ public class OperatorLike extends Operator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValue(ExpressionState state) throws EvaluationException {
|
public Boolean getValue(ExpressionState state) throws EvaluationException {
|
||||||
SpelNode leftOp = getLeftOperand();
|
SpelNode leftOp = getLeftOperand();
|
||||||
SpelNode rightOp = getRightOperand();
|
SpelNode rightOp = getRightOperand();
|
||||||
Object left = leftOp.getValue(state);
|
Object left = leftOp.getValue(state, String.class);
|
||||||
Object right = getRightOperand().getValue(state);
|
Object right = getRightOperand().getValue(state);
|
||||||
try {
|
try {
|
||||||
if (!(left instanceof String)) {
|
if (!(left instanceof String)) {
|
||||||
|
|
@ -57,12 +58,16 @@ public class OperatorLike extends Operator {
|
||||||
throw new SpelException(rightOp.getCharPositionInLine(),
|
throw new SpelException(rightOp.getCharPositionInLine(),
|
||||||
SpelMessages.INVALID_SECOND_OPERAND_FOR_LIKE_OPERATOR, right);
|
SpelMessages.INVALID_SECOND_OPERAND_FOR_LIKE_OPERATOR, right);
|
||||||
}
|
}
|
||||||
Pattern pattern = Pattern.compile((String) right);
|
// Translate that pattern to a java regex
|
||||||
|
// not really the best option, what if the right operand already had regex related chars in it?
|
||||||
|
String likePattern = (String) right;
|
||||||
|
likePattern = likePattern.replace('_', '.');
|
||||||
|
likePattern = likePattern.replaceAll("%", ".*");
|
||||||
|
Pattern pattern = Pattern.compile(likePattern);
|
||||||
Matcher matcher = pattern.matcher((String) left);
|
Matcher matcher = pattern.matcher((String) left);
|
||||||
return matcher.matches();
|
return matcher.matches();
|
||||||
} catch (PatternSyntaxException pse) {
|
} catch (PatternSyntaxException pse) {
|
||||||
throw new SpelException(rightOp.getCharPositionInLine(), pse, SpelMessages.INVALID_PATTERN, right);
|
throw new SpelException(rightOp.getCharPositionInLine(), pse, SpelMessages.INVALID_PATTERN, right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,11 +58,11 @@ public class OperatorMatches extends Operator {
|
||||||
try {
|
try {
|
||||||
if (!(left instanceof String)) {
|
if (!(left instanceof String)) {
|
||||||
throw new SpelException(leftOp.getCharPositionInLine(),
|
throw new SpelException(leftOp.getCharPositionInLine(),
|
||||||
SpelMessages.INVALID_FIRST_OPERAND_FOR_LIKE_OPERATOR, left);
|
SpelMessages.INVALID_FIRST_OPERAND_FOR_MATCHES_OPERATOR, left);
|
||||||
}
|
}
|
||||||
if (!(right instanceof String)) {
|
if (!(right instanceof String)) {
|
||||||
throw new SpelException(rightOp.getCharPositionInLine(),
|
throw new SpelException(rightOp.getCharPositionInLine(),
|
||||||
SpelMessages.INVALID_SECOND_OPERAND_FOR_LIKE_OPERATOR, right);
|
SpelMessages.INVALID_SECOND_OPERAND_FOR_MATCHES_OPERATOR, right);
|
||||||
}
|
}
|
||||||
Pattern pattern = Pattern.compile((String) right);
|
Pattern pattern = Pattern.compile((String) right);
|
||||||
Matcher matcher = pattern.matcher((String) left);
|
Matcher matcher = pattern.matcher((String) left);
|
||||||
|
|
|
||||||
|
|
@ -58,21 +58,25 @@ public class EvaluationTests extends ExpressionTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRelOperatorsLike01() {
|
public void testRelOperatorsLike01() {
|
||||||
evaluate("'Abc' like '[A-Z]b.*'", "true", Boolean.class);
|
evaluate("'Abc' like 'A%_'", "true", Boolean.class);
|
||||||
} // not the same as CSharp thing which matched '[A-Z]b*'
|
}
|
||||||
|
|
||||||
public void testRelOperatorsLike02() {
|
public void testRelOperatorsLike02() {
|
||||||
evaluate("'Abc' like '..'", "false", Boolean.class);
|
evaluate("'Abc' like '..'", "false", Boolean.class);
|
||||||
} // was '?'
|
}
|
||||||
|
|
||||||
public void testRelOperatorsLike03() {
|
public void testRelOperatorsLike03() {
|
||||||
evaluateAndCheckError("7 like '.'", SpelMessages.INVALID_FIRST_OPERAND_FOR_LIKE_OPERATOR);
|
evaluateAndCheckError("null like '.'", SpelMessages.INVALID_FIRST_OPERAND_FOR_LIKE_OPERATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRelOperatorsLike04() {
|
public void testRelOperatorsLike04() {
|
||||||
evaluateAndCheckError("'abc' like 2.0", SpelMessages.INVALID_SECOND_OPERAND_FOR_LIKE_OPERATOR);
|
evaluateAndCheckError("'abc' like 2.0", SpelMessages.INVALID_SECOND_OPERAND_FOR_LIKE_OPERATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testRelOperatorsLike05() {
|
||||||
|
evaluate("27 like '__'", "true", Boolean.class); // conversion int>string
|
||||||
|
}
|
||||||
|
|
||||||
public void testRelOperatorsBetween01() {
|
public void testRelOperatorsBetween01() {
|
||||||
evaluate("1 between {1, 5}", "true", Boolean.class);
|
evaluate("1 between {1, 5}", "true", Boolean.class);
|
||||||
}
|
}
|
||||||
|
|
@ -122,11 +126,11 @@ public class EvaluationTests extends ExpressionTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRelOperatorsMatches03() {
|
public void testRelOperatorsMatches03() {
|
||||||
evaluateAndCheckError("null matches '^.*$'", SpelMessages.INVALID_FIRST_OPERAND_FOR_LIKE_OPERATOR, 0, null);
|
evaluateAndCheckError("null matches '^.*$'", SpelMessages.INVALID_FIRST_OPERAND_FOR_MATCHES_OPERATOR, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRelOperatorsMatches04() {
|
public void testRelOperatorsMatches04() {
|
||||||
evaluateAndCheckError("'abc' matches null", SpelMessages.INVALID_SECOND_OPERAND_FOR_LIKE_OPERATOR, 14, null);
|
evaluateAndCheckError("'abc' matches null", SpelMessages.INVALID_SECOND_OPERAND_FOR_MATCHES_OPERATOR, 14, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRelOperatorsMatches05() {
|
public void testRelOperatorsMatches05() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue