FormatterRegistry extends ConverterRegistry now; FormattingConversionService extends GenericConversionService

This commit is contained in:
Juergen Hoeller 2009-11-27 01:58:31 +00:00
parent a1916ca765
commit 7e5106d1ac
6 changed files with 119 additions and 102 deletions

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.format; package org.springframework.format;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
@ -23,9 +24,10 @@ import org.springframework.core.convert.converter.ConverterRegistry;
* A registry of field formatting logic. * A registry of field formatting logic.
* *
* @author Keith Donald * @author Keith Donald
* @author Juergen Hoeller
* @since 3.0 * @since 3.0
*/ */
public interface FormatterRegistry { public interface FormatterRegistry extends ConverterRegistry {
/** /**
* Adds a Formatter to format fields of a specific type. * Adds a Formatter to format fields of a specific type.
@ -57,14 +59,5 @@ public interface FormatterRegistry {
* @param annotationFormatterFactory the annotation formatter factory to add * @param annotationFormatterFactory the annotation formatter factory to add
*/ */
void addFormatterForFieldAnnotation(AnnotationFormatterFactory<? extends Annotation> annotationFormatterFactory); void addFormatterForFieldAnnotation(AnnotationFormatterFactory<? extends Annotation> annotationFormatterFactory);
/**
* Returns the registry of Converters that coerse field values to types required by Formatters.
* Allows clients to register their own custom converters directly.
* For example, a date/time formatting configuration might expect a java.util.Date field value to be coersed to a Long for formatting.
* Registering a simpler DateToLongConverter allievates the need to register multiple formatters for closely related types.
* @return the converter registry, allowing new Converters to be registered
*/
ConverterRegistry getConverterRegistry();
} }

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.format.support; package org.springframework.format.support;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
@ -21,13 +22,13 @@ import java.util.Set;
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.GenericTypeResolver; import org.springframework.core.GenericTypeResolver;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalGenericConverter; import org.springframework.core.convert.converter.ConditionalGenericConverter;
import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.core.convert.converter.GenericConverter; import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.core.convert.support.ConversionServiceFactory; import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.format.AnnotationFormatterFactory; import org.springframework.format.AnnotationFormatterFactory;
import org.springframework.format.Formatter; import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry; import org.springframework.format.FormatterRegistry;
@ -35,29 +36,30 @@ import org.springframework.format.Parser;
import org.springframework.format.Printer; import org.springframework.format.Printer;
/** /**
* A ConversionService implementation designed to be configured as a {@link FormatterRegistry}.. * A {@link org.springframework.core.convert.ConversionService} implementation
* designed to be configured as a {@link FormatterRegistry}.
*
* @author Keith Donald * @author Keith Donald
* @author Juergen Hoeller
* @since 3.0 * @since 3.0
*/ */
public class FormattingConversionService implements FormatterRegistry, ConversionService { public class FormattingConversionService extends GenericConversionService
implements FormatterRegistry {
private ConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
// implementing FormattingRegistry
public void addFormatterForFieldType(Class<?> fieldType, Printer<?> printer, Parser<?> parser) { public void addFormatterForFieldType(Class<?> fieldType, Printer<?> printer, Parser<?> parser) {
getConverterRegistry().addGenericConverter(new PrinterConverter(fieldType, printer, this.conversionService)); addGenericConverter(new PrinterConverter(fieldType, printer, this));
getConverterRegistry().addGenericConverter(new ParserConverter(fieldType, parser, this.conversionService)); addGenericConverter(new ParserConverter(fieldType, parser, this));
} }
public void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter) { public void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter) {
getConverterRegistry().addGenericConverter(new PrinterConverter(fieldType, formatter, this.conversionService)); addGenericConverter(new PrinterConverter(fieldType, formatter, this));
getConverterRegistry().addGenericConverter(new ParserConverter(fieldType, formatter, this.conversionService)); addGenericConverter(new ParserConverter(fieldType, formatter, this));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void addFormatterForFieldAnnotation(final AnnotationFormatterFactory annotationFormatterFactory) { public void addFormatterForFieldAnnotation(final AnnotationFormatterFactory annotationFormatterFactory) {
final Class<? extends Annotation> annotationType = resolveAnnotationType(annotationFormatterFactory); final Class<? extends Annotation> annotationType = (Class<? extends Annotation>)
GenericTypeResolver.resolveTypeArgument(annotationFormatterFactory.getClass(), AnnotationFormatterFactory.class);
if (annotationType == null) { if (annotationType == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Unable to extract parameterized Annotation type argument from AnnotationFormatterFactory [" "Unable to extract parameterized Annotation type argument from AnnotationFormatterFactory ["
@ -65,74 +67,44 @@ public class FormattingConversionService implements FormatterRegistry, Conversio
+ "]; does the factory parameterize the <A extends Annotation> generic type?"); + "]; does the factory parameterize the <A extends Annotation> generic type?");
} }
Set<Class<?>> fieldTypes = annotationFormatterFactory.getFieldTypes(); Set<Class<?>> fieldTypes = annotationFormatterFactory.getFieldTypes();
for (final Class<?> fieldType : fieldTypes) { for (final Class<?> fieldType : fieldTypes) {
getConverterRegistry().addGenericConverter(new ConditionalGenericConverter() { addGenericConverter(new ConditionalGenericConverter() {
public Class<?>[][] getConvertibleTypes() { public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { fieldType, String.class } }; return new Class<?>[][] {{fieldType, String.class}};
} }
public boolean matches(TypeDescriptor sourceFieldType, TypeDescriptor targetFieldType) { public boolean matches(TypeDescriptor sourceFieldType, TypeDescriptor targetFieldType) {
return sourceFieldType.getAnnotation(annotationType) != null; return (sourceFieldType.getAnnotation(annotationType) != null);
} }
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
Printer<?> printer = annotationFormatterFactory.getPrinter(sourceType.getAnnotation(annotationType), sourceType.getType()); Printer<?> printer = annotationFormatterFactory.getPrinter(sourceType.getAnnotation(annotationType), sourceType.getType());
return new PrinterConverter(fieldType, printer, conversionService).convert(source, sourceType, targetType); return new PrinterConverter(fieldType, printer, FormattingConversionService.this).convert(source, sourceType, targetType);
} }
public String toString() { public String toString() {
return "@" + annotationType.getName() + " " + fieldType.getName() + " -> " + String.class.getName() + " : " + annotationFormatterFactory; return "@" + annotationType.getName() + " " + fieldType.getName() + " -> " +
String.class.getName() + ": " + annotationFormatterFactory;
} }
}); });
getConverterRegistry().addGenericConverter(new ConditionalGenericConverter() { addGenericConverter(new ConditionalGenericConverter() {
public Class<?>[][] getConvertibleTypes() { public Class<?>[][] getConvertibleTypes() {
return new Class<?>[][] { { String.class, fieldType } }; return new Class<?>[][] {{String.class, fieldType}};
} }
public boolean matches(TypeDescriptor sourceFieldType, TypeDescriptor targetFieldType) { public boolean matches(TypeDescriptor sourceFieldType, TypeDescriptor targetFieldType) {
return targetFieldType.getAnnotation(annotationType) != null; return (targetFieldType.getAnnotation(annotationType) != null);
} }
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
Parser<?> parser = annotationFormatterFactory.getParser(targetType.getAnnotation(annotationType), targetType.getType()); Parser<?> parser = annotationFormatterFactory.getParser(targetType.getAnnotation(annotationType), targetType.getType());
return new ParserConverter(fieldType, parser, conversionService).convert(source, sourceType, targetType); return new ParserConverter(fieldType, parser, FormattingConversionService.this).convert(source, sourceType, targetType);
} }
public String toString() { public String toString() {
return String.class.getName() + " -> @" + annotationType.getName() + " " + fieldType.getName() + " : " + annotationFormatterFactory; return String.class.getName() + " -> @" + annotationType.getName() + " " +
fieldType.getName() + ": " + annotationFormatterFactory;
} }
}); });
} }
} }
public ConverterRegistry getConverterRegistry() {
return (ConverterRegistry) this.conversionService;
}
// implementing ConverisonService
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
return canConvert(TypeDescriptor.valueOf(sourceType), TypeDescriptor.valueOf(targetType));
}
@SuppressWarnings("unchecked")
public <T> T convert(Object source, Class<T> targetType) {
return (T) convert(source, TypeDescriptor.forObject(source), TypeDescriptor.valueOf(targetType));
}
public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
return this.conversionService.canConvert(sourceType, targetType);
}
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
return this.conversionService.convert(source, sourceType, targetType);
}
public String toString() {
return this.conversionService.toString();
}
// internal helpers
@SuppressWarnings("unchecked")
private Class<? extends Annotation> resolveAnnotationType(AnnotationFormatterFactory<?> annotationFormatterFactory) {
return (Class<? extends Annotation>) GenericTypeResolver.resolveTypeArgument(annotationFormatterFactory.getClass(), AnnotationFormatterFactory.class);
}
private static class PrinterConverter implements GenericConverter { private static class PrinterConverter implements GenericConverter {
private Class<?> fieldType; private Class<?> fieldType;
@ -172,6 +144,7 @@ public class FormattingConversionService implements FormatterRegistry, Conversio
} }
} }
private static class ParserConverter implements GenericConverter { private static class ParserConverter implements GenericConverter {
private Class<?> fieldType; private Class<?> fieldType;
@ -198,22 +171,24 @@ public class FormattingConversionService implements FormatterRegistry, Conversio
Object parsedValue; Object parsedValue;
try { try {
parsedValue = this.parser.parse(submittedValue, LocaleContextHolder.getLocale()); parsedValue = this.parser.parse(submittedValue, LocaleContextHolder.getLocale());
} catch (ParseException e) { }
throw new ConversionFailedException(sourceType, targetType, source, e); catch (ParseException ex) {
throw new ConversionFailedException(sourceType, targetType, source, ex);
} }
TypeDescriptor parsedObjectType = TypeDescriptor.valueOf(parsedValue.getClass()); TypeDescriptor parsedObjectType = TypeDescriptor.valueOf(parsedValue.getClass());
if (!parsedObjectType.isAssignableTo(targetType)) { if (!parsedObjectType.isAssignableTo(targetType)) {
try { try {
parsedValue = this.conversionService.convert(parsedValue, parsedObjectType, targetType); parsedValue = this.conversionService.convert(parsedValue, parsedObjectType, targetType);
} catch (ConversionFailedException e) { }
throw new ConversionFailedException(sourceType, targetType, source, e); catch (ConversionException ex) {
throw new ConversionFailedException(sourceType, targetType, source, ex);
} }
} }
return parsedValue; return parsedValue;
} }
public String toString() { public String toString() {
return String.class.getName() + " -> " + this.fieldType.getName() + " : " + this.parser; return String.class.getName() + " -> " + this.fieldType.getName() + ": " + this.parser;
} }
} }

