diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterRegistry.java b/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterRegistry.java index 943acaae9c0..a2e0da852ce 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterRegistry.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterRegistry.java @@ -27,16 +27,28 @@ public interface ConverterRegistry { /** * Add a plain converter to this registry. + * The convertible sourceType/targetType pair is derived from the Converter's parameterized types. + * @throws IllegalArgumentException if the parameterized types could not be resolved */ void addConverter(Converter converter); + /** + * Add a plain converter to this registry. + * The convertible sourceType/targetType pair is specified explicitly. + * Allows for a Converter to be reused for multiple distinct pairs without having to create a Converter class for each pair. + * @since 3.1 + */ + void addConverter(Class sourceType, Class targetType, Converter converter); + /** * Add a generic converter to this registry. */ void addConverter(GenericConverter converter); - + /** * Add a ranged converter factory to this registry. + * The convertible sourceType/rangeType pair is derived from the ConverterFactory's parameterized types. + * @throws IllegalArgumentException if the parameterized types could not be resolved. */ void addConverterFactory(ConverterFactory converterFactory); diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionServiceFactory.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionServiceFactory.java index c397ab55ba9..3772d529965 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionServiceFactory.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionServiceFactory.java @@ -61,8 +61,7 @@ public abstract class ConversionServiceFactory { } /** - * Create a new default ConversionService instance that can be safely modified. - * + * Create a new default GenericConversionService instance that can be safely modified. * @deprecated in Spring 3.1 in favor of {@link DefaultConversionService#DefaultConversionService()} */ public static GenericConversionService createDefaultConversionService() { @@ -70,9 +69,8 @@ public abstract class ConversionServiceFactory { } /** - * Populate the given ConversionService instance with all applicable default converters. - * - * @deprecated in Spring 3.1 in favor of {@link DefaultConversionService#addDefaultConverters} + * Populate the given GenericConversionService instance with the set of default converters. + * @deprecated in Spring 3.1 in favor of {@link DefaultConversionService#addDefaultConverters(ConverterRegistry)} */ public static void addDefaultConverters(GenericConversionService conversionService) { DefaultConversionService.addDefaultConverters(conversionService); diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultConversionService.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultConversionService.java index 85d6c4542a7..377f1f7deb9 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultConversionService.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultConversionService.java @@ -18,13 +18,16 @@ package org.springframework.core.convert.support; import java.util.Locale; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.converter.ConverterRegistry; + /** * A specialization of {@link GenericConversionService} configured by default with - * converters appropriate for most applications. + * converters appropriate for most environments. * *

Designed for direct instantiation but also exposes the static - * {@link #addDefaultConverters} utility method for ad hoc use against any - * {@code GenericConversionService} instance. + * {@link #addDefaultConverters(ConverterRegistry)} utility method for ad hoc use against any + * {@code ConverterRegistry} instance. * * @author Chris Beams * @since 3.1 @@ -33,62 +36,79 @@ public class DefaultConversionService extends GenericConversionService { /** * Create a new {@code DefaultConversionService} with the set of - * {@linkplain DefaultConversionService#addDefaultConverters default converters}. + * {@linkplain DefaultConversionService#addDefaultConverters(ConverterRegistry) default converters}. */ public DefaultConversionService() { addDefaultConverters(this); } + // static utility methods + /** * Add converters appropriate for most environments. - * @param conversionService the service to register default formatters against + * @param converterRegistry the registry of converters to add to (must also be castable to ConversionService) + * @throws ClassCastException if the converterRegistry could not be cast to a ConversionService */ - public static void addDefaultConverters(GenericConversionService conversionService) { - conversionService.addConverter(new ArrayToCollectionConverter(conversionService)); - conversionService.addConverter(new CollectionToArrayConverter(conversionService)); + public static void addDefaultConverters(ConverterRegistry converterRegistry) { + addScalarConverters(converterRegistry); + addCollectionConverters(converterRegistry); + addFallbackConverters(converterRegistry); + } + + // internal helpers + + private static void addScalarConverters(ConverterRegistry converterRegistry) { + converterRegistry.addConverter(new StringToBooleanConverter()); + converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter()); - conversionService.addConverter(new ArrayToStringConverter(conversionService)); - conversionService.addConverter(new StringToArrayConverter(conversionService)); + converterRegistry.addConverterFactory(new StringToNumberConverterFactory()); + converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter()); - conversionService.addConverter(new ArrayToObjectConverter(conversionService)); - conversionService.addConverter(new ObjectToArrayConverter(conversionService)); - - conversionService.addConverter(new CollectionToStringConverter(conversionService)); - conversionService.addConverter(new StringToCollectionConverter(conversionService)); - - conversionService.addConverter(new CollectionToObjectConverter(conversionService)); - conversionService.addConverter(new ObjectToCollectionConverter(conversionService)); - - conversionService.addConverter(new ArrayToArrayConverter(conversionService)); - conversionService.addConverter(new CollectionToCollectionConverter(conversionService)); - conversionService.addConverter(new MapToMapConverter(conversionService)); - - conversionService.addConverter(new PropertiesToStringConverter()); - conversionService.addConverter(new StringToPropertiesConverter()); - - conversionService.addConverter(new StringToBooleanConverter()); - conversionService.addConverter(Boolean.class, String.class, new ObjectToStringConverter()); - - conversionService.addConverter(new StringToCharacterConverter()); - conversionService.addConverter(Character.class, String.class, new ObjectToStringConverter()); - - conversionService.addConverter(new StringToLocaleConverter()); - conversionService.addConverter(Locale.class, String.class, new ObjectToStringConverter()); + converterRegistry.addConverterFactory(new NumberToNumberConverterFactory()); - conversionService.addConverterFactory(new StringToNumberConverterFactory()); - conversionService.addConverter(Number.class, String.class, new ObjectToStringConverter()); - - conversionService.addConverterFactory(new StringToEnumConverterFactory()); - conversionService.addConverter(Enum.class, String.class, new EnumToStringConverter()); - - conversionService.addConverter(new NumberToCharacterConverter()); - conversionService.addConverterFactory(new CharacterToNumberFactory()); + converterRegistry.addConverter(new StringToCharacterConverter()); + converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter()); - conversionService.addConverterFactory(new NumberToNumberConverterFactory()); + converterRegistry.addConverter(new NumberToCharacterConverter()); + converterRegistry.addConverterFactory(new CharacterToNumberFactory()); + + converterRegistry.addConverterFactory(new StringToEnumConverterFactory()); + converterRegistry.addConverter(Enum.class, String.class, new EnumToStringConverter()); + + converterRegistry.addConverter(new StringToLocaleConverter()); + converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter()); - conversionService.addConverter(new ObjectToObjectConverter()); - conversionService.addConverter(new IdToEntityConverter(conversionService)); - conversionService.addConverter(new FallbackObjectToStringConverter()); + converterRegistry.addConverter(new PropertiesToStringConverter()); + converterRegistry.addConverter(new StringToPropertiesConverter()); } -} + private static void addCollectionConverters(ConverterRegistry converterRegistry) { + ConversionService conversionService = (ConversionService) converterRegistry; + converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService)); + converterRegistry.addConverter(new CollectionToArrayConverter(conversionService)); + + converterRegistry.addConverter(new ArrayToArrayConverter(conversionService)); + converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService)); + converterRegistry.addConverter(new MapToMapConverter(conversionService)); + + converterRegistry.addConverter(new ArrayToStringConverter(conversionService)); + converterRegistry.addConverter(new StringToArrayConverter(conversionService)); + + converterRegistry.addConverter(new ArrayToObjectConverter(conversionService)); + converterRegistry.addConverter(new ObjectToArrayConverter(conversionService)); + + converterRegistry.addConverter(new CollectionToStringConverter(conversionService)); + converterRegistry.addConverter(new StringToCollectionConverter(conversionService)); + + converterRegistry.addConverter(new CollectionToObjectConverter(conversionService)); + converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService)); + } + + private static void addFallbackConverters(ConverterRegistry converterRegistry) { + ConversionService conversionService = (ConversionService) converterRegistry; + converterRegistry.addConverter(new ObjectToObjectConverter()); + converterRegistry.addConverter(new IdToEntityConverter(conversionService)); + converterRegistry.addConverter(new FallbackObjectToStringConverter()); + } + +} \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java index f83372ed8a9..0b8616d887c 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java @@ -88,17 +88,6 @@ public class GenericConversionService implements ConversionService, ConverterReg new ConcurrentHashMap(); - /** - * Add a converter to the register indexed under the explicit source and target types. - * Allows for a general converter to be reused for multiple distinct source-to-target convertible pairs without having to create a Converter class for each pair. - * Not yet part of the ConverterRegistry interface. - * @since 3.1 - */ - public void addConverter(Class sourceType, Class targetType, Converter converter) { - GenericConverter.ConvertiblePair typeInfo = new GenericConverter.ConvertiblePair(sourceType, targetType); - addConverter(new ConverterAdapter(typeInfo, converter)); - } - // implementing ConverterRegistry public void addConverter(Converter converter) { @@ -110,13 +99,9 @@ public class GenericConversionService implements ConversionService, ConverterReg addConverter(new ConverterAdapter(typeInfo, converter)); } - public void addConverterFactory(ConverterFactory converterFactory) { - GenericConverter.ConvertiblePair typeInfo = getRequiredTypeInfo(converterFactory, ConverterFactory.class); - if (typeInfo == null) { - throw new IllegalArgumentException("Unable to the determine sourceType and targetRangeType R which " + - "your ConverterFactory converts between; declare these generic types."); - } - addConverter(new ConverterFactoryAdapter(typeInfo, converterFactory)); + public void addConverter(Class sourceType, Class targetType, Converter converter) { + GenericConverter.ConvertiblePair typeInfo = new GenericConverter.ConvertiblePair(sourceType, targetType); + addConverter(new ConverterAdapter(typeInfo, converter)); } public void addConverter(GenericConverter converter) { @@ -127,6 +112,15 @@ public class GenericConversionService implements ConversionService, ConverterReg invalidateCache(); } + public void addConverterFactory(ConverterFactory converterFactory) { + GenericConverter.ConvertiblePair typeInfo = getRequiredTypeInfo(converterFactory, ConverterFactory.class); + if (typeInfo == null) { + throw new IllegalArgumentException("Unable to the determine sourceType and targetRangeType R which " + + "your ConverterFactory converts between; declare these generic types."); + } + addConverter(new ConverterFactoryAdapter(typeInfo, converterFactory)); + } + public void removeConvertible(Class sourceType, Class targetType) { getSourceConverterMap(sourceType).remove(targetType); invalidateCache(); diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/IdToEntityConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/IdToEntityConverter.java index fdcbac5037c..af97f7083f1 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/IdToEntityConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/IdToEntityConverter.java @@ -21,6 +21,7 @@ import java.lang.reflect.Modifier; import java.util.Collections; import java.util.Set; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; import org.springframework.util.ClassUtils; @@ -38,9 +39,9 @@ import org.springframework.util.ReflectionUtils; */ final class IdToEntityConverter implements ConditionalGenericConverter { - private final GenericConversionService conversionService; + private final ConversionService conversionService; - public IdToEntityConverter(GenericConversionService conversionService) { + public IdToEntityConverter(ConversionService conversionService) { this.conversionService = conversionService; } @@ -56,7 +57,7 @@ final class IdToEntityConverter implements ConditionalGenericConverter { public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { - return this.conversionService.convertNullSource(sourceType, targetType); + return null; } Method finder = getFinder(targetType.getType()); Object id = this.conversionService.convert(