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:
Andy Clement 2008-08-17 01:42:06 +00:00
parent c7be5092e1
commit de965b88ea
5 changed files with 30 additions and 17 deletions

View File

@ -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?
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()
- 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.

View File

@ -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, 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,
"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 int code;

View File

@ -21,13 +21,14 @@ import java.util.regex.PatternSyntaxException;
import org.antlr.runtime.Token;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.spel.ExpressionState;
import org.springframework.expression.spel.SpelException;
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
* will return true if the string matches the regex.
* Implements the like operator. The like operator behaves the same as the SQL LIKE operator. The first operand is
* 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
*/
@ -43,10 +44,10 @@ public class OperatorLike extends Operator {
}
@Override
public Object getValue(ExpressionState state) throws EvaluationException {
public Boolean getValue(ExpressionState state) throws EvaluationException {
SpelNode leftOp = getLeftOperand();
SpelNode rightOp = getRightOperand();
Object left = leftOp.getValue(state);
Object left = leftOp.getValue(state, String.class);
Object right = getRightOperand().getValue(state);
try {
if (!(left instanceof String)) {
@ -57,12 +58,16 @@ public class OperatorLike extends Operator {
throw new SpelException(rightOp.getCharPositionInLine(),
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);
return matcher.matches();
} catch (PatternSyntaxException pse) {
throw new SpelException(rightOp.getCharPositionInLine(), pse, SpelMessages.INVALID_PATTERN, right);
}
}
}

View File

@ -58,11 +58,11 @@ public class OperatorMatches extends Operator {
try {
if (!(left instanceof String)) {
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)) {
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);
Matcher matcher = pattern.matcher((String) left);

View File

@ -58,21 +58,25 @@ public class EvaluationTests extends ExpressionTestCase {
}
public void testRelOperatorsLike01() {
evaluate("'Abc' like '[A-Z]b.*'", "true", Boolean.class);
} // not the same as CSharp thing which matched '[A-Z]b*'
evaluate("'Abc' like 'A%_'", "true", Boolean.class);
}
public void testRelOperatorsLike02() {
evaluate("'Abc' like '..'", "false", Boolean.class);
} // was '?'
}
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() {
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() {
evaluate("1 between {1, 5}", "true", Boolean.class);
}
@ -122,11 +126,11 @@ public class EvaluationTests extends ExpressionTestCase {
}
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() {
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() {