revised GenericConverter's "getConvertibleTypes()" signature to return Set of ConvertiblePair

This commit is contained in:
Juergen Hoeller 2009-12-09 17:52:19 +00:00
parent 010e72c35a
commit bc6b707a22
20 changed files with 217 additions and 108 deletions

View File

@ -16,19 +16,26 @@
package org.springframework.core.convert.converter;
import java.util.Set;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.util.Assert;
/**
* Generic converter interface for converting between two or more types.
* <p>
* This is the most flexible of the Converter SPI interfaces, but also the most complex.
* It is flexible in that a GenericConverter may support converting between multiple source/target type pairs (see {@link #getConvertibleTypes()}.
* In addition, GenericConverter implementations have access to source/target {@link TypeDescriptor field context} during the type conversion process.
* This allows for resolving source and target field metadata such as annotations and generics information, which can be used influence the conversion logic.
* <p>
* This interface should generally not be used when the simpler {@link Converter} or {@link ConverterFactory} interfaces are sufficient.
*
* <p>This is the most flexible of the Converter SPI interfaces, but also the most complex.
* It is flexible in that a GenericConverter may support converting between multiple source/target
* type pairs (see {@link #getConvertibleTypes()}. In addition, GenericConverter implementations
* have access to source/target {@link TypeDescriptor field context} during the type conversion process.
* This allows for resolving source and target field metadata such as annotations and generics
* information, which can be used influence the conversion logic.
*
* <p>This interface should generally not be used when the simpler {@link Converter} or
* {@link ConverterFactory} interfaces are sufficient.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
* @see TypeDescriptor
* @see Converter
@ -37,11 +44,10 @@ import org.springframework.core.convert.TypeDescriptor;
public interface GenericConverter {
/**
* The source and target types this converter can convert between.
* Each entry in the returned array is a convertible source-to-target type pair, also expressed as an array.
* For each pair, the first array element is a sourceType that can be converted from, and the second array element is a targetType that can be converted to.
* Return the source and target types which this converter can convert between.
* <p>Each entry is a convertible source-to-target type pair.
*/
public Class<?>[][] getConvertibleTypes();
Set<ConvertiblePair> getConvertibleTypes();
/**
* Convert the source to the targetType described by the TypeDescriptor.
@ -52,4 +58,35 @@ public interface GenericConverter {
*/
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
/**
* Holder for a source-to-target class pair.
*/
public static final class ConvertiblePair {
private final Class<?> sourceType;
private final Class<?> targetType;
/**
* Create a new source-to-target pair.
* @param sourceType the source type
* @param targetType the target type
*/
public ConvertiblePair(Class<?> sourceType, Class<?> targetType) {
Assert.notNull(sourceType, "Source type must not be null");
Assert.notNull(targetType, "Target type must not be null");
this.sourceType = sourceType;
this.targetType = targetType;
}
public Class<?> getSourceType() {
return this.sourceType;
}
public Class<?> getTargetType() {
return this.targetType;
}
}
}

View File

