type descriptor initial commit
This commit is contained in:
parent
c057638bd0
commit
ae4f80cf60
|
|
@ -32,39 +32,39 @@ public class ConversionExecutionException extends ConversionException {
|
|||
/**
|
||||
* The source type we tried to convert the value from.
|
||||
*/
|
||||
private Class<?> sourceClass;
|
||||
private TypeDescriptor sourceType;
|
||||
|
||||
/**
|
||||
* The target type we tried to convert the value to.
|
||||
*/
|
||||
private Class<?> targetClass;
|
||||
private TypeDescriptor targetType;
|
||||
|
||||
/**
|
||||
* Creates a new conversion exception.
|
||||
* @param value the value we tried to convert
|
||||
* @param sourceClass the value's original type
|
||||
* @param targetClass the value's target type
|
||||
* @param sourceType the value's original type
|
||||
* @param targetType the value's target type
|
||||
* @param cause the cause of the conversion failure
|
||||
*/
|
||||
public ConversionExecutionException(Object value, Class<?> sourceClass, Class<?> targetClass, Throwable cause) {
|
||||
super(defaultMessage(value, sourceClass, targetClass, cause), cause);
|
||||
public ConversionExecutionException(Object value, TypeDescriptor sourceType, TypeDescriptor targetType, Throwable cause) {
|
||||
super(defaultMessage(value, sourceType, targetType, cause), cause);
|
||||
this.value = value;
|
||||
this.sourceClass = sourceClass;
|
||||
this.targetClass = targetClass;
|
||||
this.sourceType = sourceType;
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new conversion exception.
|
||||
* @param value the value we tried to convert
|
||||
* @param sourceClass the value's original type
|
||||
* @param targetClass the value's target type
|
||||
* @param sourceType the value's original type
|
||||
* @param targetType the value's target type
|
||||
* @param message a descriptive message of what went wrong.
|
||||
*/
|
||||
public ConversionExecutionException(Object value, Class<?> sourceClass, Class<?> targetClass, String message) {
|
||||
public ConversionExecutionException(Object value, TypeDescriptor sourceType, TypeDescriptor targetType, String message) {
|
||||
super(message);
|
||||
this.value = value;
|
||||
this.sourceClass = sourceClass;
|
||||
this.targetClass = targetClass;
|
||||
this.sourceType = sourceType;
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -77,20 +77,20 @@ public class ConversionExecutionException extends ConversionException {
|
|||
/**
|
||||
* Returns the source type we tried to convert the value from.
|
||||
*/
|
||||
public Class<?> getSourceClass() {
|
||||
return sourceClass;
|
||||
public TypeDescriptor getSourceClass() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target type we tried to convert the value to.
|
||||
*/
|
||||
public Class<?> getTargetClass() {
|
||||
return targetClass;
|
||||
public TypeDescriptor getTargetClass() {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
private static String defaultMessage(Object value, Class<?> sourceClass, Class<?> targetClass, Throwable cause) {
|
||||
return "Unable to convert value " + StylerUtils.style(value) + " from type [" + sourceClass.getName()
|
||||
+ "] to type [" + targetClass.getName() + "]; reason = '" + cause.getMessage() + "'";
|
||||
private static String defaultMessage(Object value, TypeDescriptor sourceType, TypeDescriptor targetType, Throwable cause) {
|
||||
return "Unable to convert value " + StylerUtils.style(value) + " from type [" + sourceType.getName()
|
||||
+ "] to type [" + targetType.getName() + "]; reason = '" + cause.getMessage() + "'";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -22,23 +22,13 @@ package org.springframework.core.convert;
|
|||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface ConversionExecutor<S, T> {
|
||||
|
||||
/**
|
||||
* The type this executor converts from.
|
||||
*/
|
||||
public Class<S> getSourceClass();
|
||||
|
||||
/**
|
||||
* The type this executor converts to.
|
||||
s */
|
||||
public Class<T> getTargetClass();
|
||||
public interface ConversionExecutor {
|
||||
|
||||
/**
|
||||
* Convert the source to T.
|
||||
* @param source the source to convert
|
||||
* @throws ConversionExecutionException if an exception occurs during type conversion
|
||||
*/
|
||||
public T execute(S source) throws ConversionExecutionException;
|
||||
public Object execute(Object source) throws ConversionExecutionException;
|
||||
|
||||
}
|
||||
|
|
@ -23,33 +23,33 @@ package org.springframework.core.convert;
|
|||
*/
|
||||
public class ConversionExecutorNotFoundException extends ConversionException {
|
||||
|
||||
private Class<?> sourceClass;
|
||||
private TypeDescriptor sourceType;
|
||||
|
||||
private Class<?> targetClass;
|
||||
private TypeDescriptor targetType;
|
||||
|
||||
/**
|
||||
* Creates a new conversion executor not found exception.
|
||||
* @param sourceClass the source type requested to convert from
|
||||
* @param targetClass the target type requested to convert to
|
||||
* @param sourceType the source type requested to convert from
|
||||
* @param targetType the target type requested to convert to
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
public ConversionExecutorNotFoundException(Class<?> sourceClass, Class<?> targetClass, String message) {
|
||||
public ConversionExecutorNotFoundException(TypeDescriptor sourceType, TypeDescriptor targetType, String message) {
|
||||
super(message);
|
||||
this.sourceClass = sourceClass;
|
||||
this.targetClass = targetClass;
|
||||
this.sourceType = sourceType;
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the source type requested to convert from.
|
||||
*/
|
||||
public Class<?> getSourceClass() {
|
||||
return sourceClass;
|
||||
public TypeDescriptor getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target type requested to convert to.
|
||||
*/
|
||||
public Class<?> getTargetClass() {
|
||||
return targetClass;
|
||||
public TypeDescriptor getTargetType() {
|
||||
return targetType;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,61 +26,69 @@ package org.springframework.core.convert;
|
|||
public interface ConversionService {
|
||||
|
||||
/**
|
||||
* Convert the source to target class T.
|
||||
* Returns true if the source can be converted to targetType.
|
||||
* @param source the source to convert from (may be null)
|
||||
* @param targetClass the target class to convert to
|
||||
* @return the converted object, an instance of the <code>targetClass</code>, or <code>null</code> if a null source
|
||||
* @param targetType the target type to convert to
|
||||
* @return true if a conversion can be performed, false if not
|
||||
*/
|
||||
public boolean canConvert(TypedValue source, TypeDescriptor targetType);
|
||||
|
||||
/**
|
||||
* Convert the source to target type T.
|
||||
* @param source the source to convert from (may be null)
|
||||
* @param targetType the target type to convert to
|
||||
* @return the converted object, an instance of the <code>targetType</code>, or <code>null</code> if a null source
|
||||
* was provided
|
||||
* @throws ConversionExecutorNotFoundException if no suitable conversion executor could be found to convert the
|
||||
* source to an instance of targetClass
|
||||
* source to an instance of targetType
|
||||
* @throws ConversionException if an exception occurred during the conversion process
|
||||
*/
|
||||
public <T> T executeConversion(Object source, Class<T> targetClass) throws ConversionExecutorNotFoundException,
|
||||
public Object executeConversion(TypedValue source, TypeDescriptor targetType) throws ConversionExecutorNotFoundException,
|
||||
ConversionException;
|
||||
|
||||
/**
|
||||
* Convert the source to target class T with a custom converter.
|
||||
* Convert the source to target type T with a custom converter.
|
||||
* @param converterId the id of the custom converter, which must be registered with this conversion service and
|
||||
* capable of converting to the targetClass
|
||||
* capable of converting to the targetType
|
||||
* @param source the source to convert from (may be null)
|
||||
* @param targetClass the target class to convert to
|
||||
* @return the converted object, an instance of the <code>targetClass</code>, or <code>null</code> if a null source
|
||||
* @param targetType the target type to convert to
|
||||
* @return the converted object, an instance of the <code>targetType</code>, or <code>null</code> if a null source
|
||||
* was provided
|
||||
* @throws ConversionExecutorNotFoundException if no suitable conversion executor could be found to convert the
|
||||
* source to an instance of targetClass
|
||||
* source to an instance of targetType
|
||||
* @throws ConversionException if an exception occurred during the conversion process
|
||||
*/
|
||||
public <T> T executeConversion(String converterId, Object source, Class<T> targetClass)
|
||||
public Object executeConversion(String converterId, TypedValue source, TypeDescriptor targetType)
|
||||
throws ConversionExecutorNotFoundException, ConversionException;
|
||||
|
||||
/**
|
||||
* Get a ConversionExecutor that converts objects from S to T.
|
||||
* The returned ConversionExecutor is thread-safe and may safely be cached for later use by client code.
|
||||
* @param sourceClass the source class to convert from (required)
|
||||
* @param targetClass the target class to convert to (required)
|
||||
* @param sourceType the source type to convert from (required)
|
||||
* @param targetType the target type to convert to (required)
|
||||
* @return the executor that can execute instance type conversion, never null
|
||||
* @throws ConversionExecutorNotFoundException when no suitable conversion executor could be found
|
||||
*/
|
||||
public <S, T> ConversionExecutor<S, T> getConversionExecutor(Class<S> sourceClass, Class<T> targetClass)
|
||||
public ConversionExecutor getConversionExecutor(TypeDescriptor sourceType, TypeDescriptor targetType)
|
||||
throws ConversionExecutorNotFoundException;
|
||||
|
||||
/**
|
||||
* Get a ConversionExecutor that that converts objects from S to T with a custom converter.
|
||||
* The returned ConversionExecutor is thread-safe and may safely be cached for use in client code.
|
||||
* @param converterId the id of the custom converter, which must be registered with this conversion service and
|
||||
* capable of converting from sourceClass to targetClass (required)
|
||||
* @param sourceClass the source class to convert from (required)
|
||||
* @param targetClass the target class to convert to (required)
|
||||
* capable of converting from sourceType to targetType (required)
|
||||
* @param sourceType the source type to convert from (required)
|
||||
* @param targetType the target type to convert to (required)
|
||||
* @return the executor that can execute instance type conversion, never null
|
||||
* @throws ConversionExecutorNotFoundException when no suitable conversion executor could be found
|
||||
*/
|
||||
public <S, T> ConversionExecutor<S, T> getConversionExecutor(String converterId, Class<S> sourceClass,
|
||||
Class<T> targetClass) throws ConversionExecutorNotFoundException;
|
||||
public ConversionExecutor getConversionExecutor(String converterId, TypeDescriptor sourceType,
|
||||
TypeDescriptor targetType) throws ConversionExecutorNotFoundException;
|
||||
|
||||
/**
|
||||
* Get a class by its alias.
|
||||
* @return the class, or <code>null</code> if no such alias exists
|
||||
* Get a type by its name; may be the fully-qualified class name or a registered alias.
|
||||
* @return the class, or <code>null</code> if no such name exists
|
||||
*/
|
||||
public Class<?> getClassForAlias(String alias);
|
||||
public Class<?> getType(String name);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
package org.springframework.core.convert;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Metadata about a retrieved value or value type.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class TypeDescriptor {
|
||||
|
||||
private MethodParameter methodParameter;
|
||||
|
||||
private Field field;
|
||||
|
||||
private Annotation[] cachedFieldAnnotations;
|
||||
|
||||
private Class<?> type;
|
||||
|
||||
public TypeDescriptor(Class<?> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new descriptor for a method or constructor parameter.
|
||||
*
|
||||
* @param methodParameter the MethodParameter to wrap
|
||||
*/
|
||||
public TypeDescriptor(MethodParameter methodParameter) {
|
||||
Assert.notNull(methodParameter, "MethodParameter must not be null");
|
||||
this.methodParameter = methodParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new descriptor for a field. Considers the dependency as 'eager'.
|
||||
*
|
||||
* @param field the field to wrap
|
||||
*/
|
||||
public TypeDescriptor(Field field) {
|
||||
Assert.notNull(field, "Field must not be null");
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the declared (non-generic) type of the wrapped parameter/field.
|
||||
*
|
||||
* @return the declared type (never <code>null</code>)
|
||||
*/
|
||||
public Class<?> getType() {
|
||||
if (type != null) {
|
||||
return type;
|
||||
} else if (field != null) {
|
||||
return field.getType();
|
||||
} else {
|
||||
return methodParameter.getParameterType();
|
||||
}
|
||||
}
|
||||
|
||||
public Class<?> getWrapperTypeIfPrimitive() {
|
||||
Class<?> type = getType();
|
||||
if (type.isPrimitive()) {
|
||||
if (type.equals(int.class)) {
|
||||
return Integer.class;
|
||||
} else if (type.equals(short.class)) {
|
||||
return Short.class;
|
||||
} else if (type.equals(long.class)) {
|
||||
return Long.class;
|
||||
} else if (type.equals(float.class)) {
|
||||
return Float.class;
|
||||
} else if (type.equals(double.class)) {
|
||||
return Double.class;
|
||||
} else if (type.equals(byte.class)) {
|
||||
return Byte.class;
|
||||
} else if (type.equals(boolean.class)) {
|
||||
return Boolean.class;
|
||||
} else if (type.equals(char.class)) {
|
||||
return Character.class;
|
||||
} else {
|
||||
throw new IllegalStateException("Should never happen - primitive type is not a primitive?");
|
||||
}
|
||||
} else {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return getType().getName();
|
||||
}
|
||||
|
||||
public boolean isArray() {
|
||||
return getType().isArray();
|
||||
}
|
||||
|
||||
public Class<?> getElementType() {
|
||||
return isArray() ? getArrayComponentType() : getCollectionElementType();
|
||||
}
|
||||
|
||||
public Class<?> getArrayComponentType() {
|
||||
return getType().getComponentType();
|
||||
}
|
||||
|
||||
public boolean isInstance(Object source) {
|
||||
return getType().isInstance(source);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the generic element type of the wrapped Collection parameter/field, if any.
|
||||
*
|
||||
* @return the generic type, or <code>null</code> if none
|
||||
*/
|
||||
public Class<?> getCollectionElementType() {
|
||||
if (type != null) {
|
||||
return GenericCollectionTypeResolver.getCollectionType((Class<? extends Collection>) type);
|
||||
} else if (field != null) {
|
||||
return GenericCollectionTypeResolver.getCollectionFieldType(field);
|
||||
} else {
|
||||
return GenericCollectionTypeResolver.getCollectionParameterType(methodParameter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the generic key type of the wrapped Map parameter/field, if any.
|
||||
*
|
||||
* @return the generic type, or <code>null</code> if none
|
||||
*/
|
||||
public Class<?> getMapKeyType() {
|
||||
return (field != null ? GenericCollectionTypeResolver.getMapKeyFieldType(field) : GenericCollectionTypeResolver
|
||||
.getMapKeyParameterType(methodParameter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the generic value type of the wrapped Map parameter/field, if any.
|
||||
*
|
||||
* @return the generic type, or <code>null</code> if none
|
||||
*/
|
||||
public Class<?> getMapValueType() {
|
||||
return (field != null ? GenericCollectionTypeResolver.getMapValueFieldType(field)
|
||||
: GenericCollectionTypeResolver.getMapValueParameterType(methodParameter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the annotations associated with the wrapped parameter/field, if any.
|
||||
*/
|
||||
public Annotation[] getAnnotations() {
|
||||
if (field != null) {
|
||||
if (cachedFieldAnnotations == null) {
|
||||
cachedFieldAnnotations = field.getAnnotations();
|
||||
}
|
||||
return cachedFieldAnnotations;
|
||||
} else {
|
||||
return methodParameter.getParameterAnnotations();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the wrapped MethodParameter, if any.
|
||||
* <p>
|
||||
* Note: Either MethodParameter or Field is available.
|
||||
*
|
||||
* @return the MethodParameter, or <code>null</code> if none
|
||||
*/
|
||||
public MethodParameter getMethodParameter() {
|
||||
return methodParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the wrapped Field, if any.
|
||||
* <p>
|
||||
* Note: Either MethodParameter or Field is available.
|
||||
*
|
||||
* @return the Field, or <code>null</code> if none
|
||||
*/
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public boolean isCollection() {
|
||||
return Collection.class.isAssignableFrom(getType());
|
||||
}
|
||||
|
||||
public boolean isAbstractClass() {
|
||||
return !getType().isInterface() && Modifier.isAbstract(getType().getModifiers());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package org.springframework.core.convert;
|
||||
|
||||
/**
|
||||
* A value retrieved from some location such as a field access or getter invocation.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class TypedValue {
|
||||
|
||||
private final Object value;
|
||||
|
||||
private final TypeDescriptor typeDescriptor;
|
||||
|
||||
/**
|
||||
* Creates a typed value.
|
||||
* @param value the actual value (may be null)
|
||||
* @param typeDescriptor the value type descriptor (may be null)
|
||||
*/
|
||||
public TypedValue(Object value, TypeDescriptor typeDescriptor) {
|
||||
this.value = value;
|
||||
this.typeDescriptor = typeDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual value. May be null.
|
||||
*/
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides additional type context about the value. May be null.
|
||||
*/
|
||||
public TypeDescriptor getTypeDescriptor() {
|
||||
return typeDescriptor;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.springframework.core.convert.converter;
|
||||
|
||||
public interface ConverterInfo {
|
||||
|
||||
public Class<?> getSourceType();
|
||||
|
||||
public Class<?> getTargetType();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package org.springframework.core.convert.service;
|
||||
|
||||
import org.springframework.core.convert.ConversionExecutionException;
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
abstract class AbstractCollectionConverter implements ConversionExecutor {
|
||||
|
||||
private TypeDescriptor sourceCollectionType;
|
||||
|
||||
private TypeDescriptor targetCollectionType;
|
||||
|
||||
private GenericConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
public AbstractCollectionConverter(TypeDescriptor sourceCollectionType, TypeDescriptor targetCollectionType, GenericConversionService conversionService) {
|
||||
this.sourceCollectionType = sourceCollectionType;
|
||||
this.targetCollectionType = targetCollectionType;
|
||||
this.conversionService = conversionService;
|
||||
this.elementConverter = createElementConverter();
|
||||
}
|
||||
|
||||
private ConversionExecutor createElementConverter() {
|
||||
Class<?> sourceElementType = getSourceType().getElementType();
|
||||
Class<?> targetElementType = getTargetType().getElementType();
|
||||
return (sourceElementType != null && targetElementType != null) ? conversionService.getElementConverter(sourceElementType, targetElementType) : null;
|
||||
}
|
||||
|
||||
protected TypeDescriptor getSourceType() {
|
||||
return sourceCollectionType;
|
||||
}
|
||||
|
||||
protected TypeDescriptor getTargetType() {
|
||||
return targetCollectionType;
|
||||
}
|
||||
|
||||
protected GenericConversionService getConversionService() {
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
protected ConversionExecutor getElementConverter() {
|
||||
return elementConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(Object source) throws ConversionExecutionException {
|
||||
try {
|
||||
return doExecute(source);
|
||||
} catch (Exception e) {
|
||||
throw new ConversionExecutionException(source, sourceCollectionType, targetCollectionType, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Object doExecute(Object sourceCollection) throws Exception;
|
||||
|
||||
}
|
||||
|
|
@ -17,9 +17,8 @@ package org.springframework.core.convert.service;
|
|||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
/**
|
||||
* Special one-way converter that converts from a source array to a target array. Supports type conversion of the
|
||||
|
|
@ -28,49 +27,20 @@ import org.springframework.core.convert.converter.SuperConverter;
|
|||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class ArrayToArray implements SuperConverter {
|
||||
class ArrayToArray extends AbstractCollectionConverter {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
/**
|
||||
* Creates a new array-to-array converter.
|
||||
* @param conversionService the service to use to lookup conversion executors for individual array elements
|
||||
* dynamically
|
||||
*/
|
||||
public ArrayToArray(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
public ArrayToArray(TypeDescriptor sourceArrayType, TypeDescriptor targetArrayType, GenericConversionService conversionService) {
|
||||
super(sourceArrayType, targetArrayType, conversionService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array-to-array converter.
|
||||
* @param elementConverter a specific conversion executor to use to convert elements in the source array to elements
|
||||
* in the target array.
|
||||
*/
|
||||
public ArrayToArray(ConversionExecutor elementConverter) {
|
||||
this.elementConverter = elementConverter;
|
||||
}
|
||||
|
||||
public Object convert(Object source, Class targetClass) throws Exception {
|
||||
Class sourceComponentType = source.getClass().getComponentType();
|
||||
Class targetComponentType = targetClass.getComponentType();
|
||||
int length = Array.getLength(source);
|
||||
Object targetArray = Array.newInstance(targetComponentType, length);
|
||||
ConversionExecutor converter = getElementConverter(sourceComponentType, targetComponentType);
|
||||
public Object doExecute(Object sourceArray) throws Exception {
|
||||
int length = Array.getLength(sourceArray);
|
||||
Object targetArray = Array.newInstance(getTargetType().getElementType(), length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object value = Array.get(source, i);
|
||||
Array.set(targetArray, i, converter.execute(value));
|
||||
Object value = Array.get(sourceArray, i);
|
||||
Array.set(targetArray, i, getElementConverter().execute(value));
|
||||
}
|
||||
return targetArray;
|
||||
}
|
||||
|
||||
private ConversionExecutor getElementConverter(Class sourceComponentType, Class targetComponentType) {
|
||||
if (elementConverter != null) {
|
||||
return elementConverter;
|
||||
} else {
|
||||
return conversionService.getConversionExecutor(sourceComponentType, targetComponentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,12 +18,10 @@ package org.springframework.core.convert.service;
|
|||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.SuperTwoWayConverter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
/**
|
||||
* Special converter that converts from a source array to a target collection. Supports the selection of an
|
||||
|
|
@ -38,38 +36,23 @@ import org.springframework.core.convert.converter.SuperTwoWayConverter;
|
|||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class ArrayToCollection implements SuperTwoWayConverter {
|
||||
class ArrayToCollection extends AbstractCollectionConverter {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
/**
|
||||
* Creates a new array to collection converter.
|
||||
* @param conversionService the conversion service to use to lookup the converter to apply to array elements added
|
||||
* to the target collection
|
||||
*/
|
||||
public ArrayToCollection(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
public ArrayToCollection(TypeDescriptor sourceArrayType, TypeDescriptor targetCollectionType,
|
||||
GenericConversionService conversionService) {
|
||||
super(sourceArrayType, targetCollectionType, conversionService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array to collection converter.
|
||||
* @param elementConverter A specific converter to use on array elements when adding them to the target collection
|
||||
*/
|
||||
public ArrayToCollection(ConversionExecutor elementConverter) {
|
||||
this.elementConverter = elementConverter;
|
||||
}
|
||||
|
||||
public Object convert(Object source, Class targetClass) throws Exception {
|
||||
Class implClass = CollectionConversionUtils.getImpl(targetClass);
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object doExecute(Object sourceArray) throws Exception {
|
||||
Class implClass = CollectionConversionUtils.getImpl(getTargetType().getType());
|
||||
Constructor constructor = implClass.getConstructor((Class[]) null);
|
||||
Collection collection = (Collection) constructor.newInstance((Object[]) null);
|
||||
ConversionExecutor converter = getArrayElementConverter(source, targetClass);
|
||||
int length = Array.getLength(source);
|
||||
int length = Array.getLength(sourceArray);
|
||||
ConversionExecutor converter = getElementConverter();
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object value = Array.get(source, i);
|
||||
Object value = Array.get(sourceArray, i);
|
||||
if (converter != null) {
|
||||
value = converter.execute(value);
|
||||
}
|
||||
|
|
@ -78,38 +61,4 @@ class ArrayToCollection implements SuperTwoWayConverter {
|
|||
return collection;
|
||||
}
|
||||
|
||||
public Object convertBack(Object target, Class sourceClass) throws Exception {
|
||||
Collection collection = (Collection) target;
|
||||
Class elementType = sourceClass.getComponentType();
|
||||
Object array = Array.newInstance(elementType, collection.size());
|
||||
int i = 0;
|
||||
for (Iterator it = collection.iterator(); it.hasNext(); i++) {
|
||||
Object value = it.next();
|
||||
if (value != null) {
|
||||
ConversionExecutor converter;
|
||||
if (elementConverter != null) {
|
||||
converter = elementConverter;
|
||||
} else {
|
||||
converter = conversionService.getConversionExecutor(value.getClass(), elementType);
|
||||
}
|
||||
value = converter.execute(value);
|
||||
}
|
||||
Array.set(array, i, value);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private ConversionExecutor getArrayElementConverter(Object source, Class targetClass) {
|
||||
if (elementConverter != null) {
|
||||
return elementConverter;
|
||||
} else {
|
||||
Class elementType = GenericCollectionTypeResolver.getCollectionType(targetClass);
|
||||
if (elementType != null) {
|
||||
Class componentType = source.getClass().getComponentType();
|
||||
return conversionService.getConversionExecutor(componentType, elementType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ import java.util.Iterator;
|
|||
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
/**
|
||||
* Special converter that converts from a source array to a target collection. Supports the selection of an
|
||||
|
|
@ -36,53 +36,29 @@ import org.springframework.core.convert.converter.SuperConverter;
|
|||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class CollectionToArray implements SuperConverter {
|
||||
class CollectionToArray extends AbstractCollectionConverter {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
/**
|
||||
* Creates a new array to collection converter.
|
||||
* @param conversionService the conversion service to use to lookup the converter to apply to array elements added
|
||||
* to the target collection
|
||||
*/
|
||||
public CollectionToArray(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
public CollectionToArray(TypeDescriptor sourceArrayType, TypeDescriptor targetCollectionType,
|
||||
GenericConversionService conversionService) {
|
||||
super(sourceArrayType, targetCollectionType, conversionService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array to collection converter.
|
||||
* @param elementConverter A specific converter to use on array elements when adding them to the target collection
|
||||
*/
|
||||
public CollectionToArray(ConversionExecutor elementConverter) {
|
||||
this.elementConverter = elementConverter;
|
||||
}
|
||||
|
||||
public Object convert(Object source, Class targetClass) throws Exception {
|
||||
Collection collection = (Collection) source;
|
||||
Object array = Array.newInstance(targetClass.getComponentType(), collection.size());
|
||||
@Override
|
||||
protected Object doExecute(Object source) throws Exception {
|
||||
Collection<?> collection = (Collection<?>) source;
|
||||
Class<?> targetComponentType = getTargetType().getElementType();
|
||||
Object array = Array.newInstance(targetComponentType, collection.size());
|
||||
int i = 0;
|
||||
for (Iterator it = collection.iterator(); it.hasNext(); i++) {
|
||||
ConversionExecutor converter = getElementConverter();
|
||||
for (Iterator<?> it = collection.iterator(); it.hasNext(); i++) {
|
||||
Object value = it.next();
|
||||
if (value != null) {
|
||||
ConversionExecutor converter;
|
||||
if (elementConverter != null) {
|
||||
converter = elementConverter;
|
||||
} else {
|
||||
converter = conversionService.getConversionExecutor(value.getClass(), targetClass
|
||||
.getComponentType());
|
||||
}
|
||||
value = converter.execute(value);
|
||||
if (converter == null) {
|
||||
converter = getConversionService().getElementConverter(value.getClass(), targetComponentType);
|
||||
}
|
||||
value = converter.execute(value);
|
||||
Array.set(array, i, value);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public Object convertBack(Object target) throws Exception {
|
||||
throw new UnsupportedOperationException("Should never be called");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -20,66 +20,45 @@ import java.util.Iterator;
|
|||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
/**
|
||||
* A converter that can convert from one collection type to another.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class CollectionToCollection implements SuperConverter<Collection, Collection> {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
/**
|
||||
* Creates a new collection-to-collection converter
|
||||
* @param conversionService the conversion service to use to convert collection elements to add to the target
|
||||
* collection
|
||||
*/
|
||||
public CollectionToCollection(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
class CollectionToCollection extends AbstractCollectionConverter {
|
||||
|
||||
public CollectionToCollection(TypeDescriptor sourceCollectionType, TypeDescriptor targetCollectionType,
|
||||
GenericConversionService conversionService) {
|
||||
super(sourceCollectionType, targetCollectionType, conversionService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new collection-to-collection converter
|
||||
* @param elementConverter a specific converter to use to convert collection elements added to the target collection
|
||||
*/
|
||||
public CollectionToCollection(ConversionExecutor elementConverter) {
|
||||
this.elementConverter = elementConverter;
|
||||
}
|
||||
|
||||
public Collection convert(Collection source, Class targetClass) throws Exception {
|
||||
Class implClass = CollectionConversionUtils.getImpl(targetClass);
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object doExecute(Object source) throws Exception {
|
||||
Collection sourceCollection = (Collection) source;
|
||||
Class targetCollectionType = getTargetType().getType();
|
||||
Class implClass = CollectionConversionUtils.getImpl(targetCollectionType);
|
||||
Collection targetCollection = (Collection) implClass.getConstructor((Class[]) null)
|
||||
.newInstance((Object[]) null);
|
||||
ConversionExecutor elementConverter = getElementConverter(source, targetClass);
|
||||
Collection sourceCollection = (Collection) source;
|
||||
ConversionExecutor elementConverter = getElementConverter();
|
||||
Class elementType;
|
||||
if (elementConverter == null) {
|
||||
elementType = GenericCollectionTypeResolver.getCollectionType(targetCollectionType);
|
||||
} else {
|
||||
elementType = null;
|
||||
}
|
||||
Iterator it = sourceCollection.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object value = it.next();
|
||||
if (elementConverter != null) {
|
||||
value = elementConverter.execute(value);
|
||||
if (elementConverter == null && elementType != null) {
|
||||
elementConverter = getConversionService().getElementConverter(value.getClass(), elementType);
|
||||
}
|
||||
value = elementConverter.execute(value);
|
||||
targetCollection.add(value);
|
||||
}
|
||||
return targetCollection;
|
||||
}
|
||||
|
||||
private ConversionExecutor getElementConverter(Object source, Class targetClass) {
|
||||
if (elementConverter != null) {
|
||||
return elementConverter;
|
||||
} else {
|
||||
Class elementType = GenericCollectionTypeResolver.getCollectionType(targetClass);
|
||||
if (elementType != null) {
|
||||
Class componentType = source.getClass().getComponentType();
|
||||
return conversionService.getConversionExecutor(componentType, elementType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -67,9 +67,6 @@ public class DefaultConversionService extends GenericConversionService {
|
|||
addConverter(new StringToLocale());
|
||||
addConverter(new StringToEnum());
|
||||
addConverter(new NumberToNumber());
|
||||
// TODO probably don't allow these to be customized, or at least make public
|
||||
addConverter(new ObjectToCollection(this));
|
||||
addConverter(new CollectionToCollection(this));
|
||||
}
|
||||
|
||||
protected void addDefaultAliases() {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ import org.springframework.core.convert.ConversionException;
|
|||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionExecutorNotFoundException;
|
||||
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.SuperConverter;
|
||||
import org.springframework.core.convert.converter.SuperTwoWayConverter;
|
||||
|
|
@ -149,9 +151,9 @@ public class GenericConversionService implements ConversionService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a convenient alias for the target type. {@link #getClassForAlias(String)} can then be used to lookup the type
|
||||
* Add a convenient alias for the target type. {@link #getType(String)} can then be used to lookup the type
|
||||
* given the alias.
|
||||
* @see #getClassForAlias(String)
|
||||
* @see #getType(String)
|
||||
*/
|
||||
public void addAlias(String alias, Class targetType) {
|
||||
aliasMap.put(alias, targetType);
|
||||
|
|
@ -159,225 +161,85 @@ public class GenericConversionService implements ConversionService {
|
|||
|
||||
// implementing ConversionService
|
||||
|
||||
public Object executeConversion(Object source, Class targetClass) throws ConversionExecutorNotFoundException,
|
||||
public boolean canConvert(TypedValue source, TypeDescriptor targetType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object executeConversion(TypedValue source, TypeDescriptor targetType) throws ConversionExecutorNotFoundException,
|
||||
ConversionException {
|
||||
return getConversionExecutor(source.getClass(), targetClass).execute(source);
|
||||
return getConversionExecutor(source.getTypeDescriptor(), targetType).execute(source.getValue());
|
||||
}
|
||||
|
||||
public Object executeConversion(String converterId, Object source, Class targetClass)
|
||||
public Object executeConversion(String converterId, TypedValue source, TypeDescriptor targetType)
|
||||
throws ConversionExecutorNotFoundException, ConversionException {
|
||||
return getConversionExecutor(converterId, source.getClass(), targetClass).execute(source);
|
||||
return getConversionExecutor(converterId, source.getTypeDescriptor(), targetType).execute(source.getValue());
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(Class sourceClass, Class targetClass)
|
||||
public ConversionExecutor getConversionExecutor(TypeDescriptor sourceType, TypeDescriptor targetType)
|
||||
throws ConversionExecutorNotFoundException {
|
||||
Assert.notNull(sourceClass, "The source class to convert from is required");
|
||||
Assert.notNull(targetClass, "The target class to convert to is required");
|
||||
if (targetClass.isAssignableFrom(sourceClass)) {
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, new NoOpConverter());
|
||||
}
|
||||
sourceClass = convertToWrapperClassIfNecessary(sourceClass);
|
||||
targetClass = convertToWrapperClassIfNecessary(targetClass);
|
||||
Assert.notNull(sourceType, "The sourceType to convert from is required");
|
||||
Assert.notNull(targetType, "The targetType to convert to is required");
|
||||
// special handling for arrays since they are not indexable classes
|
||||
if (sourceClass.isArray()) {
|
||||
if (targetClass.isArray()) {
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new ArrayToArray(this));
|
||||
} else if (Collection.class.isAssignableFrom(targetClass)) {
|
||||
if (!targetClass.isInterface() && Modifier.isAbstract(targetClass.getModifiers())) {
|
||||
throw new IllegalArgumentException("Conversion target class [" + targetClass.getName()
|
||||
if (sourceType.isArray()) {
|
||||
if (targetType.isArray()) {
|
||||
return new ArrayToArray(sourceType, targetType, this);
|
||||
} else if (targetType.isCollection()) {
|
||||
if (targetType.isAbstractClass()) {
|
||||
throw new IllegalArgumentException("Conversion target class [" + targetType.getName()
|
||||
+ "] is invalid; cannot convert to abstract collection types--"
|
||||
+ "request an interface or concrete implementation instead");
|
||||
}
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new ArrayToCollection(this));
|
||||
return new ArrayToCollection(sourceType, targetType, this);
|
||||
}
|
||||
}
|
||||
if (targetClass.isArray()) {
|
||||
if (Collection.class.isAssignableFrom(sourceClass)) {
|
||||
SuperConverter collectionToArray = new ReverseSuperConverter(new ArrayToCollection(this));
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, collectionToArray);
|
||||
if (targetType.isArray()) {
|
||||
if (sourceType.isCollection()) {
|
||||
return new CollectionToArray(sourceType, targetType, this);
|
||||
} else {
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new ObjectToArray(this));
|
||||
throw new UnsupportedOperationException("Object to Array 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");
|
||||
}
|
||||
}
|
||||
Class<?> sourceClass = sourceType.getWrapperTypeIfPrimitive();
|
||||
Class<?> targetClass = targetType.getWrapperTypeIfPrimitive();
|
||||
Converter converter = findRegisteredConverter(sourceClass, targetClass);
|
||||
if (converter != null) {
|
||||
// we found a converter
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, converter);
|
||||
return new StaticConversionExecutor(sourceType, targetType, converter);
|
||||
} else {
|
||||
SuperConverter superConverter = findRegisteredSuperConverter(sourceClass, targetClass);
|
||||
if (superConverter != null) {
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, superConverter);
|
||||
return new StaticSuperConversionExecutor(sourceType, targetType, superConverter);
|
||||
}
|
||||
if (parent != null) {
|
||||
// try the parent
|
||||
return parent.getConversionExecutor(sourceClass, targetClass);
|
||||
return parent.getConversionExecutor(sourceType, targetType);
|
||||
} else {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
|
||||
"No ConversionExecutor found for converting from sourceClass [" + sourceClass.getName()
|
||||
+ "] to target class [" + targetClass.getName() + "]");
|
||||
throw new ConversionExecutorNotFoundException(sourceType, targetType,
|
||||
"No ConversionExecutor found for converting from sourceType [" + sourceType.getName()
|
||||
+ "] to targetType [" + targetType.getName() + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(String id, Class sourceClass, Class targetClass)
|
||||
throws ConversionExecutorNotFoundException {
|
||||
Assert.hasText(id, "The id of the custom converter is required");
|
||||
Assert.notNull(sourceClass, "The source class to convert from is required");
|
||||
Assert.notNull(targetClass, "The target class to convert to is required");
|
||||
Converter converter = (Converter) customConverters.get(id);
|
||||
if (converter == null) {
|
||||
if (parent != null) {
|
||||
return parent.getConversionExecutor(id, sourceClass, targetClass);
|
||||
} else {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
|
||||
"No custom Converter found with id '" + id + "' for converting from sourceClass ["
|
||||
+ sourceClass.getName() + "] to targetClass [" + targetClass.getName() + "]");
|
||||
}
|
||||
}
|
||||
sourceClass = convertToWrapperClassIfNecessary(sourceClass);
|
||||
targetClass = convertToWrapperClassIfNecessary(targetClass);
|
||||
// TODO Not optimal getting this each time
|
||||
List typeInfo = getRequiredTypeInfo(converter);
|
||||
Class converterSourceClass = (Class) typeInfo.get(0);
|
||||
Class converterTargetClass = (Class) typeInfo.get(1);
|
||||
if (sourceClass.isArray()) {
|
||||
Class sourceComponentType = sourceClass.getComponentType();
|
||||
if (targetClass.isArray()) {
|
||||
Class targetComponentType = targetClass.getComponentType();
|
||||
if (converterSourceClass.isAssignableFrom(sourceComponentType)) {
|
||||
if (!converterTargetClass.equals(targetComponentType)) {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
|
||||
"Custom Converter with id '" + id
|
||||
+ "' cannot convert from an array storing elements of type ["
|
||||
+ sourceComponentType.getName() + "] to an array of storing elements of type ["
|
||||
+ targetComponentType.getName() + "]");
|
||||
}
|
||||
ConversionExecutor elementConverter = new StaticConversionExecutor(sourceComponentType,
|
||||
targetComponentType, converter);
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new ArrayToArray(
|
||||
elementConverter));
|
||||
} else if (converterTargetClass.isAssignableFrom(sourceComponentType)) {
|
||||
if (!converterSourceClass.equals(targetComponentType)) {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
|
||||
"Custom Converter with id '" + id
|
||||
+ "' cannot convert from an array storing elements of type ["
|
||||
+ sourceComponentType.getName() + "] to an array of storing elements of type ["
|
||||
+ targetComponentType.getName() + "]");
|
||||
}
|
||||
ConversionExecutor elementConverter = new StaticConversionExecutor(sourceComponentType,
|
||||
targetComponentType, new ReverseConverter(converter));
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new ArrayToArray(
|
||||
elementConverter));
|
||||
} else {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
|
||||
"Custom Converter with id '" + id
|
||||
+ "' cannot convert from an array storing elements of type ["
|
||||
+ sourceComponentType.getName() + "] to an array storing elements of type ["
|
||||
+ targetComponentType.getName() + "]");
|
||||
}
|
||||
} else if (Collection.class.isAssignableFrom(targetClass)) {
|
||||
if (!targetClass.isInterface() && Modifier.isAbstract(targetClass.getModifiers())) {
|
||||
throw new IllegalArgumentException("Conversion target class [" + targetClass.getName()
|
||||
+ "] is invalid; cannot convert to abstract collection types--"
|
||||
+ "request an interface or concrete implementation instead");
|
||||
}
|
||||
if (converterSourceClass.isAssignableFrom(sourceComponentType)) {
|
||||
// type erasure has prevented us from getting the concrete type, this is best we can do for now
|
||||
ConversionExecutor elementConverter = new StaticConversionExecutor(sourceComponentType,
|
||||
converterTargetClass, converter);
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new ArrayToCollection(
|
||||
elementConverter));
|
||||
} else if (converterTargetClass.isAssignableFrom(sourceComponentType)) {
|
||||
ConversionExecutor elementConverter = new StaticConversionExecutor(sourceComponentType,
|
||||
converterSourceClass, new ReverseConverter(converter));
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new ArrayToCollection(
|
||||
elementConverter));
|
||||
} else {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
|
||||
"Custom Converter with id '" + id
|
||||
+ "' cannot convert from array an storing elements type ["
|
||||
+ sourceComponentType.getName() + "] to a collection of type ["
|
||||
+ targetClass.getName() + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetClass.isArray()) {
|
||||
Class targetComponentType = targetClass.getComponentType();
|
||||
if (Collection.class.isAssignableFrom(sourceClass)) {
|
||||
// type erasure limits us here as well
|
||||
if (converterTargetClass.equals(targetComponentType)) {
|
||||
ConversionExecutor elementConverter = new StaticConversionExecutor(converterSourceClass,
|
||||
targetComponentType, converter);
|
||||
SuperConverter collectionToArray = new ReverseSuperConverter(
|
||||
new ArrayToCollection(elementConverter));
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, collectionToArray);
|
||||
} else if (converterSourceClass.equals(targetComponentType)) {
|
||||
ConversionExecutor elementConverter = new StaticConversionExecutor(converterTargetClass,
|
||||
targetComponentType, new ReverseConverter(converter));
|
||||
SuperConverter collectionToArray = new ReverseSuperConverter(
|
||||
new ArrayToCollection(elementConverter));
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, collectionToArray);
|
||||
} else {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
|
||||
"Custom Converter with id '" + id + "' cannot convert from collection of type ["
|
||||
+ sourceClass.getName() + "] to an array storing elements of type ["
|
||||
+ targetComponentType.getName() + "]");
|
||||
}
|
||||
} else {
|
||||
if (converterSourceClass.isAssignableFrom(sourceClass)) {
|
||||
if (!converterTargetClass.equals(targetComponentType)) {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
|
||||
"Custom Converter with id '" + id + "' cannot convert from sourceClass ["
|
||||
+ sourceClass.getName() + "] to array holding elements of type ["
|
||||
+ targetComponentType.getName() + "]");
|
||||
}
|
||||
ConversionExecutor elementConverter = new StaticConversionExecutor(sourceClass,
|
||||
targetComponentType, converter);
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new ObjectToArray(
|
||||
elementConverter));
|
||||
} else if (converterTargetClass.isAssignableFrom(sourceClass)) {
|
||||
if (!converterSourceClass.equals(targetComponentType)) {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
|
||||
"Custom Converter with id '" + id + "' cannot convert from sourceClass ["
|
||||
+ sourceClass.getName() + "] to array holding elements of type ["
|
||||
+ targetComponentType.getName() + "]");
|
||||
}
|
||||
ConversionExecutor elementConverter = new StaticConversionExecutor(sourceClass,
|
||||
targetComponentType, new ReverseConverter(converter));
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new ObjectToArray(
|
||||
elementConverter));
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO look to factor some of this duplicated code here and above out a bit
|
||||
if (converterSourceClass.isAssignableFrom(sourceClass)) {
|
||||
if (!converterTargetClass.equals(targetClass)) {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass, "Custom Converter with id '"
|
||||
+ id + "' cannot convert from sourceClass [" + sourceClass.getName() + "] to targetClass ["
|
||||
+ targetClass.getName() + "]");
|
||||
}
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, converter);
|
||||
} else if (converterTargetClass.isAssignableFrom(sourceClass)) {
|
||||
if (!converterSourceClass.equals(targetClass)) {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass, "Custom Converter with id '"
|
||||
+ id + "' cannot convert from sourceClass [" + sourceClass.getName() + "] to targetClass ["
|
||||
+ targetClass.getName() + "]");
|
||||
}
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, new ReverseConverter(converter));
|
||||
} else {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass, "Custom Converter with id '" + id
|
||||
+ "' cannot convert from sourceClass [" + sourceClass.getName() + "] to targetClass ["
|
||||
+ targetClass.getName() + "]");
|
||||
}
|
||||
public ConversionExecutor getConversionExecutor(String converterId, TypeDescriptor sourceType,
|
||||
TypeDescriptor targetType) throws ConversionExecutorNotFoundException {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
public Class getClassForAlias(String name) throws IllegalArgumentException {
|
||||
public Class getType(String name) throws IllegalArgumentException {
|
||||
Class clazz = (Class) aliasMap.get(name);
|
||||
if (clazz != null) {
|
||||
return clazz;
|
||||
} else {
|
||||
if (parent != null) {
|
||||
return parent.getClassForAlias(name);
|
||||
return parent.getType(name);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -444,32 +306,6 @@ public class GenericConversionService implements ConversionService {
|
|||
return sourceMap;
|
||||
}
|
||||
|
||||
private Class convertToWrapperClassIfNecessary(Class targetType) {
|
||||
if (targetType.isPrimitive()) {
|
||||
if (targetType.equals(int.class)) {
|
||||
return Integer.class;
|
||||
} else if (targetType.equals(short.class)) {
|
||||
return Short.class;
|
||||
} else if (targetType.equals(long.class)) {
|
||||
return Long.class;
|
||||
} else if (targetType.equals(float.class)) {
|
||||
return Float.class;
|
||||
} else if (targetType.equals(double.class)) {
|
||||
return Double.class;
|
||||
} else if (targetType.equals(byte.class)) {
|
||||
return Byte.class;
|
||||
} else if (targetType.equals(boolean.class)) {
|
||||
return Boolean.class;
|
||||
} else if (targetType.equals(char.class)) {
|
||||
return Character.class;
|
||||
} else {
|
||||
throw new IllegalStateException("Should never happen - primitive type is not a primitive?");
|
||||
}
|
||||
} else {
|
||||
return targetType;
|
||||
}
|
||||
}
|
||||
|
||||
private Converter findRegisteredConverter(Class sourceClass, Class targetClass) {
|
||||
if (sourceClass.isInterface()) {
|
||||
LinkedList classQueue = new LinkedList();
|
||||
|
|
@ -604,4 +440,8 @@ public class GenericConversionService implements ConversionService {
|
|||
}
|
||||
}
|
||||
|
||||
public ConversionExecutor getElementConverter(Class<?> sourceElementType, Class<?> targetElementType) {
|
||||
return getConversionExecutor(new TypeDescriptor(sourceElementType), new TypeDescriptor(targetElementType));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-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.core.convert.service;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
|
||||
/**
|
||||
* Special converter that converts an object to an single-element array. Mainly used internally by
|
||||
* {@link ConversionService} implementations.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class ObjectToArray implements SuperConverter {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
/**
|
||||
* Creates a new object to array converter.
|
||||
* @param conversionService the conversion service to resolve the converter to use to convert the object added to
|
||||
* the target array.
|
||||
*/
|
||||
public ObjectToArray(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new object to array converter.
|
||||
* @param elementConverter a specific converter to use to convert the object added to the target array.
|
||||
*/
|
||||
public ObjectToArray(ConversionExecutor elementConverter) {
|
||||
this.elementConverter = elementConverter;
|
||||
}
|
||||
|
||||
public Object convert(Object source, Class targetClass) throws Exception {
|
||||
Class componentType = targetClass.getComponentType();
|
||||
Object array = Array.newInstance(componentType, 1);
|
||||
ConversionExecutor converter;
|
||||
if (elementConverter != null) {
|
||||
converter = elementConverter;
|
||||
} else {
|
||||
converter = conversionService.getConversionExecutor(source.getClass(), componentType);
|
||||
}
|
||||
Array.set(array, 0, converter.execute(source));
|
||||
return array;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-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.core.convert.service;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
|
||||
/**
|
||||
* Special two-way converter that converts an object to an single-element collection. Supports type conversion of the
|
||||
* individual element with parameterized collection implementations.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class ObjectToCollection implements SuperConverter<Object, Collection> {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
/**
|
||||
* Creates a new object to collection converter
|
||||
* @param conversionService the conversion service to lookup the converter to use to convert an object when adding
|
||||
* it to a target collection
|
||||
*/
|
||||
public ObjectToCollection(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new object to collection converter
|
||||
* @param elementConverter a specific converter to execute on an object when adding it to a target collection
|
||||
*/
|
||||
public ObjectToCollection(ConversionExecutor elementConverter) {
|
||||
this.elementConverter = elementConverter;
|
||||
}
|
||||
|
||||
public Collection convert(Object source, Class targetClass) throws Exception {
|
||||
Class implClass = CollectionConversionUtils.getImpl(targetClass);
|
||||
Constructor constructor = implClass.getConstructor((Class[]) null);
|
||||
Collection collection = (Collection) constructor.newInstance((Object[]) null);
|
||||
ConversionExecutor converter = getElementConverter(source, targetClass);
|
||||
Object value;
|
||||
if (converter != null) {
|
||||
value = converter.execute(source);
|
||||
} else {
|
||||
value = source;
|
||||
}
|
||||
collection.add(value);
|
||||
return collection;
|
||||
}
|
||||
|
||||
private ConversionExecutor getElementConverter(Object source, Class targetClass) {
|
||||
if (elementConverter != null) {
|
||||
return elementConverter;
|
||||
} else {
|
||||
Class elementType = GenericCollectionTypeResolver.getCollectionType(targetClass);
|
||||
if (elementType != null) {
|
||||
Class componentType = source.getClass().getComponentType();
|
||||
return conversionService.getConversionExecutor(componentType, elementType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,47 +17,44 @@ package org.springframework.core.convert.service;
|
|||
|
||||
import org.springframework.core.convert.ConversionExecutionException;
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
class StaticConversionExecutor<S, T> implements ConversionExecutor<S, T> {
|
||||
class StaticConversionExecutor implements ConversionExecutor {
|
||||
|
||||
private final Class<S> sourceClass;
|
||||
private final TypeDescriptor sourceType;
|
||||
|
||||
private final Class<T> targetClass;
|
||||
private final TypeDescriptor targetType;
|
||||
|
||||
private final Converter<S, T> converter;
|
||||
private final Converter converter;
|
||||
|
||||
public StaticConversionExecutor(Class<S> sourceClass, Class<T> targetClass, Converter<S, T> converter) {
|
||||
Assert.notNull(sourceClass, "The source class is required");
|
||||
Assert.notNull(targetClass, "The target class is required");
|
||||
Assert.notNull(converter, "The converter is required");
|
||||
this.sourceClass = sourceClass;
|
||||
this.targetClass = targetClass;
|
||||
public StaticConversionExecutor(TypeDescriptor sourceClass, TypeDescriptor targetClass, Converter converter) {
|
||||
this.sourceType = sourceClass;
|
||||
this.targetType = targetClass;
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public Class<S> getSourceClass() {
|
||||
return sourceClass;
|
||||
public TypeDescriptor getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
public Class<T> getTargetClass() {
|
||||
return targetClass;
|
||||
public TypeDescriptor getTargetType() {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
public T execute(S source) throws ConversionExecutionException {
|
||||
public Object execute(Object source) throws ConversionExecutionException {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
if (!sourceClass.isInstance(source)) {
|
||||
throw new ConversionExecutionException(source, getSourceClass(), getTargetClass(), "Source object "
|
||||
+ source + " to convert is expected to be an instance of [" + getSourceClass().getName() + "]");
|
||||
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() + "]");
|
||||
}
|
||||
try {
|
||||
return converter.convert(source);
|
||||
} catch (Exception e) {
|
||||
throw new ConversionExecutionException(source, getSourceClass(), getTargetClass(), e);
|
||||
throw new ConversionExecutionException(source, getSourceType(), getTargetType(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,16 +62,16 @@ class StaticConversionExecutor<S, T> implements ConversionExecutor<S, T> {
|
|||
if (!(o instanceof StaticConversionExecutor)) {
|
||||
return false;
|
||||
}
|
||||
StaticConversionExecutor<?, ?> other = (StaticConversionExecutor<?, ?>) o;
|
||||
return sourceClass.equals(other.sourceClass) && targetClass.equals(other.targetClass);
|
||||
StaticConversionExecutor other = (StaticConversionExecutor) o;
|
||||
return sourceType.equals(other.sourceType) && targetType.equals(other.targetType);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return sourceClass.hashCode() + targetClass.hashCode();
|
||||
return sourceType.hashCode() + targetType.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("sourceClass", sourceClass).append("targetClass", targetClass)
|
||||
return new ToStringCreator(this).append("sourceClass", sourceType).append("targetClass", targetType)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -17,47 +17,37 @@ package org.springframework.core.convert.service;
|
|||
|
||||
import org.springframework.core.convert.ConversionExecutionException;
|
||||
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;
|
||||
|
||||
class StaticSuperConversionExecutor<S, T> implements ConversionExecutor<S, T> {
|
||||
class StaticSuperConversionExecutor implements ConversionExecutor {
|
||||
|
||||
private final Class<S> sourceClass;
|
||||
private final TypeDescriptor sourceType;
|
||||
|
||||
private final Class<T> targetClass;
|
||||
private final TypeDescriptor targetType;
|
||||
|
||||
private final SuperConverter<S, T> converter;
|
||||
private final SuperConverter converter;
|
||||
|
||||
public StaticSuperConversionExecutor(Class<S> sourceClass, Class<T> targetClass, SuperConverter<S, T> converter) {
|
||||
Assert.notNull(sourceClass, "The source class is required");
|
||||
Assert.notNull(targetClass, "The target class is required");
|
||||
Assert.notNull(converter, "The super converter is required");
|
||||
this.sourceClass = sourceClass;
|
||||
this.targetClass = targetClass;
|
||||
public StaticSuperConversionExecutor(TypeDescriptor sourceType, TypeDescriptor targetType, SuperConverter converter) {
|
||||
this.sourceType = sourceType;
|
||||
this.targetType = targetType;
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public Class<S> getSourceClass() {
|
||||
return sourceClass;
|
||||
}
|
||||
|
||||
public Class<T> getTargetClass() {
|
||||
return targetClass;
|
||||
}
|
||||
|
||||
public T execute(S source) throws ConversionExecutionException {
|
||||
public Object execute(Object source) throws ConversionExecutionException {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
if (!sourceClass.isInstance(source)) {
|
||||
throw new ConversionExecutionException(source, getSourceClass(), getTargetClass(), "Source object "
|
||||
+ source + " to convert is expected to be an instance of [" + getSourceClass().getName() + "]");
|
||||
if (!sourceType.isInstance(source)) {
|
||||
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, targetClass);
|
||||
return converter.convert(source, targetType.getType());
|
||||
} catch (Exception e) {
|
||||
throw new ConversionExecutionException(source, getSourceClass(), getTargetClass(), e);
|
||||
throw new ConversionExecutionException(source, sourceType, targetType, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,16 +55,16 @@ class StaticSuperConversionExecutor<S, T> implements ConversionExecutor<S, T> {
|
|||
if (!(o instanceof StaticSuperConversionExecutor)) {
|
||||
return false;
|
||||
}
|
||||
StaticSuperConversionExecutor<?, ?> other = (StaticSuperConversionExecutor<?, ?>) o;
|
||||
return sourceClass.equals(other.sourceClass) && targetClass.equals(other.targetClass);
|
||||
StaticSuperConversionExecutor other = (StaticSuperConversionExecutor) o;
|
||||
return sourceType.equals(other.sourceType) && targetType.equals(other.targetType);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return sourceClass.hashCode() + targetClass.hashCode();
|
||||
return sourceType.hashCode() + targetType.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("sourceClass", sourceClass).append("targetClass", targetClass)
|
||||
return new ToStringCreator(this).append("sourceClass", sourceType).append("targetClass", targetType)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,8 @@ import org.springframework.core.convert.ConversionException;
|
|||
import org.springframework.core.convert.ConversionExecutionException;
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionExecutorNotFoundException;
|
||||
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.NumberToNumber;
|
||||
import org.springframework.core.convert.converter.StringToEnum;
|
||||
|
|
@ -37,47 +39,55 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
private GenericConversionService service = new GenericConversionService();
|
||||
|
||||
private TypedValue value(Object obj) {
|
||||
return new TypedValue(obj, new TypeDescriptor(obj.getClass()));
|
||||
}
|
||||
|
||||
private TypeDescriptor type(Class clazz) {
|
||||
return new TypeDescriptor(clazz);
|
||||
}
|
||||
|
||||
public void testExecuteConversion() {
|
||||
service.addConverter(new StringToInteger());
|
||||
assertEquals(new Integer(3), service.executeConversion("3", Integer.class));
|
||||
assertEquals(new Integer(3), service.executeConversion(value("3"), type(Integer.class)));
|
||||
}
|
||||
|
||||
public void testConverterConversionForwardIndex() {
|
||||
service.addConverter(new StringToInteger());
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, Integer.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String.class), type(Integer.class));
|
||||
Integer three = (Integer) executor.execute("3");
|
||||
assertEquals(3, three.intValue());
|
||||
}
|
||||
|
||||
public void testConverterConversionReverseIndex() {
|
||||
service.addConverter(new StringToInteger());
|
||||
ConversionExecutor executor = service.getConversionExecutor(Integer.class, String.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(Integer.class), type(String.class));
|
||||
String threeString = (String) executor.execute(new Integer(3));
|
||||
assertEquals("3", threeString);
|
||||
}
|
||||
|
||||
public void testConversionExecutorNotFound() {
|
||||
try {
|
||||
service.getConversionExecutor(String.class, Integer.class);
|
||||
service.getConversionExecutor(type(String.class), type(Integer.class));
|
||||
fail("Should have thrown an exception");
|
||||
} catch (ConversionExecutorNotFoundException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testConversionCompatibleTypes() {
|
||||
ArrayList source = new ArrayList();
|
||||
assertSame(source, service.getConversionExecutor(ArrayList.class, List.class).execute(source));
|
||||
String source = "foo";
|
||||
assertSame(source, service.getConversionExecutor(type(String.class), type(String.class)).execute(source));
|
||||
}
|
||||
|
||||
public void testConversionExecutorNullArgument() {
|
||||
service.addConverter(new StringToInteger());
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, Integer.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String.class), type(Integer.class));
|
||||
assertNull(executor.execute(null));
|
||||
}
|
||||
|
||||
public void testConversionExecutorWrongTypeArgument() {
|
||||
service.addConverter(new StringToInteger());
|
||||
ConversionExecutor executor = service.getConversionExecutor(Integer.class, String.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(Integer.class), type(String.class));
|
||||
try {
|
||||
executor.execute("BOGUS");
|
||||
fail("Should have failed");
|
||||
|
|
@ -96,7 +106,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
return target.toString();
|
||||
}
|
||||
});
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, Integer.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String.class), type(Integer.class));
|
||||
Integer result = (Integer) executor.execute("3");
|
||||
assertEquals(new Integer(3), result);
|
||||
}
|
||||
|
|
@ -112,7 +122,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
}
|
||||
});
|
||||
try {
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, Integer.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String.class), type(Integer.class));
|
||||
fail("Should have failed");
|
||||
} catch (ConversionExecutorNotFoundException e) {
|
||||
|
||||
|
|
@ -121,14 +131,14 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testConversionObjectToPrimitive() {
|
||||
service.addConverter(new StringToInteger());
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, int.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String.class), type(int.class));
|
||||
Integer three = (Integer) executor.execute("3");
|
||||
assertEquals(3, three.intValue());
|
||||
}
|
||||
|
||||
public void testConversionArrayToArray() {
|
||||
service.addConverter(new StringToInteger());
|
||||
ConversionExecutor executor = service.getConversionExecutor(String[].class, Integer[].class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String[].class), type(Integer[].class));
|
||||
Integer[] result = (Integer[]) executor.execute(new String[] { "1", "2", "3" });
|
||||
assertEquals(new Integer(1), result[0]);
|
||||
assertEquals(new Integer(2), result[1]);
|
||||
|
|
@ -137,7 +147,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testConversionArrayToPrimitiveArray() {
|
||||
service.addConverter(new StringToInteger());
|
||||
ConversionExecutor executor = service.getConversionExecutor(String[].class, int[].class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String[].class), type(int[].class));
|
||||
int[] result = (int[]) executor.execute(new String[] { "1", "2", "3" });
|
||||
assertEquals(1, result[0]);
|
||||
assertEquals(2, result[1]);
|
||||
|
|
@ -145,15 +155,23 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
}
|
||||
|
||||
public void testConversionArrayToListInterface() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(String[].class, List.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String[].class), type(List.class));
|
||||
List result = (List) executor.execute(new String[] { "1", "2", "3" });
|
||||
assertEquals("1", result.get(0));
|
||||
assertEquals("2", result.get(1));
|
||||
assertEquals("3", result.get(2));
|
||||
}
|
||||
|
||||
public void testConversionArrayToListGenericTypeConversion() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String[].class), type(List.class));
|
||||
List result = (List) executor.execute(new String[] { "1", "2", "3" });
|
||||
assertEquals(new Integer("1"), result.get(0));
|
||||
assertEquals(new Integer("2"), result.get(1));
|
||||
assertEquals(new Integer("3"), result.get(2));
|
||||
}
|
||||
|
||||
public void testConversionArrayToListImpl() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(String[].class, LinkedList.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String[].class), type(LinkedList.class));
|
||||
LinkedList result = (LinkedList) executor.execute(new String[] { "1", "2", "3" });
|
||||
assertEquals("1", result.get(0));
|
||||
assertEquals("2", result.get(1));
|
||||
|
|
@ -162,14 +180,14 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testConversionArrayToAbstractList() {
|
||||
try {
|
||||
service.getConversionExecutor(String[].class, AbstractList.class);
|
||||
service.getConversionExecutor(type(String[].class), type(AbstractList.class));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void testConversionListToArray() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(Collection.class, String[].class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(Collection.class), type(String[].class));
|
||||
List list = new ArrayList();
|
||||
list.add("1");
|
||||
list.add("2");
|
||||
|
|
@ -182,7 +200,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testConversionListToArrayWithComponentConversion() {
|
||||
service.addConverter(new StringToInteger());
|
||||
ConversionExecutor executor = service.getConversionExecutor(Collection.class, Integer[].class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(Collection.class), type(Integer[].class));
|
||||
List list = new ArrayList();
|
||||
list.add("1");
|
||||
list.add("2");
|
||||
|
|
@ -194,7 +212,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
}
|
||||
|
||||
public void testConversionObjectToArray() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, String[].class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String.class), type(String[].class));
|
||||
String[] result = (String[]) executor.execute("1,2,3");
|
||||
assertEquals(1, result.length);
|
||||
assertEquals("1,2,3", result[0]);
|
||||
|
|
@ -202,7 +220,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testConversionObjectToArrayWithElementConversion() {
|
||||
service.addConverter(new StringToInteger());
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, Integer[].class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String.class), type(Integer[].class));
|
||||
Integer[] result = (Integer[]) executor.execute("123");
|
||||
assertEquals(1, result.length);
|
||||
assertEquals(new Integer(123), result[0]);
|
||||
|
|
@ -214,19 +232,19 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testSuperConverterConversionForwardIndex() {
|
||||
service.addConverter(new StringToEnum());
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, FooEnum.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String.class), type(FooEnum.class));
|
||||
assertEquals(FooEnum.BAR, executor.execute("BAR"));
|
||||
}
|
||||
|
||||
public void testSuperTwoWayConverterConversionReverseIndex() {
|
||||
service.addConverter(new StringToEnum());
|
||||
ConversionExecutor executor = service.getConversionExecutor(FooEnum.class, String.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(FooEnum.class), type(String.class));
|
||||
assertEquals("BAR", executor.execute(FooEnum.BAR));
|
||||
}
|
||||
|
||||
public void testSuperConverterConversionNotConvertibleAbstractType() {
|
||||
service.addConverter(new StringToEnum());
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, Enum.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(String.class), type(Enum.class));
|
||||
try {
|
||||
executor.execute("WHATEV");
|
||||
fail("Should have failed");
|
||||
|
|
@ -258,7 +276,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
return 0;
|
||||
}
|
||||
};
|
||||
ConversionExecutor executor = service.getConversionExecutor(Integer.class, customNumber.getClass());
|
||||
ConversionExecutor executor = service.getConversionExecutor(type(Integer.class), type(customNumber.getClass()));
|
||||
try {
|
||||
executor.execute(3);
|
||||
fail("Should have failed");
|
||||
|
|
@ -286,13 +304,13 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testCustomConverterConversionForwardIndex() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", String.class, Principal.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", type(String.class), type(Principal.class));
|
||||
assertEquals("keith", ((Principal) executor.execute("keith")).getName());
|
||||
}
|
||||
|
||||
public void testCustomConverterConversionReverseIndex() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", Principal.class, String.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", type(Principal.class), type(String.class));
|
||||
assertEquals("keith", executor.execute(new Principal() {
|
||||
public String getName() {
|
||||
return "keith";
|
||||
|
|
@ -302,14 +320,14 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testCustomConverterConversionForSameType() {
|
||||
service.addConverter("trimmer", new Trimmer());
|
||||
ConversionExecutor executor = service.getConversionExecutor("trimmer", String.class, String.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor("trimmer", type(String.class), type(String.class));
|
||||
assertEquals("a string", executor.execute("a string "));
|
||||
}
|
||||
|
||||
public void testCustomConverterLookupNotCompatibleSource() {
|
||||
service.addConverter("trimmer", new Trimmer());
|
||||
try {
|
||||
service.getConversionExecutor("trimmer", Object.class, String.class);
|
||||
service.getConversionExecutor("trimmer", type(Object.class), type(String.class));
|
||||
fail("Should have failed");
|
||||
} catch (ConversionException e) {
|
||||
|
||||
|
|
@ -319,7 +337,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
public void testCustomConverterLookupNotCompatibleTarget() {
|
||||
service.addConverter("trimmer", new Trimmer());
|
||||
try {
|
||||
service.getConversionExecutor("trimmer", String.class, Object.class);
|
||||
service.getConversionExecutor("trimmer", type(String.class), type(Object.class));
|
||||
} catch (ConversionException e) {
|
||||
|
||||
}
|
||||
|
|
@ -328,7 +346,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
public void testCustomConverterLookupNotCompatibleTargetReverse() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
try {
|
||||
service.getConversionExecutor("princy", Principal.class, Integer.class);
|
||||
service.getConversionExecutor("princy", type(Principal.class), type(Integer.class));
|
||||
} catch (ConversionException e) {
|
||||
|
||||
}
|
||||
|
|
@ -336,7 +354,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testCustomConverterConversionArrayToArray() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", String[].class, Principal[].class);
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", type(String[].class), type(Principal[].class));
|
||||
Principal[] p = (Principal[]) executor.execute(new String[] { "princy1", "princy2" });
|
||||
assertEquals("princy1", p[0].getName());
|
||||
assertEquals("princy2", p[1].getName());
|
||||
|
|
@ -344,7 +362,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testCustomConverterConversionArrayToArrayReverse() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", Principal[].class, String[].class);
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", type(Principal[].class), type(String[].class));
|
||||
final Principal princy1 = new Principal() {
|
||||
public String getName() {
|
||||
return "princy1";
|
||||
|
|
@ -363,7 +381,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
public void testCustomConverterLookupArrayToArrayBogusSource() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
try {
|
||||
service.getConversionExecutor("princy", Integer[].class, Principal[].class);
|
||||
service.getConversionExecutor("princy", type(Integer[].class), type(Principal[].class));
|
||||
fail("Should have failed");
|
||||
} catch (ConversionExecutorNotFoundException e) {
|
||||
}
|
||||
|
|
@ -372,7 +390,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
public void testCustomConverterLookupArrayToArrayBogusTarget() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
try {
|
||||
service.getConversionExecutor("princy", Principal[].class, Integer[].class);
|
||||
service.getConversionExecutor("princy", type(Principal[].class), type(Integer[].class));
|
||||
} catch (ConversionExecutorNotFoundException e) {
|
||||
|
||||
}
|
||||
|
|
@ -380,7 +398,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testCustomConverterConversionArrayToCollection() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", String[].class, List.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", type(String[].class), type(List.class));
|
||||
List list = (List) executor.execute(new String[] { "princy1", "princy2" });
|
||||
assertEquals("princy1", ((Principal) list.get(0)).getName());
|
||||
assertEquals("princy2", ((Principal) list.get(1)).getName());
|
||||
|
|
@ -388,7 +406,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testCustomConverterConversionArrayToCollectionReverse() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", Principal[].class, List.class);
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", type(Principal[].class), type(List.class));
|
||||
final Principal princy1 = new Principal() {
|
||||
public String getName() {
|
||||
return "princy1";
|
||||
|
|
@ -407,7 +425,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
public void testCustomConverterLookupArrayToCollectionBogusSource() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
try {
|
||||
service.getConversionExecutor("princy", Integer[].class, List.class);
|
||||
service.getConversionExecutor("princy", type(Integer[].class), type(List.class));
|
||||
fail("Should have failed");
|
||||
} catch (ConversionExecutorNotFoundException e) {
|
||||
|
||||
|
|
@ -416,7 +434,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testCustomConverterLookupCollectionToArray() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", List.class, Principal[].class);
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", type(List.class), type(Principal[].class));
|
||||
List princyList = new ArrayList();
|
||||
princyList.add("princy1");
|
||||
princyList.add("princy2");
|
||||
|
|
@ -427,7 +445,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testCustomConverterLookupCollectionToArrayReverse() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", List.class, String[].class);
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", type(List.class), type(String[].class));
|
||||
final Principal princy1 = new Principal() {
|
||||
public String getName() {
|
||||
return "princy1";
|
||||
|
|
@ -449,7 +467,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
public void testtestCustomConverterLookupCollectionToArrayBogusTarget() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
try {
|
||||
service.getConversionExecutor("princy", List.class, Integer[].class);
|
||||
service.getConversionExecutor("princy", type(List.class), type(Integer[].class));
|
||||
fail("Should have failed");
|
||||
} catch (ConversionExecutorNotFoundException e) {
|
||||
|
||||
|
|
@ -458,14 +476,14 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
|
||||
public void testCustomConverterConversionObjectToArray() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", String.class, Principal[].class);
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", type(String.class), type(Principal[].class));
|
||||
Principal[] p = (Principal[]) executor.execute("princy1");
|
||||
assertEquals("princy1", p[0].getName());
|
||||
}
|
||||
|
||||
public void testCustomConverterConversionObjectToArrayReverse() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", Principal.class, String[].class);
|
||||
ConversionExecutor executor = service.getConversionExecutor("princy", type(Principal.class), type(String[].class));
|
||||
final Principal princy1 = new Principal() {
|
||||
public String getName() {
|
||||
return "princy1";
|
||||
|
|
@ -478,7 +496,7 @@ public class GenericConversionServiceTests extends TestCase {
|
|||
public void testCustomConverterLookupObjectToArrayBogusSource() {
|
||||
service.addConverter("princy", new CustomTwoWayConverter());
|
||||
try {
|
||||
service.getConversionExecutor("princy", Integer.class, Principal[].class);
|
||||
service.getConversionExecutor("princy", type(Integer.class), type(Principal[].class));
|
||||
fail("Should have failed");
|
||||
} catch (ConversionExecutorNotFoundException e) {
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue