initial typeDescriptor awareness in the EL. some basic testing of using GenericConversionService
This commit is contained in:
@@ -16,13 +16,14 @@
|
||||
|
||||
package org.springframework.expression.spel;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
@@ -264,6 +265,10 @@ public class ExpressionLanguageScenarioTests extends ExpressionTestCase {
|
||||
public void write(EvaluationContext context, Object target, String name, Object newValue)
|
||||
throws AccessException {
|
||||
}
|
||||
|
||||
public TypeDescriptor getTypeDescriptor(EvaluationContext context, Object target, String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -301,6 +306,9 @@ public class ExpressionLanguageScenarioTests extends ExpressionTestCase {
|
||||
|
||||
public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
|
||||
}
|
||||
|
||||
public TypeDescriptor getTypeDescriptor(EvaluationContext context, Object target, String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.expression.spel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.service.DefaultConversionService;
|
||||
import org.springframework.core.convert.service.GenericConversionService;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
|
||||
/**
|
||||
* Expression evaluation where the TypeConverter plugged in is the {@link GenericConversionService}
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
public class ExpressionTestsUsingCoreConversionService extends ExpressionTestCase {
|
||||
|
||||
private static List<String> listOfString = new ArrayList<String>();
|
||||
private static TypeDescriptor typeDescriptorForListOfString = null;
|
||||
private static List<Integer> listOfInteger = new ArrayList<Integer>();
|
||||
private static TypeDescriptor typeDescriptorForListOfInteger = null;
|
||||
|
||||
static {
|
||||
listOfString.add("1");
|
||||
listOfString.add("2");
|
||||
listOfString.add("3");
|
||||
listOfInteger.add(4);
|
||||
listOfInteger.add(5);
|
||||
listOfInteger.add(6);
|
||||
}
|
||||
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
typeDescriptorForListOfString = new TypeDescriptor(ExpressionTestsUsingCoreConversionService.class.getDeclaredField("listOfString"));
|
||||
typeDescriptorForListOfInteger = new TypeDescriptor(ExpressionTestsUsingCoreConversionService.class.getDeclaredField("listOfInteger"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test the service can convert what we are about to use in the expression evaluation tests.
|
||||
*/
|
||||
public void testConversionsAvailable() throws Exception {
|
||||
TypeConvertorUsingConversionService tcs = new TypeConvertorUsingConversionService();
|
||||
|
||||
// ArrayList containing List<Integer> to List<String>
|
||||
Class<?> clazz = typeDescriptorForListOfString.getElementType();
|
||||
assertEquals(String.class,clazz);
|
||||
ConversionExecutor executor = tcs.getConversionExecutor(ArrayList.class, typeDescriptorForListOfString);
|
||||
assertNotNull(executor);
|
||||
List l = (List)executor.execute(listOfInteger);
|
||||
assertNotNull(l);
|
||||
|
||||
// ArrayList containing List<String> to List<Integer>
|
||||
clazz = typeDescriptorForListOfInteger.getElementType();
|
||||
assertEquals(Integer.class,clazz);
|
||||
executor = tcs.getConversionExecutor(ArrayList.class, typeDescriptorForListOfInteger);
|
||||
assertNotNull(executor);
|
||||
l = (List)executor.execute(listOfString);
|
||||
assertNotNull(l);
|
||||
}
|
||||
|
||||
public void testSetParameterizedList() throws Exception {
|
||||
StandardEvaluationContext context = TestScenarioCreator.getTestEvaluationContext();
|
||||
Expression e = parser.parseExpression("listOfInteger.size()");
|
||||
assertEquals(0,e.getValue(context,Integer.class).intValue());
|
||||
context.setTypeConverter(new TypeConvertorUsingConversionService());
|
||||
// Assign a List<String> to the List<Integer> field - the component elements should be converted
|
||||
parser.parseExpression("listOfInteger").setValue(context,listOfString);
|
||||
assertEquals(3,e.getValue(context,Integer.class).intValue()); // size now 3
|
||||
Class clazz = parser.parseExpression("listOfInteger[1].getClass()").getValue(context,Class.class); // element type correctly Integer
|
||||
assertEquals(Integer.class,clazz);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Type convertor that uses the core conversion service.
|
||||
*/
|
||||
private static class TypeConvertorUsingConversionService extends DefaultConversionService implements TypeConverter {
|
||||
|
||||
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
|
||||
return super.canConvert(sourceType, TypeDescriptor.valueOf(targetType));
|
||||
}
|
||||
|
||||
public boolean canConvert(Class<?> sourceType, TypeDescriptor typeDescriptor) {
|
||||
return super.canConvert(sourceType, typeDescriptor);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertValue(Object value, Class<T> targetType) throws EvaluationException {
|
||||
return (T)super.executeConversion(value,TypeDescriptor.valueOf(targetType));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertValue(Object value, TypeDescriptor typeDescriptor)
|
||||
throws EvaluationException {
|
||||
return (T)super.executeConversion(value, typeDescriptor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package org.springframework.expression.spel;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
@@ -61,7 +62,7 @@ public class MapAccessTests extends ExpressionTestCase {
|
||||
}
|
||||
|
||||
|
||||
private static class MapAccessor implements PropertyAccessor {
|
||||
public static class MapAccessor implements PropertyAccessor {
|
||||
|
||||
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
|
||||
return (((Map) target).containsKey(name));
|
||||
@@ -75,6 +76,7 @@ public class MapAccessTests extends ExpressionTestCase {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void write(EvaluationContext context, Object target, String name, Object newValue)
|
||||
throws AccessException {
|
||||
((Map) target).put(name, newValue);
|
||||
@@ -83,6 +85,10 @@ public class MapAccessTests extends ExpressionTestCase {
|
||||
public Class<?>[] getSpecificTargetClasses() {
|
||||
return new Class[] { Map.class };
|
||||
}
|
||||
|
||||
public TypeDescriptor getTypeDescriptor(EvaluationContext context, Object target, String name) {
|
||||
return TypeDescriptor.valueOf(Map.class);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.expression.spel;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
@@ -87,6 +88,10 @@ public class PropertyAccessTests extends ExpressionTestCase {
|
||||
|
||||
int flibbles = 7;
|
||||
|
||||
public TypeDescriptor getTypeDescriptor(EvaluationContext context, Object target, String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Class<?>[] getSpecificTargetClasses() {
|
||||
return new Class[] { String.class };
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.expression.spel;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
@@ -224,6 +225,11 @@ public class ScenariosForSpringSecurity extends ExpressionTestCase {
|
||||
public Class<?>[] getSpecificTargetClasses() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public TypeDescriptor getTypeDescriptor(EvaluationContext context, Object target, String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -252,6 +258,10 @@ public class ScenariosForSpringSecurity extends ExpressionTestCase {
|
||||
public Class<?>[] getSpecificTargetClasses() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public TypeDescriptor getTypeDescriptor(EvaluationContext context, Object target, String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -98,11 +98,14 @@ public class SetValueTests extends ExpressionTestCase {
|
||||
setValueExpectError("'hello'[3]", 'p');
|
||||
}
|
||||
|
||||
// public void testSetPropertyTypeCoersion() {
|
||||
// setValue("publicBoolean", "true");
|
||||
// }
|
||||
|
||||
public void testSetPropertyTypeCoersion() {
|
||||
setValue("publicBoolean", "true", Boolean.TRUE);
|
||||
}
|
||||
|
||||
public void testSetPropertyTypeCoersionThroughSetter() {
|
||||
setValue("SomeProperty", "true", Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call setValue() but expect it to fail.
|
||||
*/
|
||||
@@ -116,7 +119,6 @@ public class SetValueTests extends ExpressionTestCase {
|
||||
SpelUtilities.printAbstractSyntaxTree(System.out, e);
|
||||
}
|
||||
StandardEvaluationContext lContext = TestScenarioCreator.getTestEvaluationContext();
|
||||
// assertTrue("Expression is not writeable but should be", e.isWritable(lContext));
|
||||
e.setValue(lContext, value);
|
||||
fail("expected an error");
|
||||
} catch (ParseException pe) {
|
||||
@@ -148,4 +150,30 @@ public class SetValueTests extends ExpressionTestCase {
|
||||
fail("Unexpected Exception: " + pe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For use when coercion is happening during a setValue(). The expectedValue should be
|
||||
* the coerced form of the value.
|
||||
*/
|
||||
protected void setValue(String expression, Object value, Object expectedValue) {
|
||||
try {
|
||||
Expression e = parser.parseExpression(expression);
|
||||
if (e == null) {
|
||||
fail("Parser returned null for expression");
|
||||
}
|
||||
if (DEBUG) {
|
||||
SpelUtilities.printAbstractSyntaxTree(System.out, e);
|
||||
}
|
||||
StandardEvaluationContext lContext = TestScenarioCreator.getTestEvaluationContext();
|
||||
assertTrue("Expression is not writeable but should be", e.isWritable(lContext));
|
||||
e.setValue(lContext, value);
|
||||
assertEquals("Retrieved value was not equal to set value", expectedValue, e.getValue(lContext));
|
||||
} catch (EvaluationException ee) {
|
||||
ee.printStackTrace();
|
||||
fail("Unexpected Exception: " + ee.getMessage());
|
||||
} catch (ParseException pe) {
|
||||
pe.printStackTrace();
|
||||
fail("Unexpected Exception: " + pe.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ public class Inventor {
|
||||
private List<PlaceOfBirth> placesLivedList = new ArrayList<PlaceOfBirth>();
|
||||
public ArrayContainer arrayContainer;
|
||||
public boolean publicBoolean;
|
||||
private boolean accessedThroughGetSet;
|
||||
public List<Integer> listOfInteger = new ArrayList<Integer>();
|
||||
|
||||
public Inventor(String name, Date birthdate, String nationality) {
|
||||
this.name = name;
|
||||
@@ -110,4 +112,12 @@ public class Inventor {
|
||||
public Inventor(String... strings) {
|
||||
|
||||
}
|
||||
|
||||
public boolean getSomeProperty() {
|
||||
return accessedThroughGetSet;
|
||||
}
|
||||
|
||||
public void setSomeProperty(boolean b) {
|
||||
this.accessedThroughGetSet = b;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user