Skip to content

Commit dd67900

Browse files
committed
revised core conversion package for BeanWrapper/BeanFactory integration
1 parent 45a0cad commit dd67900

File tree

15 files changed

+92
-129
lines changed

15 files changed

+92
-129
lines changed

org.springframework.expression/src/main/java/org/springframework/expression/TypeConverter.java

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,23 @@
2020

2121
/**
2222
* A type converter can convert values between different types encountered
23-
* during expression evaluation.
23+
* during expression evaluation. This is an SPI for the expression parser;
24+
* see {@link org.springframework.core.convert.ConversionService} for the
25+
* primary user API to Spring's conversion facilities.
2426
*
2527
* @author Andy Clement
28+
* @author Juergen Hoeller
2629
* @since 3.0
2730
*/
2831
public interface TypeConverter {
29-
// TODO replace this stuff with Keiths spring-binding conversion code
30-
// TODO should ExpressionException be thrown for lost precision in the case of coercion?
31-
// TODO could remove the methods where the target is Class and just keep the TypeDescriptor variants
3232

3333
/**
34-
* Convert (may coerce) a value from one type to another, for example from a boolean to a string.
35-
* @param value the value to be converted
36-
* @param targetType the type that the value should be converted to if possible
37-
* @return the converted value
38-
* @throws EvaluationException if conversion is not possible
34+
* Return true if the type converter can convert the specified type to the desired target type.
35+
* @param sourceType the type to be converted from
36+
* @param targetType the type to be converted to
37+
* @return true if that conversion can be performed
3938
*/
40-
<T> T convertValue(Object value, Class<T> targetType) throws EvaluationException;
39+
boolean canConvert(Class<?> sourceType, Class<?> targetType);
4140

4241
/**
4342
* Convert (may coerce) a value from one type to another, for example from a boolean to a string.
@@ -50,20 +49,4 @@ public interface TypeConverter {
5049
*/
5150
Object convertValue(Object value, TypeDescriptor typeDescriptor) throws EvaluationException;
5251

53-
/**
54-
* Return true if the type converter can convert the specified type to the desired target type.
55-
* @param sourceType the type to be converted from
56-
* @param targetType the type to be converted to
57-
* @return true if that conversion can be performed
58-
*/
59-
boolean canConvert(Class<?> sourceType, Class<?> targetType);
60-
61-
/**
62-
* Return true if the type converter can convert the specified type to the desired target type.
63-
* @param sourceType the type to be converted from
64-
* @param typeDescriptor a type descriptor that supplies extra information about the requested result type
65-
* @return true if that conversion can be performed
66-
*/
67-
boolean canConvert(Class<?> sourceType, TypeDescriptor typeDescriptor);
68-
6952
}

org.springframework.expression/src/main/java/org/springframework/expression/common/ExpressionUtils.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.expression.common;
1818

19+
import org.springframework.core.convert.TypeDescriptor;
1920
import org.springframework.expression.EvaluationContext;
2021
import org.springframework.expression.EvaluationException;
2122
import org.springframework.util.ClassUtils;
@@ -47,7 +48,7 @@ public static <T> T convert(EvaluationContext context, Object value, Class<T> ta
4748
return (T) value;
4849
}
4950
if (context != null) {
50-
return context.getTypeConverter().convertValue(value, targetType);
51+
return (T) context.getTypeConverter().convertValue(value, TypeDescriptor.valueOf(targetType));
5152
}
5253
throw new EvaluationException("Cannot convert value '" + value + "' to type '" + targetType.getName() + "'");
5354
}

org.springframework.expression/src/main/java/org/springframework/expression/spel/SpelExpression.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2004-2008 the original author or authors.
2+
* Copyright 2002-2009 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
1617
package org.springframework.expression.spel;
1718

