updated formatter conversion service adapter to work with type descriptor

This commit is contained in:
Keith Donald 2009-09-17 19:48:55 +00:00
parent 39c1ab923f
commit 31441627de
4 changed files with 26 additions and 32 deletions

View File

@ -21,9 +21,9 @@ import java.text.ParseException;
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.i18n.LocaleContextHolder;
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.Converter;
import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.GenericConversionService; import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.core.convert.support.GenericConverter;
import org.springframework.ui.format.Formatter; import org.springframework.ui.format.Formatter;
import org.springframework.ui.format.FormatterRegistry; import org.springframework.ui.format.FormatterRegistry;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -40,7 +40,6 @@ public class FormattingConversionServiceAdapter extends GenericConversionService
private final FormatterRegistry formatterRegistry; private final FormatterRegistry formatterRegistry;
/** /**
* Create a new FormattingConversionServiceAdapter for the given FormatterRegistry. * Create a new FormattingConversionServiceAdapter for the given FormatterRegistry.
* @param formatterRegistry the FormatterRegistry to wrap * @param formatterRegistry the FormatterRegistry to wrap
@ -50,28 +49,26 @@ public class FormattingConversionServiceAdapter extends GenericConversionService
this.formatterRegistry = formatterRegistry; this.formatterRegistry = formatterRegistry;
if (formatterRegistry instanceof GenericFormatterRegistry) { if (formatterRegistry instanceof GenericFormatterRegistry) {
setParent(((GenericFormatterRegistry) formatterRegistry).getConversionService()); setParent(((GenericFormatterRegistry) formatterRegistry).getConversionService());
} } else {
else {
setParent(new DefaultConversionService()); setParent(new DefaultConversionService());
} }
} }
@Override @Override
protected Converter findConverter(Class<?> sourceType, TypeDescriptor targetType) { protected GenericConverter getConverter(Class sourceType, TypeDescriptor targetType) {
if (String.class.equals(sourceType)) { if (String.class.equals(sourceType)) {
Formatter formatter = this.formatterRegistry.getFormatter(targetType); Formatter formatter = this.formatterRegistry.getFormatter(targetType);
if (formatter != null) { if (formatter != null) {
return new FormattingConverter(formatter); return new FormattingConverter(formatter);
} }
} }
return super.findConverter(sourceType, targetType); return super.getConverter(sourceType, targetType);
} }
/** /**
* Adapter that exposes the Converter interface on top of a given Formatter. * Adapter that exposes the Converter interface on top of a given Formatter.
*/ */
private static class FormattingConverter implements Converter<String, Object> { private static class FormattingConverter implements GenericConverter {
private final Formatter formatter; private final Formatter formatter;
@ -79,11 +76,10 @@ public class FormattingConversionServiceAdapter extends GenericConversionService
this.formatter = formatter; this.formatter = formatter;
} }
public Object convert(String source) { public Object convert(Object source, TypeDescriptor targetType) {
try { try {
return this.formatter.parse(source, LocaleContextHolder.getLocale()); return this.formatter.parse((String) source, LocaleContextHolder.getLocale());
} } catch (ParseException ex) {
catch (ParseException ex) {
throw new IllegalArgumentException("Could not convert formatted value '" + source + "'", ex); throw new IllegalArgumentException("Could not convert formatted value '" + source + "'", ex);
} }
} }

View File

