expression parser improvements from andy's feedback

This commit is contained in:
Keith Donald
2008-01-18 06:26:14 +00:00
parent f9721eba62
commit a738289792
22 changed files with 417 additions and 247 deletions

View File

@@ -1,8 +1,8 @@
package org.springframework.binding.expression.el;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.el.ELContext;
import javax.el.ELResolver;
@@ -14,7 +14,7 @@ import junit.framework.TestCase;
import org.jboss.el.ExpressionFactoryImpl;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionVariable;
import org.springframework.binding.expression.ParserException;
import org.springframework.binding.expression.support.ParserContextImpl;
public class ELExpressionParserTests extends TestCase {
@@ -24,120 +24,54 @@ public class ELExpressionParserTests extends TestCase {
parser.putContextFactory(TestBean.class, new TestELContextFactory());
}
private static class TestELContextFactory implements ELContextFactory {
public ELContext getELContext(final Object target, final VariableMapper variableMapper) {
return new ELContext() {
public ELResolver getELResolver() {
return new DefaultELResolver(target, null);
}
public FunctionMapper getFunctionMapper() {
return null;
}
public VariableMapper getVariableMapper() {
return variableMapper;
}
};
}
public void testParseSimpleEvalExpressionNoParserContext() {
String expressionString = "#{3 + 4}";
Expression exp = parser.parseExpression(expressionString, null);
assertEquals(new Long(7), exp.getValue(null));
}
public void testParseEvalExpressionExpectedResultTypeNull() {
String expressionString = "#{value}";
Class expressionTargetType = null;
Class expectedEvaluationResultType = null;
ExpressionVariable[] expressionVariables = null;
try {
parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
expressionVariables);
fail("Should have failed");
} catch (ParserException e) {
}
public void testParseSimpleEvalExpressionNoEvalContextWithTypeCoersion() {
String expressionString = "#{3 + 4}";
Expression exp = parser.parseExpression(expressionString, new ParserContextImpl().expect(Integer.class));
assertEquals(new Integer(7), exp.getValue(null));
}
public void testParseEvalExpression() {
public void testParseBeanEvalExpressionNoParserContext() {
String expressionString = "#{value}";
Class expressionTargetType = TestBean.class;
Class expectedEvaluationResultType = String.class;
ExpressionVariable[] expressionVariables = null;
Expression exp = parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
expressionVariables);
TestBean target = new TestBean();
assertEquals("foo", exp.getValue(target));
Expression exp = parser.parseExpression(expressionString, null);
assertEquals("foo", exp.getValue(new TestBean()));
}
public void testParseEvalExpressionNoTargetType() {
String expressionString = "#{value}";
Class expressionTargetType = null;
Class expectedEvaluationResultType = Object.class;
ExpressionVariable[] expressionVariables = null;
try {
parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
expressionVariables);
fail("Should have failed");
} catch (ParserException e) {
}
public void testParseEvalExpressionWithContextTypeCoersion() {
String expressionString = "#{maximum}";
Expression exp = parser.parseExpression(expressionString, new ParserContextImpl().expect(Long.class));
assertEquals(new Long(2), exp.getValue(new TestBean()));
}
public void testParseEvalExpressionNotRegisteredTargetType() {
String expressionString = "#{value}";
Class expressionTargetType = Map.class;
Class expectedEvaluationResultType = Object.class;
ExpressionVariable[] expressionVariables = null;
try {
parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
expressionVariables);
fail("Should have failed");
} catch (ParserException e) {
}
public void testParseEvalExpressionWithContextCustomTestBeanResolver() {
String expressionString = "#{specialProperty}";
Expression exp = parser.parseExpression(expressionString, new ParserContextImpl().context(TestBean.class));
assertEquals("Custom resolver resolved this special property!", exp.getValue(new TestBean()));
}
public void testParseLiteralExpression() {
String expressionString = "value";
Class expressionTargetType = TestBean.class;
Class expectedEvaluationResultType = String.class;
ExpressionVariable[] expressionVariables = null;
Expression exp = parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
expressionVariables);
TestBean target = new TestBean();
assertEquals("value", exp.getValue(target));
Expression exp = parser.parseExpression(expressionString, null);
assertEquals("value", exp.getValue(null));
}
public void testParseExpressionWithVariables() {
String expressionString = "#{value}#{max}";
Class expressionTargetType = TestBean.class;
Class expectedEvaluationResultType = String.class;
ExpressionVariable[] expressionVariables = new ExpressionVariable[] { new ExpressionVariable("max",
"#{maximum}") };
Expression exp = parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
expressionVariables);
Expression exp = parser.parseExpression(expressionString, new ParserContextImpl()
.variable(new ExpressionVariable("max", "#{maximum}")));
TestBean target = new TestBean();
assertEquals("foo2", exp.getValue(target));
}
public void testParseExpressionWithVariables2() {
String expressionString = "#{value}#{bean.encode(value)}";
Class expressionTargetType = TestBean.class;
Class expectedEvaluationResultType = String.class;
ExpressionVariable[] expressionVariables = null;
Expression exp = parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
expressionVariables);
TestBean target = new TestBean(new TestBean());
assertEquals("foo!foo", exp.getValue(target));
}
public void testParseExpressionCoerceToInteger() {
String expressionString = "#{maximum}#{max}";
Class expressionTargetType = TestBean.class;
Class expectedEvaluationResultType = Integer.class;
ExpressionVariable[] expressionVariables = new ExpressionVariable[] { new ExpressionVariable("max",
"#{maximum}") };
Expression exp = parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
expressionVariables);
TestBean target = new TestBean();
assertEquals(new Integer(22), exp.getValue(target));
public void testParseImmediateEvalExpression() {
String expressionString = "${3 + 4}";
Expression exp = parser.parseExpression(expressionString, null);
assertEquals(new Long(7), exp.getValue(null));
}
public static class TestBean {
@@ -187,6 +121,52 @@ public class ELExpressionParserTests extends TestCase {
public void setMaximum(int maximum) {
this.maximum = maximum;
}
}
private static class TestELContextFactory implements ELContextFactory {
public ELContext getELContext(final Object target, final VariableMapper variableMapper) {
return new ELContext() {
public ELResolver getELResolver() {
return new ELResolver() {
public Class getCommonPropertyType(ELContext arg0, Object arg1) {
return Object.class;
}
public Iterator getFeatureDescriptors(ELContext arg0, Object arg1) {
return null;
}
public Class getType(ELContext arg0, Object arg1, Object arg2) {
return String.class;
}
public Object getValue(ELContext arg0, Object arg1, Object arg2) {
if (arg1 == null && arg2.equals("specialProperty")) {
return "Custom resolver resolved this special property!";
} else {
throw new IllegalStateException();
}
}
public boolean isReadOnly(ELContext arg0, Object arg1, Object arg2) {
return true;
}
public void setValue(ELContext arg0, Object arg1, Object arg2, Object arg3) {
throw new UnsupportedOperationException("Not supported");
}
};
}
public FunctionMapper getFunctionMapper() {
return null;
}
public VariableMapper getVariableMapper() {
return variableMapper;
}
};
}
}
}

