documented hooks
This commit is contained in:
parent
a6e28f4eb5
commit
01e900c33a
|
|
@ -17,6 +17,7 @@ package org.springframework.core.convert.support;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConverterNotFoundException;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
|
||||||
class ArrayToArrayGenericConverter implements GenericConverter {
|
class ArrayToArrayGenericConverter implements GenericConverter {
|
||||||
|
|
@ -34,7 +35,10 @@ class ArrayToArrayGenericConverter implements GenericConverter {
|
||||||
TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor();
|
TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor();
|
||||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
||||||
Object target = Array.newInstance(targetElementType.getType(), Array.getLength(source));
|
Object target = Array.newInstance(targetElementType.getType(), Array.getLength(source));
|
||||||
GenericConverter converter = conversionService.getConverter(sourceElementType, targetElementType);
|
GenericConverter converter = conversionService.getConverter(sourceElementType, targetElementType);
|
||||||
|
if (converter == null) {
|
||||||
|
throw new ConverterNotFoundException(sourceType, targetType);
|
||||||
|
}
|
||||||
for (int i = 0; i < Array.getLength(target); i++) {
|
for (int i = 0; i < Array.getLength(target); i++) {
|
||||||
Array.set(target, i, converter.convert(Array.get(source, i), sourceElementType, targetElementType));
|
Array.set(target, i, converter.convert(Array.get(source, i), sourceElementType, targetElementType));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import java.lang.reflect.Array;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
import org.springframework.core.CollectionFactory;
|
||||||
|
import org.springframework.core.convert.ConverterNotFoundException;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
|
||||||
class ArrayToCollectionGenericConverter implements GenericConverter {
|
class ArrayToCollectionGenericConverter implements GenericConverter {
|
||||||
|
|
@ -40,6 +41,9 @@ class ArrayToCollectionGenericConverter implements GenericConverter {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GenericConverter converter = conversionService.getConverter(sourceElementType, targetElementType);
|
GenericConverter converter = conversionService.getConverter(sourceElementType, targetElementType);
|
||||||
|
if (converter == null) {
|
||||||
|
throw new ConverterNotFoundException(sourceType, targetType);
|
||||||
|
}
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
collection.add(converter.convert(Array.get(source, i), sourceElementType, targetElementType));
|
collection.add(converter.convert(Array.get(source, i), sourceElementType, targetElementType));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ package org.springframework.core.convert.support;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConverterNotFoundException;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
|
||||||
class ArrayToObjectGenericConverter implements GenericConverter {
|
class ArrayToObjectGenericConverter implements GenericConverter {
|
||||||
|
|
@ -37,6 +38,9 @@ class ArrayToObjectGenericConverter implements GenericConverter {
|
||||||
return Array.get(source, 0);
|
return Array.get(source, 0);
|
||||||
} else {
|
} else {
|
||||||
GenericConverter converter = conversionService.getConverter(sourceElementType, targetType);
|
GenericConverter converter = conversionService.getConverter(sourceElementType, targetType);
|
||||||
|
if (converter == null) {
|
||||||
|
throw new ConverterNotFoundException(sourceType, targetType);
|
||||||
|
}
|
||||||
return converter.convert(Array.get(source, 0), sourceElementType, targetType);
|
return converter.convert(Array.get(source, 0), sourceElementType, targetType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import java.lang.reflect.Array;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConverterNotFoundException;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
|
||||||
class CollectionToArrayGenericConverter implements GenericConverter {
|
class CollectionToArrayGenericConverter implements GenericConverter {
|
||||||
|
|
@ -44,6 +45,9 @@ class CollectionToArrayGenericConverter implements GenericConverter {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GenericConverter converter = conversionService.getConverter(sourceElementType, targetElementType);
|
GenericConverter converter = conversionService.getConverter(sourceElementType, targetElementType);
|
||||||
|
if (converter == null) {
|
||||||
|
throw new ConverterNotFoundException(sourceType, targetType);
|
||||||
|
}
|
||||||
for (Iterator it = sourceCollection.iterator(); it.hasNext(); i++) {
|
for (Iterator it = sourceCollection.iterator(); it.hasNext(); i++) {
|
||||||
Array.set(array, i, converter.convert(it.next(), sourceElementType, targetElementType));
|
Array.set(array, i, converter.convert(it.next(), sourceElementType, targetElementType));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package org.springframework.core.convert.support;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
import org.springframework.core.CollectionFactory;
|
||||||
|
import org.springframework.core.convert.ConverterNotFoundException;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
|
||||||
class CollectionToCollectionGenericConverter implements GenericConverter {
|
class CollectionToCollectionGenericConverter implements GenericConverter {
|
||||||
|
|
@ -46,6 +47,9 @@ class CollectionToCollectionGenericConverter implements GenericConverter {
|
||||||
}
|
}
|
||||||
Collection targetCollection = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
|
Collection targetCollection = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
|
||||||
GenericConverter converter = conversionService.getConverter(sourceElementType, targetElementType);
|
GenericConverter converter = conversionService.getConverter(sourceElementType, targetElementType);
|
||||||
|
if (converter == null) {
|
||||||
|
throw new ConverterNotFoundException(sourceType, targetType);
|
||||||
|
}
|
||||||
for (Object element : sourceCollection) {
|
for (Object element : sourceCollection) {
|
||||||
targetCollection.add(converter.convert(element, sourceElementType, targetElementType));
|
targetCollection.add(converter.convert(element, sourceElementType, targetElementType));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ package org.springframework.core.convert.support;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConverterNotFoundException;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
|
||||||
class CollectionToObjectGenericConverter implements GenericConverter {
|
class CollectionToObjectGenericConverter implements GenericConverter {
|
||||||
|
|
@ -37,6 +38,9 @@ class CollectionToObjectGenericConverter implements GenericConverter {
|
||||||
return sourceCollection.iterator().next();
|
return sourceCollection.iterator().next();
|
||||||
} else {
|
} else {
|
||||||
GenericConverter converter = conversionService.getConverter(sourceElementType, targetType);
|
GenericConverter converter = conversionService.getConverter(sourceElementType, targetType);
|
||||||
|
if (converter == null) {
|
||||||
|
throw new ConverterNotFoundException(sourceType, targetType);
|
||||||
|
}
|
||||||
return converter.convert(sourceCollection.iterator().next(), sourceElementType, targetType);
|
return converter.convert(sourceCollection.iterator().next(), sourceElementType, targetType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private GenericConversionService parent;
|
private GenericConversionService parent;
|
||||||
|
|
||||||
private final Map<Class, Map<Class, GenericConverter>> sourceTypeConverters = new HashMap<Class, Map<Class, GenericConverter>>();
|
private final Map<Class, Map<Class, GenericConverter>> sourceTypeConverters = new HashMap<Class, Map<Class, GenericConverter>>();
|
||||||
|
|
@ -162,6 +162,9 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
GenericConverter converter = getConverter(sourceType, targetType);
|
GenericConverter converter = getConverter(sourceType, targetType);
|
||||||
|
if (converter == null) {
|
||||||
|
throw new ConverterNotFoundException(sourceType, targetType);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return converter.convert(source, sourceType, targetType);
|
return converter.convert(source, sourceType, targetType);
|
||||||
} catch (ConversionFailedException e) {
|
} catch (ConversionFailedException e) {
|
||||||
|
|
@ -173,6 +176,9 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
||||||
|
|
||||||
// subclassing hooks
|
// subclassing hooks
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook to initialize the "generic" converters that require the full TypeDescriptor context to perform their conversion operations.
|
||||||
|
*/
|
||||||
protected void initGenericConverters() {
|
protected void initGenericConverters() {
|
||||||
addGenericConverter(Object[].class, Object[].class, new ArrayToArrayGenericConverter(this));
|
addGenericConverter(Object[].class, Object[].class, new ArrayToArrayGenericConverter(this));
|
||||||
addGenericConverter(Object[].class, Collection.class, new ArrayToCollectionGenericConverter(this));
|
addGenericConverter(Object[].class, Collection.class, new ArrayToCollectionGenericConverter(this));
|
||||||
|
|
@ -185,14 +191,39 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
||||||
addGenericConverter(Object.class, Collection.class, new ObjectToCollectionGenericConverter(this));
|
addGenericConverter(Object.class, Collection.class, new ObjectToCollectionGenericConverter(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a GenericConverter.
|
||||||
|
* @param sourceType the source type to convert from
|
||||||
|
* @param targetType the target type to convert to
|
||||||
|
* @param converter the generic converter.
|
||||||
|
*/
|
||||||
protected void addGenericConverter(Class<?> sourceType, Class<?> targetType, GenericConverter converter) {
|
protected void addGenericConverter(Class<?> sourceType, Class<?> targetType, GenericConverter converter) {
|
||||||
getSourceMap(sourceType).put(targetType, converter);
|
getSourceMap(sourceType).put(targetType, converter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook method to convert a null value.
|
||||||
|
* Default implementation simply returns <code>null</code>.
|
||||||
|
* Subclasses may override to return a custom null objects for specific target types.
|
||||||
|
* @param sourceType the sourceType
|
||||||
|
* @param targetType the tagetType
|
||||||
|
* @return the null object
|
||||||
|
*/
|
||||||
protected Object convertNull(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
protected Object convertNull(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook method to lookup the converter for a given sourceType/targetType pair.
|
||||||
|
* First queries this ConversionService's converter map.
|
||||||
|
* If no suitable Converter is found, and a {@link #setParent(GenericConversionService) parent} is set, then queries the parent.
|
||||||
|
* If still no suitable Converter is found, returns a NO_OP Converter if the sourceType and targetType are assignable.
|
||||||
|
* Returns <code>null</code> if this ConversionService simply cannot convert between sourceType and targetType.
|
||||||
|
* Subclasses may override.
|
||||||
|
* @param sourceType the source type to convert from
|
||||||
|
* @param targetType the target type to convert to
|
||||||
|
* @return the generic converter that will perform the conversion, or <code>null</code> if no suitable converter was found
|
||||||
|
*/
|
||||||
protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
GenericConverter converter = findConverterByClassPair(sourceType.getObjectType(), targetType.getObjectType());
|
GenericConverter converter = findConverterByClassPair(sourceType.getObjectType(), targetType.getObjectType());
|
||||||
if (converter != null) {
|
if (converter != null) {
|
||||||
|
|
@ -204,7 +235,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
||||||
if (sourceType.isAssignableTo(targetType)) {
|
if (sourceType.isAssignableTo(targetType)) {
|
||||||
return NO_OP_CONVERTER;
|
return NO_OP_CONVERTER;
|
||||||
} else {
|
} else {
|
||||||
throw new ConverterNotFoundException(sourceType, targetType);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package org.springframework.core.convert.support;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
import org.springframework.core.CollectionFactory;
|
||||||
|
import org.springframework.core.convert.ConverterNotFoundException;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
|
||||||
class MapToMapGenericConverter implements GenericConverter {
|
class MapToMapGenericConverter implements GenericConverter {
|
||||||
|
|
@ -95,11 +96,17 @@ class MapToMapGenericConverter implements GenericConverter {
|
||||||
GenericConversionService conversionService) {
|
GenericConversionService conversionService) {
|
||||||
if (sourceKeyType != TypeDescriptor.NULL && targetKeyType != TypeDescriptor.NULL && !keysCompatible) {
|
if (sourceKeyType != TypeDescriptor.NULL && targetKeyType != TypeDescriptor.NULL && !keysCompatible) {
|
||||||
this.keyConverter = conversionService.getConverter(sourceKeyType, targetKeyType);
|
this.keyConverter = conversionService.getConverter(sourceKeyType, targetKeyType);
|
||||||
|
if (this.keyConverter == null) {
|
||||||
|
throw new ConverterNotFoundException(sourceKeyType, targetKeyType);
|
||||||
|
}
|
||||||
this.sourceKeyType = sourceKeyType;
|
this.sourceKeyType = sourceKeyType;
|
||||||
this.targetKeyType = targetKeyType;
|
this.targetKeyType = targetKeyType;
|
||||||
}
|
}
|
||||||
if (sourceValueType != TypeDescriptor.NULL && targetValueType != TypeDescriptor.NULL && !valuesCompatible) {
|
if (sourceValueType != TypeDescriptor.NULL && targetValueType != TypeDescriptor.NULL && !valuesCompatible) {
|
||||||
this.valueConverter = conversionService.getConverter(sourceValueType, targetValueType);
|
this.valueConverter = conversionService.getConverter(sourceValueType, targetValueType);
|
||||||
|
if (this.valueConverter == null) {
|
||||||
|
throw new ConverterNotFoundException(sourceValueType, targetValueType);
|
||||||
|
}
|
||||||
this.targetKeyType = targetKeyType;
|
this.targetKeyType = targetKeyType;
|
||||||
this.targetValueType = targetValueType;
|
this.targetValueType = targetValueType;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ package org.springframework.core.convert.support;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConverterNotFoundException;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
|
||||||
class ObjectToArrayGenericConverter implements GenericConverter {
|
class ObjectToArrayGenericConverter implements GenericConverter {
|
||||||
|
|
@ -34,6 +35,9 @@ class ObjectToArrayGenericConverter implements GenericConverter {
|
||||||
Array.set(target, 0, source);
|
Array.set(target, 0, source);
|
||||||
} else {
|
} else {
|
||||||
GenericConverter converter = conversionService.getConverter(sourceType, targetElementType);
|
GenericConverter converter = conversionService.getConverter(sourceType, targetElementType);
|
||||||
|
if (converter == null) {
|
||||||
|
throw new ConverterNotFoundException(sourceType, targetType);
|
||||||
|
}
|
||||||
Array.set(target, 0, converter.convert(source, sourceType, targetElementType));
|
Array.set(target, 0, converter.convert(source, sourceType, targetElementType));
|
||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package org.springframework.core.convert.support;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
import org.springframework.core.CollectionFactory;
|
||||||
|
import org.springframework.core.convert.ConverterNotFoundException;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
|
||||||
class ObjectToCollectionGenericConverter implements GenericConverter {
|
class ObjectToCollectionGenericConverter implements GenericConverter {
|
||||||
|
|
@ -27,7 +28,7 @@ class ObjectToCollectionGenericConverter implements GenericConverter {
|
||||||
public ObjectToCollectionGenericConverter(GenericConversionService conversionService) {
|
public ObjectToCollectionGenericConverter(GenericConversionService conversionService) {
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
Collection target = CollectionFactory.createCollection(targetType.getType(), 1);
|
Collection target = CollectionFactory.createCollection(targetType.getType(), 1);
|
||||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
||||||
|
|
@ -35,6 +36,9 @@ class ObjectToCollectionGenericConverter implements GenericConverter {
|
||||||
target.add(source);
|
target.add(source);
|
||||||
} else {
|
} else {
|
||||||
GenericConverter converter = conversionService.getConverter(sourceType, targetElementType);
|
GenericConverter converter = conversionService.getConverter(sourceType, targetElementType);
|
||||||
|
if (converter == null) {
|
||||||
|
throw new ConverterNotFoundException(sourceType, targetType);
|
||||||
|
}
|
||||||
target.add(converter.convert(source, sourceType, targetElementType));
|
target.add(converter.convert(source, sourceType, targetElementType));
|
||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ package org.springframework.core.convert.support;
|
||||||
import static junit.framework.Assert.assertEquals;
|
import static junit.framework.Assert.assertEquals;
|
||||||
import static junit.framework.Assert.assertNull;
|
import static junit.framework.Assert.assertNull;
|
||||||
import static junit.framework.Assert.fail;
|
import static junit.framework.Assert.fail;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.AbstractList;
|
import java.util.AbstractList;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -265,6 +267,27 @@ public class GenericConversionServiceTests {
|
||||||
assertEquals(new Integer(3), result[2]);
|
assertEquals(new Integer(3), result[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void genericConverterDelegatingBackToConversionServiceConverterNotFound() {
|
||||||
|
try {
|
||||||
|
converter.convert("1", Integer[].class);
|
||||||
|
} catch (ConversionFailedException e) {
|
||||||
|
assertTrue(e.getCause() instanceof ConverterNotFoundException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parent() {
|
||||||
|
GenericConversionService parent = new GenericConversionService();
|
||||||
|
converter.setParent(parent);
|
||||||
|
assertFalse(converter.canConvert(String.class, Integer.class));
|
||||||
|
try {
|
||||||
|
converter.convert("3", Integer.class);
|
||||||
|
} catch (ConverterNotFoundException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static enum FooEnum {
|
public static enum FooEnum {
|
||||||
BAR, BAZ
|
BAR, BAZ
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue