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 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(