View File

@@ -18,7 +18,9 @@ package org.springframework.binding.expression.ognl;
import junit.framework.TestCase;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionVariable;
import org.springframework.binding.expression.ParserException;
import org.springframework.binding.expression.support.ParserContextImpl;
/**
* Unit tests for {@link org.springframework.binding.expression.ognl.OgnlExpressionParser}.
@@ -31,21 +33,21 @@ public class OgnlExpressionParserTests extends TestCase {
public void testParseSimple() {
String exp = "${flag}";
Expression e = parser.parseExpression(exp, null, null, null);
Expression e = parser.parseExpression(exp, null);
assertNotNull(e);
Boolean b = (Boolean) e.getValue(bean);
assertFalse(b.booleanValue());
}
public void testParseEmpty() {
Expression e = parser.parseExpression("", null, null, null);
Expression e = parser.parseExpression("", null);
assertNotNull(e);
assertEquals("", e.getValue(bean));
}
public void testParseComposite() {
String exp = "hello ${flag} ${flag} ${flag}";
Expression e = parser.parseExpression(exp, null, null, null);
Expression e = parser.parseExpression(exp, null);
assertNotNull(e);
String str = (String) e.getValue(bean);
assertEquals("hello false false false", str);
@@ -54,7 +56,7 @@ public class OgnlExpressionParserTests extends TestCase {
public void testEnclosedCompositeNotSupported() {
String exp = "${hello ${flag} ${flag} ${flag}}";
try {
parser.parseExpression(exp, null, null, null);
parser.parseExpression(exp, null);
fail("Should've failed - not intended use");
} catch (ParserException e) {
}
@@ -62,13 +64,13 @@ public class OgnlExpressionParserTests extends TestCase {
public void testSyntaxError1() {
try {
parser.parseExpression("${", null, null, null);
parser.parseExpression("${", null);
fail();
} catch (ParserException e) {
}
try {
String exp = "hello ${flag} ${abcd defg";
parser.parseExpression(exp, null, null, null);
parser.parseExpression(exp, null);
fail("Should've failed - not intended use");
} catch (ParserException e) {
}
@@ -76,13 +78,13 @@ public class OgnlExpressionParserTests extends TestCase {
public void testSyntaxError2() {
try {
parser.parseExpression("${}", null, null, null);
parser.parseExpression("${}", null);
fail("Should've failed - not intended use");
} catch (ParserException e) {
}
try {
String exp = "hello ${flag} ${}";
parser.parseExpression(exp, null, null, null);
parser.parseExpression(exp, null);
fail("Should've failed - not intended use");
} catch (ParserException e) {
}
@@ -90,24 +92,28 @@ public class OgnlExpressionParserTests extends TestCase {
public void testCollectionConstructionSyntax() {
// lists
parser.parseExpression("name in {null, \"Untitled\"}", null, null, null);
parser.parseExpression("${name in {null, \"Untitled\"}}", null, null, null);
parser.parseExpression("name in {null, \"Untitled\"}", null);
parser.parseExpression("${name in {null, \"Untitled\"}}", null);
// native arrays
parser.parseExpression("new int[] {1, 2, 3}", null, null, null);
parser.parseExpression("${new int[] {1, 2, 3}}", null, null, null);
parser.parseExpression("new int[] {1, 2, 3}", null);
parser.parseExpression("${new int[] {1, 2, 3}}", null);
// maps
parser.parseExpression("#{ 'foo' : 'foo value', 'bar' : 'bar value' }", null, null, null);
parser.parseExpression("${#{ 'foo' : 'foo value', 'bar' : 'bar value' }}", null, null, null);
parser.parseExpression("#@java.util.LinkedHashMap@{ 'foo' : 'foo value', 'bar' : 'bar value' }", null, null,
null);
parser.parseExpression("${#@java.util.LinkedHashMap@{ 'foo' : 'foo value', 'bar' : 'bar value' }}", null, null,
null);
parser.parseExpression("#{ 'foo' : 'foo value', 'bar' : 'bar value' }", null);
parser.parseExpression("${#{ 'foo' : 'foo value', 'bar' : 'bar value' }}", null);
parser.parseExpression("#@java.util.LinkedHashMap@{ 'foo' : 'foo value', 'bar' : 'bar value' }", null);
parser.parseExpression("${#@java.util.LinkedHashMap@{ 'foo' : 'foo value', 'bar' : 'bar value' }}", null);
// complex examples
parser.parseExpression("b,#{1:2}", null, null, null);
parser.parseExpression("${b,#{1:2}}", null, null, null);
parser.parseExpression("a${b,#{1:2},e}f${g,#{3:4},j}k", null, null, null);
parser.parseExpression("b,#{1:2}", null);
parser.parseExpression("${b,#{1:2}}", null);
parser.parseExpression("a${b,#{1:2},e}f${g,#{3:4},j}k", null);
}
public void testVariables() {
Expression exp = parser.parseExpression("${#var}", new ParserContextImpl().variable(new ExpressionVariable(
"var", new Integer(1))));
assertEquals(new Integer(1), exp.getValue(bean));
}
}