1819
import org.springframework.core.convert.TypeDescriptor;
@@ -74,7 +75,7 @@ public <T> T getValue(EvaluationContext context, Class<T> expectedResultType) th
7475
Class<?> resultType = result.getClass();
7576
if (!expectedResultType.isAssignableFrom(resultType)) {
7677
// Attempt conversion to the requested type, may throw an exception
77-
result = context.getTypeConverter().convertValue(result, expectedResultType);
78+
result = context.getTypeConverter().convertValue(result, TypeDescriptor.valueOf(expectedResultType));
7879
}
7980
}
8081
return (T) result;
@@ -98,8 +99,7 @@ public TypeDescriptor getValueTypeDescriptor() throws EvaluationException {
9899
public TypeDescriptor getValueTypeDescriptor(EvaluationContext context) throws EvaluationException {
99100
Assert.notNull(context, "The EvaluationContext is required");
100101
ExpressionState eState = new ExpressionState(context, configuration);
101-
TypeDescriptor typeDescriptor = ast.getValueInternal(eState).getTypeDescriptor();
102-
return typeDescriptor;
102+
return ast.getValueInternal(eState).getTypeDescriptor();
103103
}
104104

105105
public String getExpressionString() {

org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/CommonTypeDescriptors.java

Lines changed: 0 additions & 37 deletions
This file was deleted.

org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public TypedValue getValueInternal(ExpressionState state) throws EvaluationExcep
5555
if (targetObject instanceof Map && (children[0] instanceof PropertyOrFieldReference)) {
5656
PropertyOrFieldReference reference = (PropertyOrFieldReference)children[0];
5757
index = reference.getName();
58-
indexValue = new TypedValue(index,CommonTypeDescriptors.STRING_TYPE_DESCRIPTOR);
58+
indexValue = new TypedValue(index, TypeDescriptor.valueOf(String.class));
5959
} else {
6060
// In case the map key is unqualified, we want it evaluated against the root object so
6161
// temporarily push that on whilst evaluating the key
@@ -85,7 +85,7 @@ public TypedValue getValueInternal(ExpressionState state) throws EvaluationExcep
8585
}
8686
Object o = ((Map<?, ?>) targetObject).get(possiblyConvertedKey);
8787
TypeDescriptor resultDescriptor = targetObjectTypeDescriptor.isMapEntryTypeKnown()?
88-
TypeDescriptor.valueOf(targetObjectTypeDescriptor.getMapValueType()):CommonTypeDescriptors.OBJECT_TYPE_DESCRIPTOR;
88+
TypeDescriptor.valueOf(targetObjectTypeDescriptor.getMapValueType()): TypeDescriptor.valueOf(Object.class);
8989
return new TypedValue(o,resultDescriptor);
9090
}
9191

org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,28 @@
2424
import org.springframework.expression.spel.SpelMessage;
2525
import org.springframework.expression.spel.SpelNode;
2626
import org.springframework.expression.spel.support.StandardEvaluationContext;
27+
import org.springframework.core.convert.TypeDescriptor;
2728

2829
/**
2930
* The common supertype of all AST nodes in a parsed Spring Expression Language format expression.
3031
*
3132
* @author Andy Clement
3233
* @since 3.0
3334
*/
34-
public abstract class SpelNodeImpl implements SpelNode, CommonTypeDescriptors {
35-
35+
public abstract class SpelNodeImpl implements SpelNode {
36+
37+
static TypeDescriptor BOOLEAN_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Boolean.class);
38+
static TypeDescriptor INTEGER_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Integer.class);
39+
static TypeDescriptor CHARACTER_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Character.class);
40+
static TypeDescriptor LONG_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Long.class);
41+
static TypeDescriptor SHORT_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Short.class);
42+
static TypeDescriptor BYTE_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Byte.class);
43+
static TypeDescriptor FLOAT_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Float.class);
44+
static TypeDescriptor DOUBLE_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Double.class);
45+
static TypeDescriptor STRING_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(String.class);
46+
static TypeDescriptor CLASS_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Class.class);
47+
static TypeDescriptor OBJECT_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Object.class);
48+
3649
private static SpelNodeImpl[] NO_CHILDREN = new SpelNodeImpl[0];
3750

3851
protected int pos; // start = top 16bits, end = bottom 16bits

org.springframework.expression/src/main/java/org/springframework/expression/spel/support/BooleanTypedValue.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
1617
package org.springframework.expression.spel.support;
1718