@ -31,23 +31,24 @@ import org.springframework.core.convert.TypeDescriptor;
class CollectionToCollectionGenericConverter implements GenericConverter { class CollectionToCollectionGenericConverter implements GenericConverter {
private GenericConversionService conversionService; private GenericConversionService conversionService;
public CollectionToCollectionGenericConverter(GenericConversionService conversionService) { public CollectionToCollectionGenericConverter(GenericConversionService conversionService) {
this.conversionService = conversionService; this.conversionService = conversionService;
} }
public Object convert(Object source, TypeDescriptor targetType) { public Object convert(Object source, TypeDescriptor targetType) {
Collection sourceCollection = (Collection) source; Collection sourceCollection = (Collection) source;
Object firstNotNullElement = getFirstNotNullElement(sourceCollection); Object firstNotNullElement = getFirstNotNullElement(sourceCollection);
if (firstNotNullElement == null) { if (firstNotNullElement == null) {
return compatibleCollectionWithoutElementConversion(sourceCollection, targetType); return compatibleCollectionWithoutElementConversion(sourceCollection, targetType);
} }
Class targetElementType = targetType.getElementType(); Class targetElementType = targetType.getElementType();
if (targetElementType == null || targetElementType.isAssignableFrom(firstNotNullElement.getClass())) { if (targetElementType == null || targetElementType.isAssignableFrom(firstNotNullElement.getClass())) {
return compatibleCollectionWithoutElementConversion(sourceCollection, targetType); return compatibleCollectionWithoutElementConversion(sourceCollection, targetType);
} }
Collection targetCollection = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size()); Collection targetCollection = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
GenericConverter elementConverter = conversionService.getConverter(firstNotNullElement.getClass(), targetElementType); GenericConverter elementConverter = conversionService.getConverter(firstNotNullElement.getClass(),
TypeDescriptor.valueOf(targetElementType));
for (Object element : sourceCollection) { for (Object element : sourceCollection) {
targetCollection.add(elementConverter.convert(element, TypeDescriptor.valueOf(targetElementType))); targetCollection.add(elementConverter.convert(element, TypeDescriptor.valueOf(targetElementType)));
} }
@ -65,7 +66,7 @@ class CollectionToCollectionGenericConverter implements GenericConverter {
return target; return target;
} }
} }
private Object getFirstNotNullElement(Collection collection) { private Object getFirstNotNullElement(Collection collection) {
for (Object element : collection) { for (Object element : collection) {
if (element != null) { if (element != null) {
@ -74,5 +75,5 @@ class CollectionToCollectionGenericConverter implements GenericConverter {
} }
return null; return null;
} }
} }

View File

@ -54,10 +54,6 @@ public class GenericConversionService implements ConversionService, ConverterReg
private ConversionService parent; private ConversionService parent;
/**
* An indexed map of Converters. Each Map.Entry key is a source class (S) that can be converted from.
* Each Map.Entry value is a Map that defines the targetType-to-Converter mappings for that source.
*/
private final Map<Class, Map<Class, GenericConverter>> sourceTypeConverters = new HashMap<Class, Map<Class, GenericConverter>>(); private final Map<Class, Map<Class, GenericConverter>> sourceTypeConverters = new HashMap<Class, Map<Class, GenericConverter>>();
public GenericConversionService() { public GenericConversionService() {
@ -143,7 +139,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
} }
Class sourceClass = ClassUtils.resolvePrimitiveIfNecessary(sourceType); Class sourceClass = ClassUtils.resolvePrimitiveIfNecessary(sourceType);
Class targetClass = targetType.getObjectType(); Class targetClass = targetType.getObjectType();
return getConverter(sourceClass, targetType.getObjectType()) != null || this.parent != null return getConverter(sourceClass, targetType) != null || this.parent != null
&& this.parent.canConvert(sourceClass, targetClass); && this.parent.canConvert(sourceClass, targetClass);
} }
@ -161,7 +157,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
return null; return null;
} }
Class sourceType = ClassUtils.resolvePrimitiveIfNecessary(source.getClass()); Class sourceType = ClassUtils.resolvePrimitiveIfNecessary(source.getClass());
GenericConverter converter = getConverter(sourceType, targetType.getObjectType()); GenericConverter converter = getConverter(sourceType, targetType);
if (converter != null) { if (converter != null) {
try { try {
return converter.convert(source, targetType); return converter.convert(source, targetType);
@ -181,7 +177,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
// subclassing hooks // subclassing hooks
protected GenericConverter getConverter(Class<?> sourceType, Class<?> targetType) { protected GenericConverter getConverter(Class sourceType, TypeDescriptor targetType) {
if (sourceType.isInterface()) { if (sourceType.isInterface()) {
LinkedList<Class> classQueue = new LinkedList<Class>(); LinkedList<Class> classQueue = new LinkedList<Class>();
classQueue.addFirst(sourceType); classQueue.addFirst(sourceType);
@ -223,7 +219,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
// internal helpers // internal helpers
private void addGenericConverter(Class<?> sourceType, Class<?> targetType, GenericConverter converter) { private void addGenericConverter(Class sourceType, Class targetType, GenericConverter converter) {
getSourceMap(sourceType).put(targetType, converter); getSourceMap(sourceType).put(targetType, converter);
} }
@ -287,7 +283,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
return sourceMap; return sourceMap;
} }
private Map<Class, GenericConverter> getConvertersForSource(Class<?> sourceType) { private Map<Class, GenericConverter> getConvertersForSource(Class sourceType) {
Map<Class, GenericConverter> converters = this.sourceTypeConverters.get(sourceType); Map<Class, GenericConverter> converters = this.sourceTypeConverters.get(sourceType);
if (converters == null) { if (converters == null) {
converters = Collections.emptyMap(); converters = Collections.emptyMap();
@ -295,10 +291,11 @@ public class GenericConversionService implements ConversionService, ConverterReg
return converters; return converters;
} }
private GenericConverter getConverter(Map<Class, GenericConverter> converters, Class<?> targetType) { private GenericConverter getConverter(Map<Class, GenericConverter> converters, TypeDescriptor targetType) {
if (targetType.isInterface()) { Class targetClass = targetType.getObjectType();
if (targetClass.isInterface()) {
LinkedList<Class> classQueue = new LinkedList<Class>(); LinkedList<Class> classQueue = new LinkedList<Class>();
classQueue.addFirst(targetType); classQueue.addFirst(targetClass);
while (!classQueue.isEmpty()) { while (!classQueue.isEmpty()) {
Class currentClass = classQueue.removeLast(); Class currentClass = classQueue.removeLast();
GenericConverter converter = converters.get(currentClass); GenericConverter converter = converters.get(currentClass);
@ -313,7 +310,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
return converters.get(Object.class); return converters.get(Object.class);
} else { } else {
LinkedList<Class> classQueue = new LinkedList<Class>(); LinkedList<Class> classQueue = new LinkedList<Class>();
classQueue.addFirst(targetType); classQueue.addFirst(targetClass);
while (!classQueue.isEmpty()) { while (!classQueue.isEmpty()) {
Class currentClass = classQueue.removeLast(); Class currentClass = classQueue.removeLast();
GenericConverter converter = converters.get(currentClass); GenericConverter converter = converters.get(currentClass);

View File

@ -2,7 +2,7 @@ package org.springframework.core.convert.support;
import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.TypeDescriptor;
interface GenericConverter { public interface GenericConverter {
Object convert(Object source, TypeDescriptor type); Object convert(Object source, TypeDescriptor type);