Backported DataBindingPropertyAccessor and DataBindingMethodResolver
Issue: SPR-16588
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -32,7 +32,9 @@ import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypedValue;
|
||||
import org.springframework.expression.spel.standard.SpelExpression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.testresources.Person;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -73,7 +75,7 @@ public class PropertyAccessTests extends AbstractExpressionTests {
|
||||
* supplied resolver might be able to - so null shouldn't crash the reflection resolver.
|
||||
*/
|
||||
@Test
|
||||
public void testAccessingOnNullObject() throws Exception {
|
||||
public void testAccessingOnNullObject() {
|
||||
SpelExpression expr = (SpelExpression)parser.parseExpression("madeup");
|
||||
EvaluationContext context = new StandardEvaluationContext(null);
|
||||
try {
|
||||
@@ -85,7 +87,7 @@ public class PropertyAccessTests extends AbstractExpressionTests {
|
||||
}
|
||||
assertFalse(expr.isWritable(context));
|
||||
try {
|
||||
expr.setValue(context,"abc");
|
||||
expr.setValue(context, "abc");
|
||||
fail("Should have failed - default property resolver cannot resolve on null");
|
||||
}
|
||||
catch (Exception ex) {
|
||||
@@ -93,19 +95,19 @@ public class PropertyAccessTests extends AbstractExpressionTests {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkException(Exception e, SpelMessage expectedMessage) {
|
||||
if (e instanceof SpelEvaluationException) {
|
||||
SpelMessage sm = ((SpelEvaluationException)e).getMessageCode();
|
||||
assertEquals("Expected exception type did not occur",expectedMessage,sm);
|
||||
private void checkException(Exception ex, SpelMessage expectedMessage) {
|
||||
if (ex instanceof SpelEvaluationException) {
|
||||
SpelMessage sm = ((SpelEvaluationException) ex).getMessageCode();
|
||||
assertEquals("Expected exception type did not occur", expectedMessage, sm);
|
||||
}
|
||||
else {
|
||||
fail("Should be a SpelException "+e);
|
||||
fail("Should be a SpelException " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
// Adding a new property accessor just for a particular type
|
||||
public void testAddingSpecificPropertyAccessor() throws Exception {
|
||||
public void testAddingSpecificPropertyAccessor() {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
StandardEvaluationContext ctx = new StandardEvaluationContext();
|
||||
|
||||
@@ -115,7 +117,7 @@ public class PropertyAccessTests extends AbstractExpressionTests {
|
||||
ctx.addPropertyAccessor(new StringyPropertyAccessor());
|
||||
Expression expr = parser.parseRaw("new String('hello').flibbles");
|
||||
Integer i = expr.getValue(ctx, Integer.class);
|
||||
assertEquals((int) i, 7);
|
||||
assertEquals(7, (int) i);
|
||||
|
||||
// The reflection one will be used for other properties...
|
||||
expr = parser.parseRaw("new String('hello').CASE_INSENSITIVE_ORDER");
|
||||
@@ -125,7 +127,7 @@ public class PropertyAccessTests extends AbstractExpressionTests {
|
||||
expr = parser.parseRaw("new String('hello').flibbles");
|
||||
expr.setValue(ctx, 99);
|
||||
i = expr.getValue(ctx, Integer.class);
|
||||
assertEquals((int) i, 99);
|
||||
assertEquals(99, (int) i);
|
||||
|
||||
// Cannot set it to a string value
|
||||
try {
|
||||
@@ -162,10 +164,10 @@ public class PropertyAccessTests extends AbstractExpressionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessingPropertyOfClass() throws Exception {
|
||||
public void testAccessingPropertyOfClass() {
|
||||
Expression expression = parser.parseExpression("name");
|
||||
Object value = expression.getValue(new StandardEvaluationContext(String.class));
|
||||
assertEquals(value, "java.lang.String");
|
||||
assertEquals("java.lang.String", value);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -182,6 +184,78 @@ public class PropertyAccessTests extends AbstractExpressionTests {
|
||||
assertEquals("Jens", expression.getValue(context));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void standardGetClassAccess() {
|
||||
assertEquals(String.class.getName(), parser.parseExpression("'a'.class.name").getValue());
|
||||
}
|
||||
|
||||
@Test(expected = SpelEvaluationException.class)
|
||||
public void noGetClassAccess() {
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
|
||||
parser.parseExpression("'a'.class.name").getValue(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyReadOnly() {
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
|
||||
Expression expr = parser.parseExpression("name");
|
||||
Person target = new Person("p1");
|
||||
assertEquals("p1", expr.getValue(context, target));
|
||||
target.setName("p2");
|
||||
assertEquals("p2", expr.getValue(context, target));
|
||||
|
||||
try {
|
||||
parser.parseExpression("name='p3'").getValue(context, target);
|
||||
fail("Should have thrown SpelEvaluationException");
|
||||
}
|
||||
catch (SpelEvaluationException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyReadWrite() {
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
|
||||
|
||||
Expression expr = parser.parseExpression("name");
|
||||
Person target = new Person("p1");
|
||||
assertEquals("p1", expr.getValue(context, target));
|
||||
target.setName("p2");
|
||||
assertEquals("p2", expr.getValue(context, target));
|
||||
|
||||
parser.parseExpression("name='p3'").getValue(context, target);
|
||||
assertEquals("p3", target.getName());
|
||||
assertEquals("p3", expr.getValue(context, target));
|
||||
|
||||
expr.setValue(context, target, "p4");
|
||||
assertEquals("p4", target.getName());
|
||||
assertEquals("p4", expr.getValue(context, target));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyAccessWithoutMethodResolver() {
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
|
||||
Person target = new Person("p1");
|
||||
try {
|
||||
parser.parseExpression("name.substring(1)").getValue(context, target);
|
||||
fail("Should have thrown SpelEvaluationException");
|
||||
}
|
||||
catch (SpelEvaluationException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyAccessWithInstanceMethodResolver() {
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().withInstanceMethods().build();
|
||||
|
||||
Person target = new Person("p1");
|
||||
assertEquals("1", parser.parseExpression("name.substring(1)").getValue(context, target));
|
||||
}
|
||||
|
||||
|
||||
// This can resolve the property 'flibbles' on any String (very useful...)
|
||||
private static class StringyPropertyAccessor implements PropertyAccessor {
|
||||
@@ -223,7 +297,8 @@ public class PropertyAccessTests extends AbstractExpressionTests {
|
||||
throw new RuntimeException("Assertion Failed! name should be flibbles");
|
||||
}
|
||||
try {
|
||||
flibbles = (Integer) context.getTypeConverter().convertValue(newValue, TypeDescriptor.forObject(newValue), TypeDescriptor.valueOf(Integer.class));
|
||||
flibbles = (Integer) context.getTypeConverter().convertValue(newValue,
|
||||
TypeDescriptor.forObject(newValue), TypeDescriptor.valueOf(Integer.class));
|
||||
}
|
||||
catch (EvaluationException ex) {
|
||||
throw new AccessException("Cannot set flibbles to an object of type '" + newValue.getClass() + "'");
|
||||
|
||||
Reference in New Issue
Block a user