1819
import org.springframework.expression.TypedValue;
19-
import org.springframework.expression.spel.ast.CommonTypeDescriptors;
20+
import org.springframework.core.convert.TypeDescriptor;
2021

2122
/**
2223
* @author Andy Clement
@@ -28,7 +29,7 @@ public class BooleanTypedValue extends TypedValue {
2829
public static final BooleanTypedValue False = new BooleanTypedValue(false);
2930

3031
private BooleanTypedValue(boolean b) {
31-
super(b,CommonTypeDescriptors.BOOLEAN_TYPE_DESCRIPTOR);
32+
super(b, TypeDescriptor.valueOf(Boolean.class));
3233
}
3334

3435
public static BooleanTypedValue forValue(boolean b) {

org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectionHelper.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.ArrayList;
2121
import java.util.List;
2222

23+
import org.springframework.core.convert.TypeDescriptor;
2324
import org.springframework.expression.EvaluationException;
2425
import org.springframework.expression.TypeConverter;
2526
import org.springframework.expression.spel.SpelEvaluationException;
@@ -228,7 +229,7 @@ public static void convertArguments(Class[] requiredParameterTypes, boolean isVa
228229
} else {
229230
targetType = requiredParameterTypes[argPosition];
230231
}
231-
arguments[argPosition] = converter.convertValue(arguments[argPosition], targetType);
232+
arguments[argPosition] = converter.convertValue(arguments[argPosition], TypeDescriptor.valueOf(targetType));
232233
}
233234
}
234235

@@ -267,7 +268,7 @@ public static void convertAllArguments(Class[] parameterTypes, boolean isVarargs
267268
if (converter == null) {
268269
throw new SpelEvaluationException(SpelMessage.TYPE_CONVERSION_ERROR, arguments[i].getClass().getName(),targetType);
269270
}
270-
arguments[i] = converter.convertValue(arguments[i], targetType);
271+
arguments[i] = converter.convertValue(arguments[i], TypeDescriptor.valueOf(targetType));
271272
}
272273
} catch (EvaluationException ex) {
273274
// allows for another type converter throwing a different kind of EvaluationException

org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveConstructorExecutor.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.expression.ConstructorExecutor;
2424
import org.springframework.expression.EvaluationContext;
2525
import org.springframework.expression.TypedValue;
26+
import org.springframework.util.ReflectionUtils;
2627

2728
/**
2829
* A simple ConstructorExecutor implementation that runs a constructor using reflective invocation.
@@ -32,33 +33,35 @@
3233
*/
3334
class ReflectiveConstructorExecutor implements ConstructorExecutor {
3435

35-
private final Constructor<?> c;
36+
private final Constructor<?> ctor;
3637

3738
// When the constructor was found, we will have determined if arguments need to be converted for it
3839
// to be invoked. Conversion won't be cheap so let's only do it if necessary.
3940
private final int[] argsRequiringConversion;
4041

4142

42-
public ReflectiveConstructorExecutor(Constructor<?> constructor, int[] argsRequiringConversion) {
43-
c = constructor;
43+
public ReflectiveConstructorExecutor(Constructor<?> ctor, int[] argsRequiringConversion) {
44+
this.ctor = ctor;
4445
this.argsRequiringConversion = argsRequiringConversion;
4546
}
4647

4748
public TypedValue execute(EvaluationContext context, Object... arguments) throws AccessException {
4849
try {
4950
if (argsRequiringConversion != null && arguments != null) {
50-
ReflectionHelper.convertArguments(c.getParameterTypes(), c.isVarArgs(),
51-
context.getTypeConverter(), argsRequiringConversion, arguments);
51+
ReflectionHelper.convertArguments(this.ctor.getParameterTypes(),
52+
this.ctor.isVarArgs(), context.getTypeConverter(),
53+
this.argsRequiringConversion, arguments);
5254
}
53-
if (c.isVarArgs()) {
54-
arguments = ReflectionHelper.setupArgumentsForVarargsInvocation(c.getParameterTypes(), arguments);
55+
if (this.ctor.isVarArgs()) {
56+
arguments = ReflectionHelper.setupArgumentsForVarargsInvocation(
57+
this.ctor.getParameterTypes(), arguments);
5558
}
56-
if (!c.isAccessible()) {
57-
c.setAccessible(true);
58-
}
59-
return new TypedValue(c.newInstance(arguments),TypeDescriptor.valueOf(c.getClass()));
60-
} catch (Exception ex) {
61-
throw new AccessException("Problem invoking constructor: " + c, ex);
59+
ReflectionUtils.makeAccessible(this.ctor);
60+
return new TypedValue(this.ctor.newInstance(arguments),
61+
TypeDescriptor.valueOf(this.ctor.getClass()));
62+
}
63+
catch (Exception ex) {
64+
throw new AccessException("Problem invoking constructor: " + this.ctor, ex);
6265
}
6366
}
6467

org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardTypeConverter.java

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,58 +16,55 @@
1616

1717
package org.springframework.expression.spel.support;
1818

19-
import org.springframework.core.convert.ConvertException;
19+
import org.springframework.core.convert.ConversionException;
20+
import org.springframework.core.convert.ConversionService;
2021
import org.springframework.core.convert.ConverterNotFoundException;
2122
import org.springframework.core.convert.TypeDescriptor;
22-
import org.springframework.core.convert.support.DefaultTypeConverter;
23+
import org.springframework.core.convert.support.DefaultConversionService;
2324
import org.springframework.expression.EvaluationException;
2425
import org.springframework.expression.TypeConverter;
2526
import org.springframework.expression.spel.SpelEvaluationException;
2627
import org.springframework.expression.spel.SpelMessage;
2728
import org.springframework.util.Assert;
2829

2930
/**
31+
* Default implementation of the {@link TypeConverter} interface,
32+
* delegating to a core Spring {@link ConversionService}.
33+
*
3034
* @author Juergen Hoeller
3135
* @author Andy Clement
3236
* @since 3.0
37+
* @see org.springframework.core.convert.ConversionService
3338
*/
3439
public class StandardTypeConverter implements TypeConverter {
3540

36-
private org.springframework.core.convert.TypeConverter typeConverter;
37-
41+
private final ConversionService typeConverter;
42+
43+
3844
public StandardTypeConverter() {
39-
this.typeConverter = new DefaultTypeConverter();
45+
this.typeConverter = new DefaultConversionService();
4046
}
4147

42-
public StandardTypeConverter(org.springframework.core.convert.TypeConverter typeConverter) {
43-
Assert.notNull(typeConverter, "TypeConverter must not be null");
48+
public StandardTypeConverter(ConversionService typeConverter) {
49+
Assert.notNull(typeConverter, "ConversionService must not be null");
4450
this.typeConverter = typeConverter;
4551
}
4652

47-
@SuppressWarnings("unchecked")
48-
public <T> T convertValue(Object value, Class<T> targetType) throws EvaluationException {
49-
return (T) convertValue(value, TypeDescriptor.valueOf(targetType));
53+
54+
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
55+
return this.typeConverter.canConvert(sourceType, targetType);
5056
}
5157

52-
@SuppressWarnings("unchecked")
5358
public Object convertValue(Object value, TypeDescriptor typeDescriptor) throws EvaluationException {
5459
try {
5560
return this.typeConverter.convert(value, typeDescriptor);
5661
}
5762
catch (ConverterNotFoundException cenfe) {
5863
throw new SpelEvaluationException(cenfe, SpelMessage.TYPE_CONVERSION_ERROR, value.getClass(), typeDescriptor.asString());
5964
}
60-
catch (ConvertException ce) {
65+
catch (ConversionException ce) {
6166
throw new SpelEvaluationException(ce, SpelMessage.TYPE_CONVERSION_ERROR, value.getClass(), typeDescriptor.asString());
6267
}
6368
}
6469

65-
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
66-
return canConvert(sourceType, TypeDescriptor.valueOf(targetType));
67-
}
68-
69-
public boolean canConvert(Class<?> sourceType, TypeDescriptor targetType) {
70-
return this.typeConverter.canConvert(sourceType, targetType);
71-
}
72-
7370
}

0 commit comments

Comments
 (0)