@ -17,6 +17,8 @@
package org.springframework.core.convert.support;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
@ -35,9 +37,9 @@ final class ArrayToArrayConverter implements GenericConverter {
public ArrayToArrayConverter(GenericConversionService conversionService) {
this.helperConverter = new CollectionToArrayConverter(conversionService);
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Object[].class, Object[].class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Object[].class, Object[].class));
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {

View File

@ -16,15 +16,16 @@
package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import static org.springframework.core.convert.support.ConversionUtils.*;
/**
* Converts from an array to a collection.
@ -40,8 +41,8 @@ final class ArrayToCollectionConverter implements GenericConverter {
this.conversionService = conversionService;
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Object[].class, Collection.class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Object[].class, Collection.class));
}
@SuppressWarnings("unchecked")

View File

@ -17,7 +17,9 @@
package org.springframework.core.convert.support;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
@ -37,8 +39,8 @@ final class ArrayToMapConverter implements GenericConverter {
this.helperConverter = new CollectionToMapConverter(conversionService);
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Object[].class, Map.class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Object[].class, Map.class));
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {

View File

@ -17,6 +17,8 @@
package org.springframework.core.convert.support;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
@ -36,8 +38,8 @@ final class ArrayToObjectConverter implements GenericConverter {
this.helperConverter = new CollectionToObjectConverter(conversionService);
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] {{Object[].class, Object.class}};
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Object[].class, Object.class));
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {

View File

@ -16,16 +16,16 @@
package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.getElementType;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import static org.springframework.core.convert.support.ConversionUtils.*;
/**
* Converts from a Collection to an array.
@ -41,8 +41,8 @@ final class CollectionToArrayConverter implements GenericConverter {
this.conversionService = conversionService;
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Collection.class, Object[].class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Collection.class, Object[].class));
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {

View File

@ -16,15 +16,15 @@
package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.getElementType;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import static org.springframework.core.convert.support.ConversionUtils.*;
/**
* Converts from a source Collection to target Collection type.
@ -40,8 +40,8 @@ final class CollectionToCollectionConverter implements GenericConverter {
this.conversionService = conversionService;
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Collection.class, Collection.class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Collection.class, Collection.class));
}
@SuppressWarnings("unchecked")

View File

@ -16,14 +16,15 @@
package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.getElementType;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import static org.springframework.core.convert.support.ConversionUtils.*;
/**
* Converts from a Collection to a Map.
@ -39,8 +40,8 @@ final class CollectionToMapConverter implements GenericConverter {
this.conversionService = conversionService;
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Collection.class, Map.class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Collection.class, Map.class));
}
@SuppressWarnings("unchecked")

View File

@ -16,14 +16,14 @@
package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.getElementType;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import static org.springframework.core.convert.support.ConversionUtils.*;
/**
* Converts from a Collection to a single Object.
@ -41,8 +41,8 @@ final class CollectionToObjectConverter implements GenericConverter {
this.conversionService = conversionService;
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Collection.class, Object.class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Collection.class, Object.class));
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {

View File

@ -16,9 +16,16 @@
package org.springframework.core.convert.support;
import java.util.Set;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.core.convert.converter.GenericConverter;
/**
* A factory for common ConversionService configurations.
* A factory for common {@link org.springframework.core.convert.ConversionService}
* configurations.
*
* @author Keith Donald
* @author Juergen Hoeller
@ -67,4 +74,30 @@ public abstract class ConversionServiceFactory {
conversionService.addGenericConverter(new IdToEntityConverter(conversionService));
}
/**
* Register the given converter objects with the given target registry.
* @param converters the converter objects: implementing {@link Converter},
* {@link ConverterFactory}, or {@link GenericConverter}
* @param registry the target registry to register with
*/
public static void registerConverters(Set<Object> converters, ConverterRegistry registry) {
if (converters != null) {
for (Object converter : converters) {
if (converter instanceof Converter<?, ?>) {
registry.addConverter((Converter<?, ?>) converter);
}
else if (converter instanceof ConverterFactory<?, ?>) {
registry.addConverterFactory((ConverterFactory<?, ?>) converter);
}
else if (converter instanceof GenericConverter) {
registry.addGenericConverter((GenericConverter) converter);
}
else {
throw new IllegalArgumentException("Each converter object must implement one of the " +
"Converter, ConverterFactory, or GenericConverter interfaces");
}
}
}
}
}

View File

