This commit is contained in:
Keith Donald
2009-02-13 20:49:24 +00:00
parent 5b0c53f079
commit 4ceabdc927
7 changed files with 180 additions and 68 deletions

View File

@@ -36,11 +36,17 @@ public class ArrayToArray implements Converter {
/**
* 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;
}
/**
* 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;
}

View File

@@ -50,10 +50,19 @@ public class ArrayToCollection implements TwoWayConverter {
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;
}
/**
* 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;
}

View File

@@ -14,16 +14,31 @@ import org.springframework.binding.convert.ConversionService;
import org.springframework.core.GenericCollectionTypeResolver;
import org.springframework.core.JdkVersion;
/**
* A converter that can convert from one collection type to another.
*
* @author Keith Donald
*/
public class CollectionToCollection implements Converter {
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;
}
/**
* Creates a new collection-to-collection converter
* @param conversionService a specific converter to use to convert collection elements added to the target
* collection
*/
public CollectionToCollection(ConversionExecutor elementConverter) {
this.elementConverter = elementConverter;
}
@@ -55,6 +70,7 @@ public class CollectionToCollection implements Converter {
return targetCollection;
}
// this code is duplicated in ArrayToCollection.java and ObjectToCollection too
private Class getCollectionImplClass(Class targetClass) {
if (targetClass.isInterface()) {
if (List.class.equals(targetClass)) {

View File

@@ -32,10 +32,19 @@ public class ObjectToArray implements Converter {
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;
}

View File

@@ -39,10 +39,16 @@ public class ObjectToCollection implements Converter {
private ConversionService conversionService;
private ConversionExecutor elementConverter;
public ObjectToCollection(ConversionService conversionService) {
this.conversionService = conversionService;
}
public ObjectToCollection(ConversionExecutor elementConverter) {
this.elementConverter = elementConverter;
}
public Class getSourceClass() {
return Object.class;
}
@@ -69,6 +75,7 @@ public class ObjectToCollection implements Converter {
return collection;
}
// this code is duplicated in ArrayToCollection and CollectionToCollection
private Class getCollectionImplClass(Class targetClass) {
if (targetClass.isInterface()) {
if (List.class.equals(targetClass)) {
@@ -86,13 +93,17 @@ public class ObjectToCollection implements Converter {
}
private ConversionExecutor getElementConverter(Object source, Class targetClass) {
if (JdkVersion.isAtLeastJava15()) {
Class elementType = GenericCollectionTypeResolver.getCollectionType(targetClass);
if (elementType != null) {
Class componentType = source.getClass().getComponentType();
return conversionService.getConversionExecutor(componentType, elementType);
if (elementConverter != null) {
return elementConverter;
} else {
if (JdkVersion.isAtLeastJava15()) {
Class elementType = GenericCollectionTypeResolver.getCollectionType(targetClass);
if (elementType != null) {
Class componentType = source.getClass().getComponentType();
return conversionService.getConversionExecutor(componentType, elementType);
}
}
return null;
}
return null;
}
}

View File

@@ -26,7 +26,6 @@ import java.util.Map;
import java.util.Set;
import org.springframework.binding.convert.ConversionException;
import org.springframework.binding.convert.ConversionExecutionException;
import org.springframework.binding.convert.ConversionExecutor;
import org.springframework.binding.convert.ConversionExecutorNotFoundException;
import org.springframework.binding.convert.ConversionService;
@@ -35,6 +34,7 @@ import org.springframework.binding.convert.converters.ArrayToCollection;
import org.springframework.binding.convert.converters.CollectionToCollection;
import org.springframework.binding.convert.converters.Converter;
import org.springframework.binding.convert.converters.ObjectToArray;
import org.springframework.binding.convert.converters.ObjectToCollection;
import org.springframework.binding.convert.converters.ReverseConverter;
import org.springframework.binding.convert.converters.TwoWayConverter;
import org.springframework.util.Assert;
@@ -194,9 +194,8 @@ public class GenericConversionService implements ConversionService {
if (!converter.getTargetClass().isAssignableFrom(targetComponentType)) {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id
+ "' cannot convert from array storing elements of type ["
+ sourceComponentType.getName()
+ "]; to an array of storing elements of type ["
+ "' 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,
@@ -210,8 +209,9 @@ public class GenericConversionService implements ConversionService {
return new StaticConversionExecutor(sourceClass, targetClass, new ArrayToArray(elementConverter));
} else {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id + "' cannot convert from array of type ["
+ sourceComponentType.getName() + "]; to an array of type ["
"Custom ConversionExecutor 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)) {
@@ -236,8 +236,9 @@ public class GenericConversionService implements ConversionService {
} else {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id
+ "' cannot convert from array storing elements type ["
+ sourceComponentType.getName() + "]; to collection");
+ "' cannot convert from array an storing elements type ["
+ sourceComponentType.getName() + "] to a collection of type ["
+ targetClass.getName() + "]");
}
}
}
@@ -259,8 +260,8 @@ public class GenericConversionService implements ConversionService {
return new StaticConversionExecutor(sourceClass, targetClass, collectionToArray);
} else {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id
+ "' cannot convert from collection to to an array holding elements of type ["
"Custom ConversionExecutor with id '" + id + "' cannot convert from collection of type ["
+ sourceClass.getName() + "] to an array storing elements of type ["
+ targetComponentType.getName() + "]");
}
} else {
@@ -289,17 +290,30 @@ public class GenericConversionService implements ConversionService {
}
}
}
if (Collection.class.isAssignableFrom(sourceClass) && Collection.class.isAssignableFrom(targetClass)) {
ConversionExecutor elementConverter;
// type erasure forces us to do runtime checks of list elements
if (converter instanceof TwoWayConverter) {
elementConverter = new TwoWayCapableConversionExecutor(converter.getSourceClass(), converter
.getTargetClass(), (TwoWayConverter) converter);
if (Collection.class.isAssignableFrom(targetClass)) {
if (Collection.class.isAssignableFrom(sourceClass)) {
ConversionExecutor elementConverter;
// type erasure forces us to do runtime checks of list elements
if (converter instanceof TwoWayConverter) {
elementConverter = new TwoWayCapableConversionExecutor(converter.getSourceClass(), converter
.getTargetClass(), (TwoWayConverter) converter);
} else {
elementConverter = new StaticConversionExecutor(converter.getSourceClass(), converter
.getTargetClass(), converter);
}
return new StaticConversionExecutor(sourceClass, targetClass, new CollectionToCollection(
elementConverter));
} else {
elementConverter = new StaticConversionExecutor(converter.getSourceClass(), converter.getTargetClass(),
converter);
ConversionExecutor elementConverter;
// type erasure forces us to do runtime checks of list elements
if (converter instanceof TwoWayConverter) {
elementConverter = new TwoWayCapableConversionExecutor(sourceClass, converter.getTargetClass(),
(TwoWayConverter) converter);
} else {
elementConverter = new StaticConversionExecutor(sourceClass, converter.getTargetClass(), converter);
}
return new StaticConversionExecutor(sourceClass, targetClass, new ObjectToCollection(elementConverter));
}
return new StaticConversionExecutor(sourceClass, targetClass, new CollectionToCollection(elementConverter));
}
if (converter.getSourceClass().isAssignableFrom(sourceClass)) {
if (!converter.getTargetClass().isAssignableFrom(targetClass)) {
@@ -501,47 +515,4 @@ public class GenericConversionService implements ConversionService {
return targetType;
}
}
private static class TwoWayCapableConversionExecutor implements ConversionExecutor {
private Class sourceClass;
private Class targetClass;
private TwoWayConverter converter;
public TwoWayCapableConversionExecutor(Class sourceClass, Class targetClass, TwoWayConverter converter) {
this.sourceClass = sourceClass;
this.targetClass = targetClass;
this.converter = converter;
}
public Class getSourceClass() {
return sourceClass;
}
public Class getTargetClass() {
return targetClass;
}
public Object execute(Object source) throws ConversionExecutionException {
if (source == null || getSourceClass().isInstance(source)) {
try {
return converter.convertSourceToTargetClass(source, targetClass);
} catch (Exception e) {
throw new ConversionExecutionException(source, getSourceClass(), getTargetClass(), e);
}
} else if (getTargetClass().isInstance(source)) {
try {
return converter.convertTargetToSourceClass(source, sourceClass);
} catch (Exception e) {
throw new ConversionExecutionException(source, getTargetClass(), getSourceClass(), e);
}
} else {
throw new ConversionExecutionException(source, getSourceClass(), getTargetClass(), "Source object "
+ source + " to convert is expected to be an instance of [" + getSourceClass().getName()
+ "] or [" + getTargetClass().getName() + "]");
}
}
}
}