View File

@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.format.support; package org.springframework.format.support;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.format.FormatterRegistry; import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.joda.JodaTimeFormattingConfigurer; import org.springframework.format.datetime.joda.JodaTimeFormattingConfigurer;
import org.springframework.format.number.NumberFormatAnnotationFormatterFactory; import org.springframework.format.number.NumberFormatAnnotationFormatterFactory;
@ -25,40 +26,47 @@ import org.springframework.format.number.NumberFormatter;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
/** /**
* A factory for a FormattingConversionService that installs default formatters for common types such as numbers and datetimes. * A factory for a {@link FormattingConversionService} that installs default
* Subclasses may override {@link #installFormatters(FormatterRegistry)} to register custom formatters. * formatters for common types such as numbers and datetimes.
*
* <p>Subclasses may override {@link #installFormatters(FormatterRegistry)}
* to register custom formatters.
*
* @author Keith Donald * @author Keith Donald
* @author Juergen Hoeller
* @since 3.0 * @since 3.0
*/ */
public class FormattingConversionServiceFactoryBean implements FactoryBean<ConversionService>, InitializingBean { public class FormattingConversionServiceFactoryBean
implements FactoryBean<FormattingConversionService>, InitializingBean {
private static final boolean jodaTimePresent = ClassUtils.isPresent( private static final boolean jodaTimePresent = ClassUtils.isPresent(
"org.joda.time.DateTime", FormattingConversionService.class.getClassLoader()); "org.joda.time.DateTime", FormattingConversionService.class.getClassLoader());
private FormattingConversionService conversionService; private FormattingConversionService conversionService;
// implementing InitializingBean
public void afterPropertiesSet() { public void afterPropertiesSet() {
this.conversionService = new FormattingConversionService(); this.conversionService = new FormattingConversionService();
ConversionServiceFactory.addDefaultConverters(this.conversionService);
installFormatters(this.conversionService); installFormatters(this.conversionService);
} }
// implementing FactoryBean // implementing FactoryBean
public ConversionService getObject() { public FormattingConversionService getObject() {
return this.conversionService; return this.conversionService;
} }
public Class<ConversionService> getObjectType() { public Class<? extends FormattingConversionService> getObjectType() {
return ConversionService.class; return FormattingConversionService.class;
} }
public boolean isSingleton() { public boolean isSingleton() {
return true; return true;
} }
// subclassing hooks
// subclassing hooks
/** /**
* Install Formatters and Converters into the new FormattingConversionService using the FormatterRegistry SPI. * Install Formatters and Converters into the new FormattingConversionService using the FormatterRegistry SPI.
@ -72,4 +80,4 @@ public class FormattingConversionServiceFactoryBean implements FactoryBean<Conve
} }
} }
} }

View File

@ -1,6 +1,20 @@
package org.springframework.format.datetime.joda; /*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static org.junit.Assert.assertEquals; package org.springframework.format.datetime.joda;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
@ -12,15 +26,22 @@ import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime; import org.joda.time.LocalDateTime;
import org.joda.time.LocalTime; import org.joda.time.LocalTime;
import org.junit.After; import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.MutablePropertyValues;
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO; import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.format.support.FormattingConversionService; import org.springframework.format.support.FormattingConversionService;
import org.springframework.validation.DataBinder; import org.springframework.validation.DataBinder;
/**
* @author Keith Donald
* @author Juergen Hoeller
*/
public class JodaTimeFormattingTests { public class JodaTimeFormattingTests {
private FormattingConversionService conversionService = new FormattingConversionService(); private FormattingConversionService conversionService = new FormattingConversionService();
@ -29,6 +50,8 @@ public class JodaTimeFormattingTests {
@Before @Before
public void setUp() { public void setUp() {
ConversionServiceFactory.addDefaultConverters(conversionService);
JodaTimeFormattingConfigurer configurer = new JodaTimeFormattingConfigurer(); JodaTimeFormattingConfigurer configurer = new JodaTimeFormattingConfigurer();
configurer.installJodaTimeFormatting(conversionService); configurer.installJodaTimeFormatting(conversionService);
@ -81,6 +104,16 @@ public class JodaTimeFormattingTests {
assertEquals("Oct 31, 2009", binder.getBindingResult().getFieldValue("localDateAnnotated")); assertEquals("Oct 31, 2009", binder.getBindingResult().getFieldValue("localDateAnnotated"));
} }
@Test
public void testBindLocalDateAnnotatedWithDirectFieldAccess() {
binder.initDirectFieldAccess();
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("localDateAnnotated", "Oct 31, 2009");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("Oct 31, 2009", binder.getBindingResult().getFieldValue("localDateAnnotated"));
}
@Test @Test
public void testBindLocalTime() { public void testBindLocalTime() {
MutablePropertyValues propertyValues = new MutablePropertyValues(); MutablePropertyValues propertyValues = new MutablePropertyValues();
@ -235,6 +268,7 @@ public class JodaTimeFormattingTests {
assertEquals("2009-10-31T07:00:00.000-05:00", binder.getBindingResult().getFieldValue("isoDateTime")); assertEquals("2009-10-31T07:00:00.000-05:00", binder.getBindingResult().getFieldValue("isoDateTime"));
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static class JodaTimeBean { private static class JodaTimeBean {

View File

@ -16,9 +16,6 @@
package org.springframework.format.support; package org.springframework.format.support;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.text.ParseException; import java.text.ParseException;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
@ -27,11 +24,14 @@ import org.joda.time.DateTime;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormat;
import org.junit.After; import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.format.datetime.joda.DateTimeFormatAnnotationFormatterFactory; import org.springframework.format.datetime.joda.DateTimeFormatAnnotationFormatterFactory;
import org.springframework.format.datetime.joda.DateTimeParser; import org.springframework.format.datetime.joda.DateTimeParser;
import org.springframework.format.datetime.joda.ReadablePartialPrinter; import org.springframework.format.datetime.joda.ReadablePartialPrinter;
@ -48,6 +48,7 @@ public class FormattingConversionServiceTests {
@Before @Before
public void setUp() { public void setUp() {
formattingService = new FormattingConversionService(); formattingService = new FormattingConversionService();
ConversionServiceFactory.addDefaultConverters(formattingService);
LocaleContextHolder.setLocale(Locale.US); LocaleContextHolder.setLocale(Locale.US);
} }
@ -59,15 +60,15 @@ public class FormattingConversionServiceTests {
@Test @Test
public void testFormatFieldForTypeWithFormatter() throws ParseException { public void testFormatFieldForTypeWithFormatter() throws ParseException {
formattingService.addFormatterForFieldType(Number.class, new NumberFormatter()); formattingService.addFormatterForFieldType(Number.class, new NumberFormatter());
String formatted = formattingService.convert(new Integer(3), String.class); String formatted = formattingService.convert(3, String.class);
assertEquals("3", formatted); assertEquals("3", formatted);
Integer i = (Integer) formattingService.convert("3", Integer.class); Integer i = formattingService.convert("3", Integer.class);
assertEquals(new Integer(3), i); assertEquals(new Integer(3), i);
} }
@Test @Test
public void testFormatFieldForTypeWithPrinterParserWithCoersion() throws ParseException { public void testFormatFieldForTypeWithPrinterParserWithCoersion() throws ParseException {
formattingService.getConverterRegistry().addConverter(new Converter<DateTime, LocalDate>() { formattingService.addConverter(new Converter<DateTime, LocalDate>() {
public LocalDate convert(DateTime source) { public LocalDate convert(DateTime source) {
return source.toLocalDate(); return source.toLocalDate();
} }
@ -76,18 +77,18 @@ public class FormattingConversionServiceTests {
.shortDate()), new DateTimeParser(DateTimeFormat.shortDate())); .shortDate()), new DateTimeParser(DateTimeFormat.shortDate()));
String formatted = formattingService.convert(new LocalDate(2009, 10, 31), String.class); String formatted = formattingService.convert(new LocalDate(2009, 10, 31), String.class);
assertEquals("10/31/09", formatted); assertEquals("10/31/09", formatted);
LocalDate date = (LocalDate) formattingService.convert("10/31/09", LocalDate.class); LocalDate date = formattingService.convert("10/31/09", LocalDate.class);
assertEquals(new LocalDate(2009, 10, 31), date); assertEquals(new LocalDate(2009, 10, 31), date);
} }
@Test @Test
public void testFormatFieldForAnnotation() throws Exception { public void testFormatFieldForAnnotation() throws Exception {
formattingService.getConverterRegistry().addConverter(new Converter<Date, Long>() { formattingService.addConverter(new Converter<Date, Long>() {
public Long convert(Date source) { public Long convert(Date source) {
return source.getTime(); return source.getTime();
} }
}); });
formattingService.getConverterRegistry().addConverter(new Converter<DateTime, Date>() { formattingService.addConverter(new Converter<DateTime, Date>() {
public Date convert(DateTime source) { public Date convert(DateTime source) {
return source.toDate(); return source.toDate();
} }

View File

@ -21,21 +21,27 @@ import org.springframework.core.convert.converter.ConverterRegistry;
/** /**
* A factory for creating common ConversionService configurations. * A factory for creating common ConversionService configurations.
*
* @author Keith Donald * @author Keith Donald
* @author Juergen Hoeller
* @since 3.0 * @since 3.0
*/ */
public final class ConversionServiceFactory { public abstract class ConversionServiceFactory {
private ConversionServiceFactory() {
}
/** /**
* Create a new default ConversionService prototype that can be safely modified. * Create a new default ConversionService instance that can be safely modified.
* Callers may cast the returned ConversionService to a {@link ConverterRegistry} to supplement or override the default converters.
*/ */
public static ConversionService createDefaultConversionService() { public static ConversionService createDefaultConversionService() {
GenericConversionService conversionService = new GenericConversionService(); GenericConversionService conversionService = new GenericConversionService();
addDefaultConverters(conversionService);
return conversionService;
}
/**
* Populate the given ConversionService instance with all applicable default converters.
* Callers may cast the returned ConversionService to a {@link ConverterRegistry} to supplement or override the default converters.
*/
public static void addDefaultConverters(GenericConversionService conversionService) {
conversionService.addGenericConverter(new ArrayToArrayConverter(conversionService)); conversionService.addGenericConverter(new ArrayToArrayConverter(conversionService));
conversionService.addGenericConverter(new ArrayToCollectionConverter(conversionService)); conversionService.addGenericConverter(new ArrayToCollectionConverter(conversionService));
conversionService.addGenericConverter(new ArrayToMapConverter(conversionService)); conversionService.addGenericConverter(new ArrayToMapConverter(conversionService));
@ -51,6 +57,7 @@ public final class ConversionServiceFactory {
conversionService.addGenericConverter(new ObjectToArrayConverter(conversionService)); conversionService.addGenericConverter(new ObjectToArrayConverter(conversionService));
conversionService.addGenericConverter(new ObjectToCollectionConverter(conversionService)); conversionService.addGenericConverter(new ObjectToCollectionConverter(conversionService));
conversionService.addGenericConverter(new ObjectToMapConverter(conversionService)); conversionService.addGenericConverter(new ObjectToMapConverter(conversionService));
conversionService.addConverter(new ObjectToStringConverter());
conversionService.addConverter(new StringToBooleanConverter()); conversionService.addConverter(new StringToBooleanConverter());
conversionService.addConverter(new StringToCharacterConverter()); conversionService.addConverter(new StringToCharacterConverter());
conversionService.addConverter(new StringToLocaleConverter()); conversionService.addConverter(new StringToLocaleConverter());
@ -59,9 +66,8 @@ public final class ConversionServiceFactory {
conversionService.addConverterFactory(new StringToEnumConverterFactory()); conversionService.addConverterFactory(new StringToEnumConverterFactory());
conversionService.addConverterFactory(new NumberToNumberConverterFactory()); conversionService.addConverterFactory(new NumberToNumberConverterFactory());
conversionService.addConverterFactory(new CharacterToNumberFactory()); conversionService.addConverterFactory(new CharacterToNumberFactory());
conversionService.addConverter(new ObjectToStringConverter());
conversionService.addGenericConverter(new ObjectToObjectGenericConverter()); conversionService.addGenericConverter(new ObjectToObjectGenericConverter());
conversionService.addGenericConverter(new IdToEntityConverter(conversionService)); conversionService.addGenericConverter(new IdToEntityConverter(conversionService));
return conversionService;
} }
} }