SPR-6230: SpEL improvements

This commit is contained in:
Andy Clement
2009-10-13 18:11:34 +00:00
parent 06286b19ce
commit c9057fd1da
19 changed files with 848 additions and 77 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.expression.spel;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.Map;
@@ -117,8 +118,10 @@ public class ExpressionStateTests extends ExpressionTestCase {
ExpressionState state = getState();
Assert.assertEquals(Inventor.class,state.getRootContextObject().getValue().getClass());
// although the root object is being set on the evaluation context, the value in the 'state' remains what it was when constructed
((StandardEvaluationContext) state.getEvaluationContext()).setRootObject(null);
Assert.assertEquals(null, state.getRootContextObject().getValue());
Assert.assertEquals(Inventor.class,state.getRootContextObject().getValue().getClass());
// Assert.assertEquals(null, state.getRootContextObject().getValue());
state = new ExpressionState(new StandardEvaluationContext());
Assert.assertEquals(TypedValue.NULL_TYPED_VALUE,state.getRootContextObject());
@@ -133,6 +136,13 @@ public class ExpressionStateTests extends ExpressionTestCase {
ExpressionState state = getState();
Assert.assertEquals(state.getRootContextObject().getValue(),state.getActiveContextObject().getValue());
try {
state.popActiveContextObject();
Assert.fail("stack should be empty...");
} catch (EmptyStackException ese) {
// success
}
state.pushActiveContextObject(new TypedValue(34));
Assert.assertEquals(34,state.getActiveContextObject().getValue());
@@ -168,6 +178,17 @@ public class ExpressionStateTests extends ExpressionTestCase {
Assert.assertNull(state.lookupLocalVariable("goo"));
}
@Test
public void testRootObjectConstructor() {
EvaluationContext ctx = getContext();
// TypedValue root = ctx.getRootObject();
// supplied should override root on context
ExpressionState state = new ExpressionState(ctx,new TypedValue("i am a string"));
TypedValue stateRoot = state.getRootContextObject();
Assert.assertEquals(String.class,stateRoot.getTypeDescriptor().getType());
Assert.assertEquals("i am a string",stateRoot.getValue());
}
@Test
public void testPopulatedNestedScopesMap() {
ExpressionState state = getState();
@@ -257,5 +278,9 @@ public class ExpressionStateTests extends ExpressionTestCase {
ExpressionState state = new ExpressionState(context);
return state;
}
private EvaluationContext getContext() {
return TestScenarioCreator.getTestEvaluationContext();
}
}

View File

@@ -26,6 +26,7 @@ import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.ParseException;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
import org.springframework.expression.spel.ast.FormatHelper;
import org.springframework.expression.spel.support.ReflectionHelper;
@@ -307,6 +308,82 @@ public class HelperTests extends ExpressionTestCase {
// Assert.assertEquals(0,rpr.read(ctx,t,"field3").getValue());
Assert.assertEquals(false,rpr.read(ctx,t,"property4").getValue());
Assert.assertTrue(rpr.canRead(ctx,t,"property4"));
}
@Test
public void testOptimalReflectivePropertyResolver() throws Exception {
ReflectivePropertyResolver rpr = new ReflectivePropertyResolver();
Tester t = new Tester();
t.setProperty("hello");
EvaluationContext ctx = new StandardEvaluationContext(t);
// Assert.assertTrue(rpr.canRead(ctx, t, "property"));
// Assert.assertEquals("hello",rpr.read(ctx, t, "property").getValue());
// Assert.assertEquals("hello",rpr.read(ctx, t, "property").getValue()); // cached accessor used
PropertyAccessor optA = rpr.createOptimalAccessor(ctx, t, "property");
Assert.assertTrue(optA.canRead(ctx, t, "property"));
Assert.assertFalse(optA.canRead(ctx, t, "property2"));
try {
optA.canWrite(ctx, t, "property");
Assert.fail();
} catch (UnsupportedOperationException uoe) {
// success
}
try {
optA.canWrite(ctx, t, "property2");
Assert.fail();
} catch (UnsupportedOperationException uoe) {
// success
}
Assert.assertEquals("hello",optA.read(ctx, t, "property").getValue());
Assert.assertEquals("hello",optA.read(ctx, t, "property").getValue()); // cached accessor used
try {
optA.getSpecificTargetClasses();
Assert.fail();
} catch (UnsupportedOperationException uoe) {
// success
}
try {
optA.write(ctx,t,"property",null);
Assert.fail();
} catch (UnsupportedOperationException uoe) {
// success
}
optA = rpr.createOptimalAccessor(ctx, t, "field");
Assert.assertTrue(optA.canRead(ctx, t, "field"));
Assert.assertFalse(optA.canRead(ctx, t, "field2"));
try {
optA.canWrite(ctx, t, "field");
Assert.fail();
} catch (UnsupportedOperationException uoe) {
// success
}
try {
optA.canWrite(ctx, t, "field2");
Assert.fail();
} catch (UnsupportedOperationException uoe) {
// success
}
Assert.assertEquals(3,optA.read(ctx, t, "field").getValue());
Assert.assertEquals(3,optA.read(ctx, t, "field").getValue()); // cached accessor used
try {
optA.getSpecificTargetClasses();
Assert.fail();
} catch (UnsupportedOperationException uoe) {
// success
}
try {
optA.write(ctx,t,"field",null);
Assert.fail();
} catch (UnsupportedOperationException uoe) {
// success
}
}

View File

@@ -37,9 +37,17 @@ public class LiteralExpressionTests {
EvaluationContext ctx = new StandardEvaluationContext();
checkString("somevalue", lEx.getValue(ctx));
checkString("somevalue", lEx.getValue(ctx, String.class));
checkString("somevalue", lEx.getValue(new Rooty()));
checkString("somevalue", lEx.getValue(new Rooty(), String.class));
checkString("somevalue", lEx.getValue(ctx, new Rooty()));
checkString("somevalue", lEx.getValue(ctx, new Rooty(),String.class));
Assert.assertEquals("somevalue", lEx.getExpressionString());
Assert.assertFalse(lEx.isWritable(new StandardEvaluationContext()));
Assert.assertFalse(lEx.isWritable(new Rooty()));
Assert.assertFalse(lEx.isWritable(new StandardEvaluationContext(), new Rooty()));
}
static class Rooty {}
@Test
public void testSetValue() {
@@ -52,6 +60,24 @@ public class LiteralExpressionTests {
// success, not allowed - whilst here, check the expression value in the exception
Assert.assertEquals(ee.getExpressionString(), "somevalue");
}
try {
LiteralExpression lEx = new LiteralExpression("somevalue");
lEx.setValue(new Rooty(), "flibble");
Assert.fail("Should have got an exception that the value cannot be set");
}
catch (EvaluationException ee) {
// success, not allowed - whilst here, check the expression value in the exception
Assert.assertEquals(ee.getExpressionString(), "somevalue");
}
try {
LiteralExpression lEx = new LiteralExpression("somevalue");
lEx.setValue(new StandardEvaluationContext(), new Rooty(), "flibble");
Assert.fail("Should have got an exception that the value cannot be set");
}
catch (EvaluationException ee) {
// success, not allowed - whilst here, check the expression value in the exception
Assert.assertEquals(ee.getExpressionString(), "somevalue");
}
}
@Test
@@ -59,6 +85,12 @@ public class LiteralExpressionTests {
LiteralExpression lEx = new LiteralExpression("somevalue");
Assert.assertEquals(String.class, lEx.getValueType());
Assert.assertEquals(String.class, lEx.getValueType(new StandardEvaluationContext()));
Assert.assertEquals(String.class, lEx.getValueType(new Rooty()));
Assert.assertEquals(String.class, lEx.getValueType(new StandardEvaluationContext(), new Rooty()));
Assert.assertEquals(String.class, lEx.getValueTypeDescriptor().getType());
Assert.assertEquals(String.class, lEx.getValueTypeDescriptor(new StandardEvaluationContext()).getType());
Assert.assertEquals(String.class, lEx.getValueTypeDescriptor(new Rooty()).getType());
Assert.assertEquals(String.class, lEx.getValueTypeDescriptor(new StandardEvaluationContext(), new Rooty()).getType());
}
private void checkString(String expectedString, Object value) {

View File

@@ -20,6 +20,7 @@ import junit.framework.Assert;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.Expression;
import org.springframework.expression.ParseException;
import org.springframework.expression.ParserContext;
@@ -98,6 +99,10 @@ public class TemplateExpressionParsingTests extends ExpressionTestCase {
expr = parser.parseExpression("abc", DEFAULT_TEMPLATE_PARSER_CONTEXT);
o = expr.getValue();
Assert.assertEquals("abc", o.toString());
expr = parser.parseExpression("abc", DEFAULT_TEMPLATE_PARSER_CONTEXT);
o = expr.getValue((Object)null);
Assert.assertEquals("abc", o.toString());
}
@Test
@@ -106,13 +111,53 @@ public class TemplateExpressionParsingTests extends ExpressionTestCase {
Expression ex = parser.parseExpression("hello ${'world'}", DEFAULT_TEMPLATE_PARSER_CONTEXT);
checkString("hello world", ex.getValue());
checkString("hello world", ex.getValue(String.class));
checkString("hello world", ex.getValue((Object)null, String.class));
checkString("hello world", ex.getValue(new Rooty()));
checkString("hello world", ex.getValue(new Rooty(), String.class));
EvaluationContext ctx = new StandardEvaluationContext();
checkString("hello world", ex.getValue(ctx));
checkString("hello world", ex.getValue(ctx, String.class));
checkString("hello world", ex.getValue(ctx, null, String.class));
checkString("hello world", ex.getValue(ctx, new Rooty()));
checkString("hello world", ex.getValue(ctx, new Rooty(), String.class));
checkString("hello world", ex.getValue(ctx, new Rooty(), String.class));
Assert.assertEquals("hello ${'world'}", ex.getExpressionString());
Assert.assertFalse(ex.isWritable(new StandardEvaluationContext()));
Assert.assertFalse(ex.isWritable(new Rooty()));
Assert.assertFalse(ex.isWritable(new StandardEvaluationContext(), new Rooty()));
Assert.assertEquals(String.class,ex.getValueType());
Assert.assertEquals(String.class,ex.getValueType(ctx));
Assert.assertEquals(String.class,ex.getValueTypeDescriptor().getType());
Assert.assertEquals(String.class,ex.getValueTypeDescriptor(ctx).getType());
Assert.assertEquals(String.class,ex.getValueType(new Rooty()));
Assert.assertEquals(String.class,ex.getValueType(ctx, new Rooty()));
Assert.assertEquals(String.class,ex.getValueTypeDescriptor(new Rooty()).getType());
Assert.assertEquals(String.class,ex.getValueTypeDescriptor(ctx, new Rooty()).getType());
try {
ex.setValue(ctx, null);
Assert.fail();
} catch (EvaluationException ee) {
// success
}
try {
ex.setValue((Object)null, null);
Assert.fail();
} catch (EvaluationException ee) {
// success
}
try {
ex.setValue(ctx, null, null);
Assert.fail();
} catch (EvaluationException ee) {
// success
}
}
static class Rooty {}
@Test
public void testNestedExpressions() throws Exception {
SpelExpressionParser parser = new SpelExpressionParser();
@@ -204,6 +249,16 @@ public class TemplateExpressionParsingTests extends ExpressionTestCase {
Assert.assertEquals("abc", tpc.getExpressionPrefix());
Assert.assertEquals("def", tpc.getExpressionSuffix());
Assert.assertTrue(tpc.isTemplate());
tpc = new TemplateParserContext();
Assert.assertEquals("#{", tpc.getExpressionPrefix());
Assert.assertEquals("}", tpc.getExpressionSuffix());
Assert.assertTrue(tpc.isTemplate());
ParserContext pc = ParserContext.TEMPLATE_EXPRESSION;
Assert.assertEquals("#{", pc.getExpressionPrefix());
Assert.assertEquals("}", pc.getExpressionSuffix());
Assert.assertTrue(pc.isTemplate());
}
// ---