documented hooks

This commit is contained in:
Keith Donald 2009-09-21 22:24:36 +00:00
parent a6e28f4eb5
commit 01e900c33a
11 changed files with 97 additions and 4 deletions

View File

@ -17,6 +17,7 @@ package org.springframework.core.convert.support;
import java.lang.reflect.Array;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
class ArrayToArrayGenericConverter implements GenericConverter {
@ -35,6 +36,9 @@ class ArrayToArrayGenericConverter implements GenericConverter {
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
Object target = Array.newInstance(targetElementType.getType(), Array.getLength(source));
GenericConverter converter = conversionService.getConverter(sourceElementType, targetElementType);
if (converter == null) {
throw new ConverterNotFoundException(sourceType, targetType);
}
for (int i = 0; i < Array.getLength(target); i++) {
Array.set(target, i, converter.convert(Array.get(source, i), sourceElementType, targetElementType));
}

View File

@ -19,6 +19,7 @@ import java.lang.reflect.Array;
import java.util.Collection;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
class ArrayToCollectionGenericConverter implements GenericConverter {
@ -40,6 +41,9 @@ class ArrayToCollectionGenericConverter implements GenericConverter {
}
} else {
GenericConverter converter = conversionService.getConverter(sourceElementType, targetElementType);
if (converter == null) {
throw new ConverterNotFoundException(sourceType, targetType);
}
for (int i = 0; i < length; i++) {
collection.add(converter.convert(Array.get(source, i), sourceElementType, targetElementType));
}

View File

@ -17,6 +17,7 @@ package org.springframework.core.convert.support;
import java.lang.reflect.Array;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
class ArrayToObjectGenericConverter implements GenericConverter {
@ -37,6 +38,9 @@ class ArrayToObjectGenericConverter implements GenericConverter {
return Array.get(source, 0);
} else {
GenericConverter converter = conversionService.getConverter(sourceElementType, targetType);
if (converter == null) {
throw new ConverterNotFoundException(sourceType, targetType);
}
return converter.convert(Array.get(source, 0), sourceElementType, targetType);
}
}

View File

@ -19,6 +19,7 @@ import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
class CollectionToArrayGenericConverter implements GenericConverter {
@ -44,6 +45,9 @@ class CollectionToArrayGenericConverter implements GenericConverter {
}
} else {
GenericConverter converter = conversionService.getConverter(sourceElementType, targetElementType);
if (converter == null) {
throw new ConverterNotFoundException(sourceType, targetType);
}
for (Iterator it = sourceCollection.iterator(); it.hasNext(); i++) {
Array.set(array, i, converter.convert(it.next(), sourceElementType, targetElementType));
}

View File

@ -18,6 +18,7 @@ package org.springframework.core.convert.support;
import java.util.Collection;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
class CollectionToCollectionGenericConverter implements GenericConverter {
@ -46,6 +47,9 @@ class CollectionToCollectionGenericConverter implements GenericConverter {
}
Collection targetCollection = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
GenericConverter converter = conversionService.getConverter(sourceElementType, targetElementType);
if (converter == null) {
throw new ConverterNotFoundException(sourceType, targetType);
}
for (Object element : sourceCollection) {
targetCollection.add(converter.convert(element, sourceElementType, targetElementType));
}

View File

@ -17,6 +17,7 @@ package org.springframework.core.convert.support;
import java.util.Collection;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
class CollectionToObjectGenericConverter implements GenericConverter {
@ -37,6 +38,9 @@ class CollectionToObjectGenericConverter implements GenericConverter {
return sourceCollection.iterator().next();
} else {
GenericConverter converter = conversionService.getConverter(sourceElementType, targetType);
if (converter == null) {
throw new ConverterNotFoundException(sourceType, targetType);
}
return converter.convert(sourceCollection.iterator().next(), sourceElementType, targetType);
}
}

View File

@ -162,6 +162,9 @@ public class GenericConversionService implements ConversionService, ConverterReg
return null;
}
GenericConverter converter = getConverter(sourceType, targetType);
if (converter == null) {
throw new ConverterNotFoundException(sourceType, targetType);
}
try {
return converter.convert(source, sourceType, targetType);
} catch (ConversionFailedException e) {
@ -173,6 +176,9 @@ public class GenericConversionService implements ConversionService, ConverterReg
// subclassing hooks
/**
* Hook to initialize the "generic" converters that require the full TypeDescriptor context to perform their conversion operations.
*/
protected void initGenericConverters() {
addGenericConverter(Object[].class, Object[].class, new ArrayToArrayGenericConverter(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));
}
/**
* 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) {
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) {
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) {
GenericConverter converter = findConverterByClassPair(sourceType.getObjectType(), targetType.getObjectType());
if (converter != null) {
@ -204,7 +235,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
if (sourceType.isAssignableTo(targetType)) {
return NO_OP_CONVERTER;
} else {
throw new ConverterNotFoundException(sourceType, targetType);
return null;
}
}
}

View File

@ -3,6 +3,7 @@ package org.springframework.core.convert.support;
import java.util.Map;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
class MapToMapGenericConverter implements GenericConverter {
@ -95,11 +96,17 @@ class MapToMapGenericConverter implements GenericConverter {
GenericConversionService conversionService) {
if (sourceKeyType != TypeDescriptor.NULL && targetKeyType != TypeDescriptor.NULL && !keysCompatible) {
this.keyConverter = conversionService.getConverter(sourceKeyType, targetKeyType);
if (this.keyConverter == null) {
throw new ConverterNotFoundException(sourceKeyType, targetKeyType);
}
this.sourceKeyType = sourceKeyType;
this.targetKeyType = targetKeyType;
}
if (sourceValueType != TypeDescriptor.NULL && targetValueType != TypeDescriptor.NULL && !valuesCompatible) {
this.valueConverter = conversionService.getConverter(sourceValueType, targetValueType);
if (this.valueConverter == null) {
throw new ConverterNotFoundException(sourceValueType, targetValueType);
}
this.targetKeyType = targetKeyType;
this.targetValueType = targetValueType;
}

View File

@ -17,6 +17,7 @@ package org.springframework.core.convert.support;
import java.lang.reflect.Array;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
class ObjectToArrayGenericConverter implements GenericConverter {
@ -34,6 +35,9 @@ class ObjectToArrayGenericConverter implements GenericConverter {
Array.set(target, 0, source);
} else {
GenericConverter converter = conversionService.getConverter(sourceType, targetElementType);
if (converter == null) {
throw new ConverterNotFoundException(sourceType, targetType);
}
Array.set(target, 0, converter.convert(source, sourceType, targetElementType));
}
return target;

View File

@ -18,6 +18,7 @@ package org.springframework.core.convert.support;
import java.util.Collection;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
class ObjectToCollectionGenericConverter implements GenericConverter {
@ -35,6 +36,9 @@ class ObjectToCollectionGenericConverter implements GenericConverter {
target.add(source);
} else {
GenericConverter converter = conversionService.getConverter(sourceType, targetElementType);
if (converter == null) {
throw new ConverterNotFoundException(sourceType, targetType);
}
target.add(converter.convert(source, sourceType, targetElementType));
}
return target;

View File

@ -19,6 +19,8 @@ package org.springframework.core.convert.support;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
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.ArrayList;
@ -265,6 +267,27 @@ public class GenericConversionServiceTests {
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 {
BAR, BAZ
}