@ -24,6 +24,7 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -55,7 +56,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
private static final Log logger = LogFactory.getLog(GenericConversionService.class);
private static final GenericConverter NO_OP_CONVERTER = new GenericConverter() {
public Class<?>[][] getConvertibleTypes() {
public Set<ConvertiblePair> getConvertibleTypes() {
return null;
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
@ -71,7 +72,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
// implementing ConverterRegistry
public void addConverter(Converter<?, ?> converter) {
Class<?>[] typeInfo = getRequiredTypeInfo(converter, Converter.class);
GenericConverter.ConvertiblePair typeInfo = getRequiredTypeInfo(converter, Converter.class);
if (typeInfo == null) {
throw new IllegalArgumentException("Unable to the determine sourceType <S> and targetType <T> which " +
"your Converter<S, T> converts between; declare these generic types.");
@ -80,7 +81,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
}
public void addConverterFactory(ConverterFactory<?, ?> converterFactory) {
Class<?>[] typeInfo = getRequiredTypeInfo(converterFactory, ConverterFactory.class);
GenericConverter.ConvertiblePair typeInfo = getRequiredTypeInfo(converterFactory, ConverterFactory.class);
if (typeInfo == null) {
throw new IllegalArgumentException("Unable to the determine sourceType <S> and targetRangeType R which " +
"your ConverterFactory<S, R> converts between; declare these generic types.");
@ -89,9 +90,9 @@ public class GenericConversionService implements ConversionService, ConverterReg
}
public void addGenericConverter(GenericConverter converter) {
Class<?>[][] convertibleTypes = converter.getConvertibleTypes();
for (Class<?>[] convertibleType : convertibleTypes) {
getMatchableConvertersList(convertibleType[0], convertibleType[1]).add(converter);
Set<GenericConverter.ConvertiblePair> convertibleTypes = converter.getConvertibleTypes();
for (GenericConverter.ConvertiblePair convertibleType : convertibleTypes) {
getMatchableConvertersList(convertibleType.getSourceType(), convertibleType.getTargetType()).add(converter);
}
}
@ -213,8 +214,9 @@ public class GenericConversionService implements ConversionService, ConverterReg
// internal helpers
private Class<?>[] getRequiredTypeInfo(Object converter, Class<?> genericIfc) {
return GenericTypeResolver.resolveTypeArguments(converter.getClass(), genericIfc);
private GenericConverter.ConvertiblePair getRequiredTypeInfo(Object converter, Class<?> genericIfc) {
Class[] args = GenericTypeResolver.resolveTypeArguments(converter.getClass(), genericIfc);
return (args != null ? new GenericConverter.ConvertiblePair(args[0], args[1]) : null);
}
private MatchableConverters getMatchableConvertersList(Class<?> sourceType, Class<?> targetType) {
@ -370,17 +372,17 @@ public class GenericConversionService implements ConversionService, ConverterReg
@SuppressWarnings("unchecked")
private final class ConverterAdapter implements GenericConverter {
private final Class<?>[] typeInfo;
private final ConvertiblePair typeInfo;
private final Converter converter;
public ConverterAdapter(Class<?>[] typeInfo, Converter<?, ?> converter) {
public ConverterAdapter(ConvertiblePair typeInfo, Converter<?, ?> converter) {
this.converter = converter;
this.typeInfo = typeInfo;
}
public Class<?>[][] getConvertibleTypes() {
return new Class[][] {this.typeInfo};
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(this.typeInfo);
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
@ -391,7 +393,8 @@ public class GenericConversionService implements ConversionService, ConverterReg
}
public String toString() {
return this.typeInfo[0].getName() + " -> " + this.typeInfo[1].getName() + " : " + this.converter.toString();
return this.typeInfo.getSourceType().getName() + " -> " + this.typeInfo.getTargetType().getName() +
" : " + this.converter.toString();
}
}
@ -399,17 +402,17 @@ public class GenericConversionService implements ConversionService, ConverterReg
@SuppressWarnings("unchecked")
private final class ConverterFactoryAdapter implements GenericConverter {
private final Class<?>[] typeInfo;
private final ConvertiblePair typeInfo;
private final ConverterFactory converterFactory;
public ConverterFactoryAdapter(Class<?>[] typeInfo, ConverterFactory<?, ?> converterFactory) {
public ConverterFactoryAdapter(ConvertiblePair typeInfo, ConverterFactory<?, ?> converterFactory) {
this.converterFactory = converterFactory;
this.typeInfo = typeInfo;
}
public Class<?>[][] getConvertibleTypes() {
return new Class[][] {this.typeInfo};
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(this.typeInfo);
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
@ -420,8 +423,8 @@ public class GenericConversionService implements ConversionService, ConverterReg
}
public String toString() {
return this.typeInfo[0].getName() + " -> " + this.typeInfo[1].getName() + " : " +
this.converterFactory.toString();
return this.typeInfo.getSourceType().getName() + " -> " + this.typeInfo.getTargetType().getName() +
" : " + this.converterFactory.toString();
}
}

View File

@ -13,10 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.convert.support;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.Set;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalGenericConverter;
@ -24,8 +27,12 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* Converts an entity identifier to a entity reference by calling a static finder method on the target entity type.
* For this converter to match, the finder method must be public, static, have the signature 'find[EntityName]([IdType])', and return an instance of the desired entity type.
* Converts an entity identifier to a entity reference by calling a static finder method
* on the target entity type.
*
* <p>For this converter to match, the finder method must be public, static, have the signature
* <code>find[EntityName]([IdType])</code>, and return an instance of the desired entity type.
*
* @author Keith Donald
* @since 3.0
*/
@ -37,8 +44,8 @@ final class IdToEntityConverter implements ConditionalGenericConverter {
this.conversionService = conversionService;
}
public Class<?>[][] getConvertibleTypes() {
return new Class[][] { { Object.class, Object.class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
}
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {

View File

@ -16,8 +16,10 @@
package org.springframework.core.convert.support;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
@ -39,8 +41,8 @@ final class MapToArrayConverter implements GenericConverter {
this.collectionToArrayHelperConverter = new CollectionToArrayConverter(conversionService);
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Map.class, Object[].class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Map.class, Object[].class));
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {

View File

@ -16,14 +16,15 @@
package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.getMapEntryTypes;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import static org.springframework.core.convert.support.ConversionUtils.*;
/**
* Converts from a Map to a Collection.
@ -39,8 +40,8 @@ final class MapToCollectionConverter implements GenericConverter {
this.conversionService = conversionService;
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Map.class, Collection.class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Map.class, Collection.class));
}
@SuppressWarnings("unchecked")

View File

@ -16,13 +16,14 @@
package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.getMapEntryTypes;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import static org.springframework.core.convert.support.ConversionUtils.*;
/**
* Converts from a source Map to a target Map type.
@ -38,8 +39,8 @@ final class MapToMapConverter implements GenericConverter {
this.conversionService = conversionService;
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Map.class, Map.class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Map.class, Map.class));
}
@SuppressWarnings("unchecked")

View File

@ -16,15 +16,16 @@
package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.getMapEntryTypes;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import static org.springframework.core.convert.support.ConversionUtils.*;
/**
* Converts from a Map to a single Object.
@ -40,8 +41,8 @@ final class MapToObjectConverter implements GenericConverter {
this.conversionService = conversionService;
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Map.class, Object.class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Map.class, Object.class));
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {

View File

@ -16,13 +16,14 @@
package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.lang.reflect.Array;
import java.util.Collections;
import java.util.Set;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import static org.springframework.core.convert.support.ConversionUtils.*;
import org.springframework.util.StringUtils;
/**
@ -39,8 +40,8 @@ final class ObjectToArrayConverter implements GenericConverter {
this.conversionService = conversionService;
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Object.class, Object[].class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Object.class, Object[].class));
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {

View File

@ -16,14 +16,15 @@
package org.springframework.core.convert.support;
import static org.springframework.core.convert.support.ConversionUtils.invokeConverter;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import static org.springframework.core.convert.support.ConversionUtils.*;
import org.springframework.util.StringUtils;
/**
@ -40,8 +41,8 @@ final class ObjectToCollectionConverter implements GenericConverter {
this.conversionService = conversionService;
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Object.class, Collection.class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Object.class, Collection.class));
}
@SuppressWarnings("unchecked")

View File

@ -17,8 +17,10 @@
package org.springframework.core.convert.support;
import java.io.ByteArrayInputStream;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.TypeDescriptor;
@ -38,8 +40,8 @@ final class ObjectToMapConverter implements GenericConverter {
this.conversionService = conversionService;
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Object.class, Map.class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Object.class, Map.class));
}
@SuppressWarnings("unchecked")

View File

@ -19,6 +19,8 @@ package org.springframework.core.convert.support;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Set;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.TypeDescriptor;
@ -27,9 +29,12 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* Generic Converter that attempts to convert a source Object to a targetType by delegating to methods on the targetType.
* Calls the static valueOf(sourceType) method on the targetType to perform the conversion, if such a method exists.
* Else calls the targetType's Constructor that accepts a single sourceType argument, if such a Constructor exists.
* Generic Converter that attempts to convert a source Object to a target type
* by delegating to methods on the target type.
*
* <p>Calls the static <code>valueOf(sourceType)</code> method on the target type
* to perform the conversion, if such a method exists. Else calls the target type's
* Constructor that accepts a single sourceType argument, if such a Constructor exists.
* Else throws a ConversionFailedException.
*
* @author Keith Donald
@ -40,11 +45,12 @@ final class ObjectToObjectGenericConverter implements ConditionalGenericConverte
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
Class<?> sourceClass = sourceType.getObjectType();
Class<?> targetClass = targetType.getObjectType();
return getValueOfMethodOn(targetClass, sourceClass) != null || getConstructor(targetClass, sourceClass) != null;
return getValueOfMethodOn(targetClass, sourceClass) != null ||
getConstructor(targetClass, sourceClass) != null;
}
public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { Object.class, Object.class } };
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
@ -57,23 +63,29 @@ final class ObjectToObjectGenericConverter implements ConditionalGenericConverte
Method method = getValueOfMethodOn(targetClass, sourceClass);
if (method != null) {
target = ReflectionUtils.invokeMethod(method, null, source);
} else {
}
else {
Constructor<?> constructor = getConstructor(targetClass, sourceClass);
if (constructor != null) {
try {
target = constructor.newInstance(source);
} catch (IllegalArgumentException e) {
throw new ConversionFailedException(sourceType, targetType, source, e);
} catch (InstantiationException e) {
throw new ConversionFailedException(sourceType, targetType, source, e);
} catch (IllegalAccessException e) {
throw new ConversionFailedException(sourceType, targetType, source, e);
} catch (InvocationTargetException e) {
throw new ConversionFailedException(sourceType, targetType, source, e);
}
} else {
throw new IllegalStateException("No static valueOf(" + sourceClass.getName()
+ ") method or Constructor(" + sourceClass.getName() + ") exists on " + targetClass.getName());
catch (IllegalArgumentException ex) {
throw new ConversionFailedException(sourceType, targetType, source, ex);
}
catch (InstantiationException ex) {
throw new ConversionFailedException(sourceType, targetType, source, ex);
}
catch (IllegalAccessException ex) {
throw new ConversionFailedException(sourceType, targetType, source, ex);
}
catch (InvocationTargetException ex) {
throw new ConversionFailedException(sourceType, targetType, source, ex);
}
}
else {
throw new IllegalStateException("No static valueOf(" + sourceClass.getName() +
") method or Constructor(" + sourceClass.getName() + ") exists on " + targetClass.getName());
}
}
return target;
@ -87,4 +99,4 @@ final class ObjectToObjectGenericConverter implements ConditionalGenericConverte
return ClassUtils.getConstructorIfAvailable(targetClass, sourceClass);
}
}
}