polish
This commit is contained in:
parent
ea9df82d2a
commit
7f6fc4e82e
|
|
@ -68,7 +68,7 @@ public class ConversionExecutionException extends ConversionException {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the actual value we tried to convert, an instance of {@link #getSourceClass()}.
|
||||
* Returns the actual value we tried to convert, an instance of {@link #getSourceType()}.
|
||||
*/
|
||||
public Object getValue() {
|
||||
return value;
|
||||
|
|
@ -77,14 +77,14 @@ public class ConversionExecutionException extends ConversionException {
|
|||
/**
|
||||
* Returns the source type we tried to convert the value from.
|
||||
*/
|
||||
public TypeDescriptor getSourceClass() {
|
||||
public TypeDescriptor getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target type we tried to convert the value to.
|
||||
*/
|
||||
public TypeDescriptor getTargetClass() {
|
||||
public TypeDescriptor getTargetType() {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ package org.springframework.core.convert;
|
|||
public interface ConversionExecutor {
|
||||
|
||||
/**
|
||||
* Convert the source to T.
|
||||
* Convert the source.
|
||||
* @param source the source to convert
|
||||
* @throws ConversionExecutionException if an exception occurs during type conversion
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package org.springframework.core.convert;
|
|||
/**
|
||||
* Thrown when a conversion executor could not be found in a conversion service.
|
||||
*
|
||||
* @see ConversionService#getConversionExecutor(Class, Class)
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class ConversionExecutorNotFoundException extends ConversionException {
|
||||
|
|
@ -40,14 +39,14 @@ public class ConversionExecutorNotFoundException extends ConversionException {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the source type requested to convert from.
|
||||
* Returns the source type that was requested to convert from.
|
||||
*/
|
||||
public TypeDescriptor getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target type requested to convert to.
|
||||
* Returns the target type that was requested to convert to.
|
||||
*/
|
||||
public TypeDescriptor getTargetType() {
|
||||
return targetType;
|
||||
|
|
|
|||
|
|
@ -17,10 +17,12 @@ package org.springframework.core.convert;
|
|||
|
||||
/**
|
||||
* A service interface for type conversion. This is the entry point into the convert system. Call one of the
|
||||
* {@link #executeConversion(Object, Class) executeConversion} operations to perform a thread-safe type conversion using
|
||||
* this system. Call one of the {@link #getConversionExecutor(Class, Class) getConversionExecutor} operations to obtain
|
||||
* <i>executeConversion</i> operations to perform a thread-safe type conversion using
|
||||
* this system. Call one of the <i>getConversionExecutor</i> operations to obtain
|
||||
* a thread-safe {@link ConversionExecutor} command for later use.
|
||||
*
|
||||
* TODO - is TypeDescriptor/TypedValue needed on source?
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface ConversionService {
|
||||
|
|
@ -86,7 +88,7 @@ public interface ConversionService {
|
|||
TypeDescriptor targetType) throws ConversionExecutorNotFoundException;
|
||||
|
||||
/**
|
||||
* Get a type by its name; may be the fully-qualified class name or a registered alias.
|
||||
* Get a type by its name; may be the fully-qualified class name or a registered type alias such as 'int'.
|
||||
* @return the class, or <code>null</code> if no such name exists
|
||||
*/
|
||||
public Class<?> getType(String name);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import org.springframework.core.MethodParameter;
|
|||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Type metadata about a bindable value.
|
||||
* Type metadata about a bindable target value.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ package org.springframework.core.convert;
|
|||
* It also allows access to field-level or method-level annotations.
|
||||
* All of this context can be utilized when performing a type conversion as part of a data binding routine.
|
||||
*
|
||||
* TODO - is this needed?
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class TypedValue {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public class DefaultConversionService extends GenericConversionService {
|
|||
addAlias("long", Long.class);
|
||||
addAlias("float", Float.class);
|
||||
addAlias("double", Double.class);
|
||||
addAlias("bigInteger", BigInteger.class);
|
||||
addAlias("bigInt", BigInteger.class);
|
||||
addAlias("bigDecimal", BigDecimal.class);
|
||||
addAlias("locale", Locale.class);
|
||||
addAlias("enum", Enum.class);
|
||||
|
|
|
|||
|
|
@ -15,12 +15,10 @@
|
|||
*/
|
||||
package org.springframework.core.convert.service;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
|
|
@ -35,6 +33,7 @@ import org.springframework.core.convert.ConversionService;
|
|||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.TypedValue;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterInfo;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
import org.springframework.core.convert.converter.SuperTwoWayConverter;
|
||||
import org.springframework.util.Assert;
|
||||
|
|
@ -42,8 +41,6 @@ import org.springframework.util.Assert;
|
|||
/**
|
||||
* Base implementation of a conversion service. Initially empty, e.g. no converters are registered by default.
|
||||
*
|
||||
* TODO auto-conversion of generic collection elements
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
@ -137,9 +134,6 @@ public class GenericConversionService implements ConversionService {
|
|||
/**
|
||||
* Adapts a {@link SuperTwoWayConverter} that converts between BS and BT class hierarchies to a {@link Converter}
|
||||
* that converts between the specific BS/BT sub types S and T.
|
||||
*
|
||||
* TODO - I think this is going to force indexing on a getSourceClass/getTargetclass prop instead generic args
|
||||
*
|
||||
* @param sourceClass the source class S to convert from, which must be equal or extend BS
|
||||
* @param targetClass the target type T to convert to, which must equal or extend BT
|
||||
* @param converter the super two way converter
|
||||
|
|
@ -147,12 +141,12 @@ public class GenericConversionService implements ConversionService {
|
|||
*/
|
||||
public static <S, T> Converter<S, T> converterFor(Class<S> sourceClass, Class<T> targetClass,
|
||||
SuperTwoWayConverter converter) {
|
||||
return new SuperTwoWayConverterConverter<S, T>(converter, sourceClass, targetClass);
|
||||
return new SuperTwoWayConverterConverter(converter, sourceClass, targetClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a convenient alias for the target type. {@link #getType(String)} can then be used to lookup the type
|
||||
* given the alias.
|
||||
* Add a convenient alias for the target type. {@link #getType(String)} can then be used to lookup the type given
|
||||
* the alias.
|
||||
* @see #getType(String)
|
||||
*/
|
||||
public void addAlias(String alias, Class targetType) {
|
||||
|
|
@ -164,9 +158,9 @@ public class GenericConversionService implements ConversionService {
|
|||
public boolean canConvert(TypedValue source, TypeDescriptor targetType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object executeConversion(TypedValue source, TypeDescriptor targetType) throws ConversionExecutorNotFoundException,
|
||||
ConversionException {
|
||||
|
||||
public Object executeConversion(TypedValue source, TypeDescriptor targetType)
|
||||
throws ConversionExecutorNotFoundException, ConversionException {
|
||||
Assert.notNull(source, "The source to convert from is required");
|
||||
if (source.isNull()) {
|
||||
return null;
|
||||
|
|
@ -179,7 +173,7 @@ public class GenericConversionService implements ConversionService {
|
|||
Assert.notNull(source, "The source to convert from is required");
|
||||
if (source.isNull()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return getConversionExecutor(converterId, source.getTypeDescriptor(), targetType).execute(source.getValue());
|
||||
}
|
||||
|
||||
|
|
@ -204,14 +198,14 @@ public class GenericConversionService implements ConversionService {
|
|||
if (sourceType.isCollection()) {
|
||||
return new CollectionToArray(sourceType, targetType, this);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Object to Array not yet supported");
|
||||
throw new UnsupportedOperationException("Object to Array conversion not yet supported");
|
||||
}
|
||||
}
|
||||
if (sourceType.isCollection()) {
|
||||
if (targetType.isCollection()) {
|
||||
return new CollectionToCollection(sourceType, targetType, this);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Object to collection not yet supported");
|
||||
throw new UnsupportedOperationException("Object to Collection conversion not yet supported");
|
||||
}
|
||||
}
|
||||
Converter converter = findRegisteredConverter(sourceType, targetType);
|
||||
|
|
@ -257,18 +251,22 @@ public class GenericConversionService implements ConversionService {
|
|||
|
||||
private List getRequiredTypeInfo(Object converter) {
|
||||
List typeInfo = new ArrayList(2);
|
||||
if (converter instanceof ConverterInfo) {
|
||||
ConverterInfo info = (ConverterInfo) converter;
|
||||
typeInfo.add(info.getSourceType());
|
||||
typeInfo.add(info.getTargetType());
|
||||
return typeInfo;
|
||||
}
|
||||
Class classToIntrospect = converter.getClass();
|
||||
while (classToIntrospect != null) {
|
||||
Type[] genericInterfaces = classToIntrospect.getGenericInterfaces();
|
||||
for (Type genericInterface : genericInterfaces) {
|
||||
if (genericInterface instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedInterface = (ParameterizedType) genericInterface;
|
||||
if (Converter.class.equals(parameterizedInterface.getRawType())
|
||||
|| SuperConverter.class.isAssignableFrom((Class) parameterizedInterface.getRawType())) {
|
||||
Class s = getParameterClass(parameterizedInterface.getActualTypeArguments()[0], converter
|
||||
.getClass());
|
||||
Class t = getParameterClass(parameterizedInterface.getActualTypeArguments()[1], converter
|
||||
.getClass());
|
||||
ParameterizedType pInterface = (ParameterizedType) genericInterface;
|
||||
if (Converter.class.equals(pInterface.getRawType())
|
||||
|| SuperConverter.class.isAssignableFrom((Class) pInterface.getRawType())) {
|
||||
Class s = getParameterClass(pInterface.getActualTypeArguments()[0], converter.getClass());
|
||||
Class t = getParameterClass(pInterface.getActualTypeArguments()[1], converter.getClass());
|
||||
typeInfo.add(getParameterClass(s, converter.getClass()));
|
||||
typeInfo.add(getParameterClass(t, converter.getClass()));
|
||||
break;
|
||||
|
|
@ -315,7 +313,7 @@ public class GenericConversionService implements ConversionService {
|
|||
|
||||
private Converter findRegisteredConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
Class<?> sourceClass = sourceType.getWrapperTypeIfPrimitive();
|
||||
Class<?> targetClass = targetType.getWrapperTypeIfPrimitive();
|
||||
Class<?> targetClass = targetType.getWrapperTypeIfPrimitive();
|
||||
if (sourceClass.isInterface()) {
|
||||
LinkedList classQueue = new LinkedList();
|
||||
classQueue.addFirst(sourceClass);
|
||||
|
|
@ -366,7 +364,7 @@ public class GenericConversionService implements ConversionService {
|
|||
|
||||
private SuperConverter findRegisteredSuperConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
Class<?> sourceClass = sourceType.getWrapperTypeIfPrimitive();
|
||||
Class<?> targetClass = targetType.getWrapperTypeIfPrimitive();
|
||||
Class<?> targetClass = targetType.getWrapperTypeIfPrimitive();
|
||||
if (sourceClass.isInterface()) {
|
||||
LinkedList classQueue = new LinkedList();
|
||||
classQueue.addFirst(sourceClass);
|
||||
|
|
@ -452,7 +450,8 @@ public class GenericConversionService implements ConversionService {
|
|||
}
|
||||
|
||||
public ConversionExecutor getElementConverter(Class<?> sourceElementType, Class<?> targetElementType) {
|
||||
return getConversionExecutor(TypeDescriptor.valueOf(sourceElementType), TypeDescriptor.valueOf(targetElementType));
|
||||
return getConversionExecutor(TypeDescriptor.valueOf(sourceElementType), TypeDescriptor
|
||||
.valueOf(targetElementType));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ import org.springframework.core.convert.TypeDescriptor;
|
|||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
class StaticConversionExecutor implements ConversionExecutor {
|
||||
|
||||
private final TypeDescriptor sourceType;
|
||||
|
|
@ -35,26 +36,18 @@ class StaticConversionExecutor implements ConversionExecutor {
|
|||
this.converter = converter;
|
||||
}
|
||||
|
||||
public TypeDescriptor getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
public TypeDescriptor getTargetType() {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
public Object execute(Object source) throws ConversionExecutionException {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
if (sourceType != null && !sourceType.isInstance(source)) {
|
||||
throw new ConversionExecutionException(source, getSourceType(), getTargetType(), "Source object "
|
||||
+ source + " to convert is expected to be an instance of [" + getSourceType().getName() + "]");
|
||||
throw new ConversionExecutionException(source, sourceType, targetType, "Source object "
|
||||
+ source + " to convert is expected to be an instance of [" + sourceType.getName() + "]");
|
||||
}
|
||||
try {
|
||||
return converter.convert(source);
|
||||
} catch (Exception e) {
|
||||
throw new ConversionExecutionException(source, getSourceType(), getTargetType(), e);
|
||||
throw new ConversionExecutionException(source, sourceType, targetType, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ import org.springframework.core.convert.ConversionExecutor;
|
|||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
class StaticSuperConversionExecutor implements ConversionExecutor {
|
||||
|
||||
private final TypeDescriptor sourceType;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.springframework.core.convert.service;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterInfo;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
import org.springframework.core.convert.converter.SuperTwoWayConverter;
|
||||
|
||||
|
|
@ -9,26 +10,34 @@ import org.springframework.core.convert.converter.SuperTwoWayConverter;
|
|||
* for applying more general {@link SuperConverter} logic to a specific source/target class pair.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class SuperTwoWayConverterConverter<S, T> implements Converter<S, T> {
|
||||
class SuperTwoWayConverterConverter implements Converter, ConverterInfo {
|
||||
|
||||
private SuperTwoWayConverter superConverter;
|
||||
|
||||
private Class sourceClass;
|
||||
private Class sourceType;
|
||||
|
||||
private Class targetClass;
|
||||
private Class targetType;
|
||||
|
||||
public SuperTwoWayConverterConverter(SuperTwoWayConverter superConverter, Class sourceClass, Class targetClass) {
|
||||
public SuperTwoWayConverterConverter(SuperTwoWayConverter superConverter, Class sourceType, Class targetType) {
|
||||
this.superConverter = superConverter;
|
||||
this.sourceClass = sourceClass;
|
||||
this.targetClass = targetClass;
|
||||
this.sourceType = sourceType;
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
public Class getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
public T convert(S source) throws Exception {
|
||||
return (T) superConverter.convert(source, targetClass);
|
||||
public Class getTargetType() {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
public S convertBack(T target) throws Exception {
|
||||
return (S) superConverter.convertBack(target, sourceClass);
|
||||
public Object convert(Object source) throws Exception {
|
||||
return superConverter.convert(source, targetType);
|
||||
}
|
||||
|
||||
public Object convertBack(Object target) throws Exception {
|
||||
return superConverter.convertBack(target, sourceType);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -575,9 +575,8 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
}
|
||||
|
||||
public void testSuperTwoWayConverterConverterAdaption() {
|
||||
// this fails at the moment
|
||||
//service.addConverter(GenericConversionService.converterFor(String.class, FooEnum.class, new StringToEnum()));
|
||||
//assertEquals(FooEnum.BAR, service.executeConversion("BAR", FooEnum.class));
|
||||
service.addConverter(GenericConversionService.converterFor(String.class, FooEnum.class, new StringToEnum()));
|
||||
assertEquals(FooEnum.BAR, service.executeConversion(value("BAR"), type(FooEnum.class)));
|
||||
}
|
||||
|
||||
private TypedValue value(Object obj) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue