improved conversion system logging, collection converter simplification/polish, several optimizations, annotation-driven formatting caching
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@3255 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
efc8a513d1
commit
eca3e5d0b8
|
|
@ -17,12 +17,14 @@
|
|||
package org.springframework.format.support;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
|
|
@ -66,6 +68,9 @@ public class FormattingConversionService extends GenericConversionService implem
|
|||
}
|
||||
Set<Class<?>> fieldTypes = annotationFormatterFactory.getFieldTypes();
|
||||
|
||||
final Map<FieldFormatterKey, GenericConverter> cachedPrinters = new ConcurrentHashMap<FieldFormatterKey, GenericConverter>();
|
||||
final Map<FieldFormatterKey, GenericConverter> cachedParsers = new ConcurrentHashMap<FieldFormatterKey, GenericConverter>();
|
||||
|
||||
for (final Class<?> fieldType : fieldTypes) {
|
||||
addConverter(new ConditionalGenericConverter() {
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
|
|
@ -75,8 +80,14 @@ public class FormattingConversionService extends GenericConversionService implem
|
|||
return (sourceType.getAnnotation(annotationType) != null);
|
||||
}
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
Printer<?> printer = annotationFormatterFactory.getPrinter(sourceType.getAnnotation(annotationType), sourceType.getType());
|
||||
return new PrinterConverter(fieldType, printer, FormattingConversionService.this).convert(source, sourceType, targetType);
|
||||
FieldFormatterKey key = new FieldFormatterKey(sourceType.getAnnotation(annotationType), fieldType);
|
||||
GenericConverter converter = cachedPrinters.get(key);
|
||||
if (converter == null) {
|
||||
Printer<?> printer = annotationFormatterFactory.getPrinter(key.getAnnotation(), key.getFieldType());
|
||||
converter = new PrinterConverter(fieldType, printer, FormattingConversionService.this);
|
||||
cachedPrinters.put(key, converter);
|
||||
}
|
||||
return converter.convert(source, sourceType, targetType);
|
||||
}
|
||||
public String toString() {
|
||||
return "@" + annotationType.getName() + " " + fieldType.getName() + " -> " +
|
||||
|
|
@ -91,8 +102,14 @@ public class FormattingConversionService extends GenericConversionService implem
|
|||
return (targetType.getAnnotation(annotationType) != null);
|
||||
}
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
Parser<?> parser = annotationFormatterFactory.getParser(targetType.getAnnotation(annotationType), targetType.getType());
|
||||
return new ParserConverter(fieldType, parser, FormattingConversionService.this).convert(source, sourceType, targetType);
|
||||
FieldFormatterKey key = new FieldFormatterKey(targetType.getAnnotation(annotationType), fieldType);
|
||||
GenericConverter converter = cachedParsers.get(key);
|
||||
if (converter == null) {
|
||||
Parser<?> printer = annotationFormatterFactory.getParser(key.getAnnotation(), key.getFieldType());
|
||||
converter = new ParserConverter(fieldType, printer, FormattingConversionService.this);
|
||||
cachedParsers.put(key, converter);
|
||||
}
|
||||
return converter.convert(source, sourceType, targetType);
|
||||
}
|
||||
public String toString() {
|
||||
return String.class.getName() + " -> @" + annotationType.getName() + " " +
|
||||
|
|
@ -102,6 +119,38 @@ public class FormattingConversionService extends GenericConversionService implem
|
|||
}
|
||||
}
|
||||
|
||||
private static final class FieldFormatterKey {
|
||||
|
||||
private final Annotation annotation;
|
||||
|
||||
private final Class<?> fieldType;
|
||||
|
||||
public FieldFormatterKey(Annotation annotation, Class<?> fieldType) {
|
||||
this.annotation = annotation;
|
||||
this.fieldType = fieldType;
|
||||
}
|
||||
|
||||
public Annotation getAnnotation() {
|
||||
return annotation;
|
||||
}
|
||||
|
||||
public Class<?> getFieldType() {
|
||||
return fieldType;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof FieldFormatterKey)) {
|
||||
return false;
|
||||
}
|
||||
FieldFormatterKey key = (FieldFormatterKey) o;
|
||||
return this.annotation.equals(key.annotation) && this.fieldType.equals(key.fieldType);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.annotation.hashCode() + this.fieldType.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class PrinterConverter implements GenericConverter {
|
||||
|
||||
|
|
@ -142,7 +191,6 @@ public class FormattingConversionService extends GenericConversionService implem
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class ParserConverter implements GenericConverter {
|
||||
|
||||
private Class<?> fieldType;
|
||||
|
|
@ -166,17 +214,17 @@ public class FormattingConversionService extends GenericConversionService implem
|
|||
if (text == null || text.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
Object result;
|
||||
try {
|
||||
Object result = this.parser.parse(text, LocaleContextHolder.getLocale());
|
||||
TypeDescriptor resultType = TypeDescriptor.valueOf(result.getClass());
|
||||
if (!resultType.isAssignableTo(targetType)) {
|
||||
result = this.conversionService.convert(result, resultType, targetType);
|
||||
}
|
||||
return result;
|
||||
result = this.parser.parse(text, LocaleContextHolder.getLocale());
|
||||
} catch (ParseException e) {
|
||||
throw new IllegalArgumentException("Unable to parse '" + text + "'", e);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new ConversionFailedException(sourceType, targetType, source, ex);
|
||||
TypeDescriptor resultType = TypeDescriptor.valueOf(result.getClass());
|
||||
if (!resultType.isAssignableTo(targetType)) {
|
||||
result = this.conversionService.convert(result, resultType, targetType);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ public class TypeDescriptor {
|
|||
* Is this type a {@link Collection} type?
|
||||
*/
|
||||
public boolean isCollection() {
|
||||
return isTypeAssignableTo(Collection.class);
|
||||
return Collection.class.isAssignableFrom(getType());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -257,6 +257,15 @@ public class TypeDescriptor {
|
|||
return TypeDescriptor.valueOf(getElementType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the element type as a type descriptor; if the element type is null (cannot be determined), the type descriptor is derived from the element argument.
|
||||
* @param element the element
|
||||
* @return the element type descriptor
|
||||
*/
|
||||
public TypeDescriptor getElementTypeDescriptor(Object element) {
|
||||
return getElementType() != null ? getElementTypeDescriptor() : TypeDescriptor.forObject(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of this type descriptor, preserving the context information
|
||||
* but exposing the specified element type (e.g. an array/collection element).
|
||||
|
|
@ -280,7 +289,7 @@ public class TypeDescriptor {
|
|||
* Is this type a {@link Map} type?
|
||||
*/
|
||||
public boolean isMap() {
|
||||
return isTypeAssignableTo(Map.class);
|
||||
return Map.class.isAssignableFrom(getType());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -355,6 +364,15 @@ public class TypeDescriptor {
|
|||
return TypeDescriptor.valueOf(getMapKeyType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map key type as a type descriptor; if the key type is null (cannot be determined), the type descriptor is derived from the key argument.
|
||||
* @param key the key
|
||||
* @return the map key type descriptor
|
||||
*/
|
||||
public TypeDescriptor getMapKeyTypeDescriptor(Object key) {
|
||||
return getMapKeyType() != null ? getMapKeyTypeDescriptor() : TypeDescriptor.forObject(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns map value type as a type descriptor.
|
||||
*/
|
||||
|
|
@ -362,6 +380,15 @@ public class TypeDescriptor {
|
|||
return TypeDescriptor.valueOf(getMapValueType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map value type as a type descriptor; if the value type is null (cannot be determined), the type descriptor is derived from the value argument.
|
||||
* @param value the value
|
||||
* @return the map value type descriptor
|
||||
*/
|
||||
public TypeDescriptor getMapValueTypeDescriptor(Object value) {
|
||||
return getMapValueType() != null ? getMapValueTypeDescriptor() : TypeDescriptor.forObject(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the annotations associated with the wrapped parameter/field, if any.
|
||||
*/
|
||||
|
|
@ -374,8 +401,6 @@ public class TypeDescriptor {
|
|||
}
|
||||
else if (this.methodParameter != null) {
|
||||
if (this.methodParameter.getParameterIndex() < 0) {
|
||||
// The best we can do for return type metadata is to expose
|
||||
// method-level annotations when the target is the return type...
|
||||
return this.methodParameter.getMethodAnnotations();
|
||||
}
|
||||
else {
|
||||
|
|
@ -400,76 +425,22 @@ public class TypeDescriptor {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns true if an object this type can be assigned to a reference of given targetType.
|
||||
* Returns true if an object of this type can be assigned to a reference of given targetType.
|
||||
* @param targetType the target type
|
||||
* @return true if this type is assignable to the target
|
||||
*/
|
||||
public boolean isAssignableTo(TypeDescriptor targetType) {
|
||||
Class targetClass = targetType.getType();
|
||||
if (!isTypeAssignableTo(targetClass)) {
|
||||
return false;
|
||||
if (this == TypeDescriptor.NULL || targetType == TypeDescriptor.NULL) {
|
||||
return true;
|
||||
}
|
||||
if (targetClass != null) {
|
||||
if (Collection.class.isAssignableFrom(targetClass)) {
|
||||
Class<?> elementType = targetType.getCollectionElementType();
|
||||
if (elementType != null) {
|
||||
Class<?> sourceElementType = getCollectionElementType();
|
||||
if (sourceElementType == null || !elementType.isAssignableFrom(sourceElementType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Map.class.isAssignableFrom(targetClass)) {
|
||||
Class<?> keyType = targetType.getMapKeyType();
|
||||
if (keyType != null) {
|
||||
Class<?> sourceKeyType = getMapKeyType();
|
||||
if (sourceKeyType == null || !keyType.isAssignableFrom(sourceKeyType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Class<?> valueType = targetType.getMapValueType();
|
||||
if (valueType != null) {
|
||||
Class<?> sourceValueType = getMapValueType();
|
||||
if (sourceValueType == null || !valueType.isAssignableFrom(sourceValueType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return targetType.getObjectType().isAssignableFrom(getObjectType());
|
||||
}
|
||||
|
||||
/**
|
||||
* A textual representation of the type descriptor (eg. Map<String,Foo>) for use in messages
|
||||
*/
|
||||
public String asString() {
|
||||
StringBuffer stringValue = new StringBuffer();
|
||||
if (isArray()) {
|
||||
// TODO should properly handle multi dimensional arrays
|
||||
stringValue.append(getArrayComponentType().getName()).append("[]");
|
||||
}
|
||||
else {
|
||||
Class<?> clazz = getType();
|
||||
if (clazz == null) {
|
||||
return "null";
|
||||
}
|
||||
stringValue.append(clazz.getName());
|
||||
if (isCollection()) {
|
||||
Class<?> collectionType = getCollectionElementType();
|
||||
if (collectionType != null) {
|
||||
stringValue.append("<").append(collectionType.getName()).append(">");
|
||||
}
|
||||
}
|
||||
else if (isMap()) {
|
||||
Class<?> keyType = getMapKeyType();
|
||||
Class<?> valType = getMapValueType();
|
||||
if (keyType != null && valType != null) {
|
||||
stringValue.append("<").append(keyType.getName()).append(",");
|
||||
stringValue.append(valType).append(">");
|
||||
}
|
||||
}
|
||||
}
|
||||
return stringValue.toString();
|
||||
return toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
|
@ -484,6 +455,14 @@ public class TypeDescriptor {
|
|||
builder.append("@").append(ann.annotationType().getName()).append(' ');
|
||||
}
|
||||
builder.append(ClassUtils.getQualifiedName(getType()));
|
||||
if (isMap()) {
|
||||
Class<?> mapKeyType = getMapKeyType();
|
||||
Class<?> valueKeyType = getMapValueType();
|
||||
builder.append("<").append(mapKeyType != null ? ClassUtils.getQualifiedName(mapKeyType) : "?").append(", ").append(valueKeyType != null ? ClassUtils.getQualifiedName(valueKeyType) : "?").append(">");
|
||||
} else if (isCollection()) {
|
||||
Class<?> elementType = getElementType();
|
||||
builder.append("<").append(elementType != null ? ClassUtils.getQualifiedName(elementType) : "?").append(">");
|
||||
}
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
|
@ -521,12 +500,6 @@ public class TypeDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isTypeAssignableTo(Class<?> clazz) {
|
||||
Class<?> type = getType();
|
||||
return (type != null && (clazz == null || ClassUtils.isAssignable(clazz, type)));
|
||||
}
|
||||
|
||||
|
||||
// static factory methods
|
||||
|
||||
/**
|
||||
|
|
@ -551,7 +524,7 @@ public class TypeDescriptor {
|
|||
if (object == null) {
|
||||
return NULL;
|
||||
}
|
||||
else if (object instanceof Collection || object instanceof Map) {
|
||||
else if (object instanceof Collection<?> || object instanceof Map<?, ?>) {
|
||||
return new TypeDescriptor(object);
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.util.Arrays;
|
|||
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.GenericConverter;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
|
@ -35,7 +36,7 @@ final class ArrayToArrayConverter implements GenericConverter {
|
|||
|
||||
private final CollectionToArrayConverter helperConverter;
|
||||
|
||||
public ArrayToArrayConverter(GenericConversionService conversionService) {
|
||||
public ArrayToArrayConverter(ConversionService conversionService) {
|
||||
this.helperConverter = new CollectionToArrayConverter(conversionService);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,27 +22,25 @@ import java.util.Collections;
|
|||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
|
||||
/**
|
||||
* Converts an Array to a Collection.
|
||||
*
|
||||
* <p>First, creates a new Collection of the requested targetType.
|
||||
* Then adds each array element to the target collection.
|
||||
* Will perform an element conversion from the source component type
|
||||
* to the collection's parameterized type if necessary.
|
||||
* Will perform an element conversion from the source component type to the collection's parameterized type if necessary.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
*/
|
||||
final class ArrayToCollectionConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final GenericConversionService conversionService;
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public ArrayToCollectionConverter(GenericConversionService conversionService) {
|
||||
public ArrayToCollectionConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
|
|
@ -57,30 +55,16 @@ final class ArrayToCollectionConverter implements ConditionalGenericConverter {
|
|||
@SuppressWarnings("unchecked")
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
||||
return null;
|
||||
}
|
||||
int length = Array.getLength(source);
|
||||
Collection collection = CollectionFactory.createCollection(targetType.getType(), length);
|
||||
TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor();
|
||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
||||
if (targetElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetElementType)) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
collection.add(Array.get(source, i));
|
||||
}
|
||||
Collection target = CollectionFactory.createCollection(targetType.getType(), length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object sourceElement = Array.get(source, i);
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor(sourceElement));
|
||||
target.add(targetElement);
|
||||
}
|
||||
else {
|
||||
GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetElementType);
|
||||
if (converter == null) {
|
||||
throw new ConverterNotFoundException(sourceElementType, targetElementType);
|
||||
}
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object sourceElement = Array.get(source, i);
|
||||
Object targetElement = ConversionUtils.invokeConverter(
|
||||
converter, sourceElement, sourceElementType, targetElementType);
|
||||
collection.add(targetElement);
|
||||
}
|
||||
}
|
||||
return collection;
|
||||
return target;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.util.Arrays;
|
|||
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.ObjectUtils;
|
||||
|
|
@ -35,7 +36,7 @@ final class ArrayToObjectConverter implements ConditionalGenericConverter {
|
|||
|
||||
private final CollectionToObjectConverter helperConverter;
|
||||
|
||||
public ArrayToObjectConverter(GenericConversionService conversionService) {
|
||||
public ArrayToObjectConverter(ConversionService conversionService) {
|
||||
this.helperConverter = new CollectionToObjectConverter(conversionService);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.util.Arrays;
|
|||
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.ObjectUtils;
|
||||
|
|
@ -35,7 +36,7 @@ final class ArrayToStringConverter implements ConditionalGenericConverter {
|
|||
|
||||
private final CollectionToStringConverter helperConverter;
|
||||
|
||||
public ArrayToStringConverter(GenericConversionService conversionService) {
|
||||
public ArrayToStringConverter(ConversionService conversionService) {
|
||||
this.helperConverter = new CollectionToStringConverter(conversionService);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,13 +19,11 @@ package org.springframework.core.convert.support;
|
|||
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.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
|
||||
/**
|
||||
* Converts a Collection to an array.
|
||||
|
|
@ -40,9 +38,9 @@ import org.springframework.core.convert.converter.GenericConverter;
|
|||
*/
|
||||
final class CollectionToArrayConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final GenericConversionService conversionService;
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public CollectionToArrayConverter(GenericConversionService conversionService) {
|
||||
public CollectionToArrayConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
|
|
@ -56,32 +54,14 @@ final class CollectionToArrayConverter implements ConditionalGenericConverter {
|
|||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Collection<?> sourceCollection = (Collection<?>) source;
|
||||
TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor();
|
||||
if (sourceElementType == TypeDescriptor.NULL) {
|
||||
sourceElementType = ConversionUtils.getElementType(sourceCollection);
|
||||
}
|
||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
||||
Object array = Array.newInstance(targetElementType.getType(), sourceCollection.size());
|
||||
Object array = Array.newInstance(targetType.getElementType(), sourceCollection.size());
|
||||
int i = 0;
|
||||
if (sourceElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetElementType)) {
|
||||
for (Iterator<?> it = sourceCollection.iterator(); it.hasNext(); i++) {
|
||||
Array.set(array, i, it.next());
|
||||
}
|
||||
}
|
||||
else {
|
||||
GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetElementType);
|
||||
if (converter == null) {
|
||||
throw new ConverterNotFoundException(sourceElementType, targetElementType);
|
||||
}
|
||||
for (Iterator<?> it = sourceCollection.iterator(); it.hasNext(); i++) {
|
||||
Object sourceElement = it.next();
|
||||
Object targetElement = ConversionUtils.invokeConverter(
|
||||
converter, sourceElement, sourceElementType, targetElementType);
|
||||
Array.set(array, i, targetElement);
|
||||
}
|
||||
for (Object sourceElement : sourceCollection) {
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(sourceElement), targetType.getElementTypeDescriptor());
|
||||
Array.set(array, i++, targetElement);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,10 +21,9 @@ import java.util.Collections;
|
|||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
|
||||
/**
|
||||
* Converts from a Collection to another Collection.
|
||||
|
|
@ -39,9 +38,9 @@ import org.springframework.core.convert.converter.GenericConverter;
|
|||
*/
|
||||
final class CollectionToCollectionConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final GenericConversionService conversionService;
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public CollectionToCollectionConverter(GenericConversionService conversionService) {
|
||||
public CollectionToCollectionConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
|
|
@ -56,32 +55,13 @@ final class CollectionToCollectionConverter implements ConditionalGenericConvert
|
|||
@SuppressWarnings("unchecked")
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
||||
return null;
|
||||
}
|
||||
Collection<?> sourceCollection = (Collection<?>) source;
|
||||
TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor();
|
||||
if (sourceElementType == TypeDescriptor.NULL) {
|
||||
sourceElementType = ConversionUtils.getElementType(sourceCollection);
|
||||
}
|
||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
||||
if (sourceElementType == TypeDescriptor.NULL || targetElementType == TypeDescriptor.NULL
|
||||
|| sourceElementType.isAssignableTo(targetElementType)) {
|
||||
if (sourceType.isAssignableTo(targetType)) {
|
||||
return sourceCollection;
|
||||
}
|
||||
else {
|
||||
Collection target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
|
||||
target.addAll(sourceCollection);
|
||||
return target;
|
||||
}
|
||||
}
|
||||
Collection target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
|
||||
GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetElementType);
|
||||
if (converter == null) {
|
||||
throw new ConverterNotFoundException(sourceElementType, targetElementType);
|
||||
}
|
||||
for (Object element : sourceCollection) {
|
||||
target.add(ConversionUtils.invokeConverter(converter, element, sourceElementType, targetElementType));
|
||||
for (Object sourceElement : sourceCollection) {
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(sourceElement), targetType.getElementTypeDescriptor(sourceElement));
|
||||
target.add(targetElement);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,9 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
|
||||
/**
|
||||
* Converts a Collection to an Object by returning the first collection element after converting it to the desired targetType.
|
||||
|
|
@ -33,9 +32,9 @@ import org.springframework.core.convert.converter.GenericConverter;
|
|||
*/
|
||||
final class CollectionToObjectConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final GenericConversionService conversionService;
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public CollectionToObjectConverter(GenericConversionService conversionService) {
|
||||
public CollectionToObjectConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
|
|
@ -49,29 +48,14 @@ final class CollectionToObjectConverter implements ConditionalGenericConverter {
|
|||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
||||
return null;
|
||||
}
|
||||
Collection<?> sourceCollection = (Collection<?>) source;
|
||||
if (sourceCollection.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
Object firstElement = sourceCollection.iterator().next();
|
||||
TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor();
|
||||
if (sourceElementType == TypeDescriptor.NULL && firstElement != null) {
|
||||
sourceElementType = TypeDescriptor.valueOf(firstElement.getClass());
|
||||
}
|
||||
if (sourceElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetType)) {
|
||||
return firstElement;
|
||||
}
|
||||
else {
|
||||
GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetType);
|
||||
if (converter == null) {
|
||||
throw new ConverterNotFoundException(sourceElementType, targetType);
|
||||
}
|
||||
return ConversionUtils.invokeConverter(converter, firstElement, sourceElementType, targetType);
|
||||
}
|
||||
}
|
||||
Object firstElement = sourceCollection.iterator().next();
|
||||
return this.conversionService.convert(firstElement, sourceType.getElementTypeDescriptor(firstElement), targetType);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -20,10 +20,9 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
|
||||
/**
|
||||
* Converts a Collection to a comma-delimited String.
|
||||
|
|
@ -35,9 +34,9 @@ final class CollectionToStringConverter implements ConditionalGenericConverter {
|
|||
|
||||
private static final String DELIMITER = ",";
|
||||
|
||||
private final GenericConversionService conversionService;
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public CollectionToStringConverter(GenericConversionService conversionService) {
|
||||
public CollectionToStringConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
|
|
@ -51,48 +50,23 @@ final class CollectionToStringConverter implements ConditionalGenericConverter {
|
|||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
||||
return null;
|
||||
}
|
||||
Collection<?> sourceCollection = (Collection<?>) source;
|
||||
if (sourceCollection.size() == 0) {
|
||||
return "";
|
||||
}
|
||||
else {
|
||||
TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor();
|
||||
if (sourceElementType == TypeDescriptor.NULL) {
|
||||
sourceElementType = ConversionUtils.getElementType(sourceCollection);
|
||||
}
|
||||
if (sourceElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetType)) {
|
||||
StringBuilder string = new StringBuilder();
|
||||
int i = 0;
|
||||
for (Object element : sourceCollection) {
|
||||
if (i > 0) {
|
||||
string.append(DELIMITER);
|
||||
}
|
||||
string.append(element);
|
||||
i++;
|
||||
}
|
||||
return string.toString();
|
||||
}
|
||||
else {
|
||||
GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetType);
|
||||
if (converter == null) {
|
||||
throw new ConverterNotFoundException(sourceElementType, targetType);
|
||||
}
|
||||
StringBuilder string = new StringBuilder();
|
||||
int i = 0;
|
||||
for (Object sourceElement : sourceCollection) {
|
||||
if (i > 0) {
|
||||
string.append(DELIMITER);
|
||||
}
|
||||
Object targetElement = ConversionUtils.invokeConverter(
|
||||
converter, sourceElement, sourceElementType, targetType);
|
||||
string.append(targetElement);
|
||||
i++;
|
||||
}
|
||||
return string.toString();
|
||||
StringBuilder string = new StringBuilder();
|
||||
int i = 0;
|
||||
for (Object sourceElement : sourceCollection) {
|
||||
if (i > 0) {
|
||||
string.append(DELIMITER);
|
||||
}
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(sourceElement), targetType);
|
||||
string.append(targetElement);
|
||||
i++;
|
||||
}
|
||||
return string.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
|
|
@ -39,6 +40,7 @@ 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;
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
|
|
@ -113,29 +115,68 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
|||
|
||||
public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
assertNotNull(sourceType, targetType);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Checking if I can convert " + sourceType + " to " + targetType);
|
||||
}
|
||||
if (sourceType == TypeDescriptor.NULL || targetType == TypeDescriptor.NULL) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Yes, I can convert");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return getConverter(sourceType, targetType) != null;
|
||||
GenericConverter converter = getConverter(sourceType, targetType);
|
||||
if (converter != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Yes, I can convert");
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No, I cannot convert");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
assertNotNull(sourceType, targetType);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Converting value of " + sourceType + " to " + targetType);
|
||||
logger.debug("Converting value " + StylerUtils.style(source) + " of " + sourceType + " to " + targetType);
|
||||
}
|
||||
if (sourceType == TypeDescriptor.NULL) {
|
||||
Assert.isTrue(source == null, "The source must be null if sourceType == TypeDescriptor.NULL");
|
||||
return convertNullSource(sourceType, targetType);
|
||||
Assert.isTrue(source == null, "The value must be null if sourceType == TypeDescriptor.NULL");
|
||||
Object result = convertNullSource(sourceType, targetType);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Converted to " + StylerUtils.style(result));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (targetType == TypeDescriptor.NULL) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Converted to null");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
GenericConverter converter = getConverter(sourceType, targetType);
|
||||
if (converter == null) {
|
||||
throw new ConverterNotFoundException(sourceType, targetType);
|
||||
ConverterNotFoundException e = new ConverterNotFoundException(sourceType, targetType);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
try {
|
||||
Object result = ConversionUtils.invokeConverter(converter, source, sourceType, targetType);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Converted to " + StylerUtils.style(result));
|
||||
}
|
||||
return result;
|
||||
} catch (ConversionException e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return ConversionUtils.invokeConverter(converter, source, sourceType, targetType);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
|
@ -197,7 +238,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
|||
|
||||
/**
|
||||
* Return the default converter if no converter is found for the given sourceType/targetType pair.
|
||||
* Returns a NO_OP Converter if the sourceType is assignalbe to the targetType.
|
||||
* Returns a NO_OP Converter if the sourceType is assignable to the targetType.
|
||||
* Returns <code>null</code> otherwise, indicating no suitable converter could be found.
|
||||
* Subclasses may override.
|
||||
* @param sourceType the source type to convert from
|
||||
|
|
@ -366,7 +407,6 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
|||
|
||||
private GenericConverter matchConverter(
|
||||
MatchableConverters matchable, TypeDescriptor sourceFieldType, TypeDescriptor targetFieldType) {
|
||||
|
||||
return (matchable != null ? matchable.matchConverter(sourceFieldType, targetFieldType) : null);
|
||||
}
|
||||
|
||||
|
|
@ -453,19 +493,19 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
|||
for (ConditionalGenericConverter conditional : this.conditionalConverters) {
|
||||
if (conditional.matches(sourceType, targetType)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Conditional converter lookup [MATCHED] " + conditional);
|
||||
logger.debug("[MATCHED] converter " + conditional);
|
||||
}
|
||||
return conditional;
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Conditional converter lookup [DID NOT MATCH] " + conditional);
|
||||
logger.debug("[DID NOT MATCH] converter " + conditional);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.defaultConverter != null && logger.isDebugEnabled()) {
|
||||
logger.debug("Default converter lookup [MATCHED] " + this.defaultConverter);
|
||||
logger.debug("[MATCHED] converter " + this.defaultConverter);
|
||||
}
|
||||
return this.defaultConverter;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
|
||||
|
|
@ -37,9 +38,9 @@ import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
|||
*/
|
||||
final class MapToMapConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final GenericConversionService conversionService;
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public MapToMapConverter(GenericConversionService conversionService) {
|
||||
public MapToMapConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
|
|
@ -55,57 +56,19 @@ final class MapToMapConverter implements ConditionalGenericConverter {
|
|||
@SuppressWarnings("unchecked")
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
||||
return null;
|
||||
}
|
||||
Map<?, ?> sourceMap = (Map<?, ?>) source;
|
||||
TypeDescriptor targetKeyType = targetType.getMapKeyTypeDescriptor();
|
||||
TypeDescriptor targetValueType = targetType.getMapValueTypeDescriptor();
|
||||
if (targetKeyType == TypeDescriptor.NULL && targetValueType == TypeDescriptor.NULL) {
|
||||
return compatibleMapWithoutEntryConversion(sourceMap, targetType);
|
||||
}
|
||||
TypeDescriptor sourceKeyType = sourceType.getMapKeyTypeDescriptor();
|
||||
TypeDescriptor sourceValueType = sourceType.getMapValueTypeDescriptor();
|
||||
if (sourceKeyType == TypeDescriptor.NULL || sourceValueType == TypeDescriptor.NULL) {
|
||||
TypeDescriptor[] sourceEntryTypes = ConversionUtils.getMapEntryTypes(sourceMap);
|
||||
sourceKeyType = sourceEntryTypes[0];
|
||||
sourceValueType = sourceEntryTypes[1];
|
||||
}
|
||||
if (sourceKeyType == TypeDescriptor.NULL && sourceValueType == TypeDescriptor.NULL) {
|
||||
return compatibleMapWithoutEntryConversion(sourceMap, targetType);
|
||||
}
|
||||
boolean keysCompatible = false;
|
||||
if (sourceKeyType != TypeDescriptor.NULL && sourceKeyType.isAssignableTo(targetKeyType)) {
|
||||
keysCompatible = true;
|
||||
}
|
||||
boolean valuesCompatible = false;
|
||||
if (sourceValueType != TypeDescriptor.NULL && sourceValueType.isAssignableTo(targetValueType)) {
|
||||
valuesCompatible = true;
|
||||
}
|
||||
if (keysCompatible && valuesCompatible) {
|
||||
return compatibleMapWithoutEntryConversion(sourceMap, targetType);
|
||||
}
|
||||
Map targetMap = CollectionFactory.createMap(targetType.getType(), sourceMap.size());
|
||||
MapEntryConverter converter = new MapEntryConverter(sourceKeyType, sourceValueType, targetKeyType,
|
||||
targetValueType, keysCompatible, valuesCompatible, this.conversionService);
|
||||
for (Object entry : sourceMap.entrySet()) {
|
||||
Map.Entry sourceMapEntry = (Map.Entry) entry;
|
||||
Object targetKey = converter.convertKey(sourceMapEntry.getKey());
|
||||
Object targetValue = converter.convertValue(sourceMapEntry.getValue());
|
||||
Object sourceKey = sourceMapEntry.getKey();
|
||||
Object sourceValue = sourceMapEntry.getValue();
|
||||
Object targetKey = this.conversionService.convert(sourceKey, sourceType.getMapKeyTypeDescriptor(sourceKey), targetType.getMapKeyTypeDescriptor(sourceKey));
|
||||
Object targetValue = this.conversionService.convert(sourceValue, sourceType.getMapValueTypeDescriptor(sourceValue), targetType.getMapValueTypeDescriptor(sourceValue));
|
||||
targetMap.put(targetKey, targetValue);
|
||||
}
|
||||
return targetMap;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<?, ?> compatibleMapWithoutEntryConversion(Map<?, ?> source, TypeDescriptor targetType) {
|
||||
if (targetType.getType().isInstance(source)) {
|
||||
return source;
|
||||
}
|
||||
else {
|
||||
Map target = CollectionFactory.createMap(targetType.getType(), source.size());
|
||||
target.putAll(source);
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,9 @@ import java.lang.reflect.Array;
|
|||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
|
||||
/**
|
||||
* Converts an Object to a single-element Array containing the Object.
|
||||
|
|
@ -34,9 +33,9 @@ import org.springframework.core.convert.converter.GenericConverter;
|
|||
*/
|
||||
final class ObjectToArrayConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final GenericConversionService conversionService;
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public ObjectToArrayConverter(GenericConversionService conversionService) {
|
||||
public ObjectToArrayConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
|
|
@ -50,20 +49,11 @@ final class ObjectToArrayConverter implements ConditionalGenericConverter {
|
|||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
||||
}
|
||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
||||
Object target = Array.newInstance(targetElementType.getType(), 1);
|
||||
if (sourceType.isAssignableTo(targetElementType)) {
|
||||
Array.set(target, 0, source);
|
||||
}
|
||||
else {
|
||||
GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType);
|
||||
if (converter == null) {
|
||||
throw new ConverterNotFoundException(sourceType, targetElementType);
|
||||
}
|
||||
Array.set(target, 0, ConversionUtils.invokeConverter(converter, source, sourceType, targetElementType));
|
||||
return null;
|
||||
}
|
||||
Object target = Array.newInstance(targetType.getElementType(), 1);
|
||||
Object targetElement = this.conversionService.convert(source, sourceType, targetType.getElementTypeDescriptor());
|
||||
Array.set(target, 0, targetElement);
|
||||
return target;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,9 @@ import java.util.Collections;
|
|||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
|
||||
/**
|
||||
* Converts an Object to a single-element Collection containing the Object.
|
||||
|
|
@ -35,9 +34,9 @@ import org.springframework.core.convert.converter.GenericConverter;
|
|||
*/
|
||||
final class ObjectToCollectionConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final GenericConversionService conversionService;
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public ObjectToCollectionConverter(GenericConversionService conversionService) {
|
||||
public ObjectToCollectionConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
|
|
@ -52,20 +51,11 @@ final class ObjectToCollectionConverter implements ConditionalGenericConverter {
|
|||
@SuppressWarnings("unchecked")
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
||||
return null;
|
||||
}
|
||||
Collection target = CollectionFactory.createCollection(targetType.getType(), 1);
|
||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
||||
if (targetElementType == TypeDescriptor.NULL || sourceType.isAssignableTo(targetElementType)) {
|
||||
target.add(source);
|
||||
}
|
||||
else {
|
||||
GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType);
|
||||
if (converter == null) {
|
||||
throw new ConverterNotFoundException(sourceType, targetElementType);
|
||||
}
|
||||
target.add(ConversionUtils.invokeConverter(converter, source, sourceType, targetElementType));
|
||||
}
|
||||
Object targetElement = this.conversionService.convert(source, sourceType, targetType.getElementTypeDescriptor(source));
|
||||
target.add(targetElement);
|
||||
return target;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,9 +52,6 @@ final class ObjectToObjectConverter implements ConditionalGenericConverter {
|
|||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (sourceType.isAssignableTo(targetType)) {
|
||||
return source;
|
||||
}
|
||||
Class<?> sourceClass = sourceType.getObjectType();
|
||||
Class<?> targetClass = targetType.getObjectType();
|
||||
Object target;
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ final class ObjectToStringConverter implements ConditionalGenericConverter {
|
|||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
Class<?> sourceClass = sourceType.getObjectType();
|
||||
return Number.class.isAssignableFrom(sourceClass) || Boolean.class.equals(sourceClass) ||
|
||||
Character.class.equals(sourceClass) || CharSequence.class.isAssignableFrom(sourceClass) ||
|
||||
StringWriter.class.isAssignableFrom(sourceClass) || sourceClass.isEnum() ||
|
||||
ObjectToObjectConverter.hasValueOfMethodOrConstructor(sourceClass, String.class);
|
||||
return String.class.equals(sourceClass) || Number.class.isAssignableFrom(sourceClass) ||
|
||||
Boolean.class.equals(sourceClass) || Character.class.equals(sourceClass) ||
|
||||
CharSequence.class.isAssignableFrom(sourceClass) || StringWriter.class.isAssignableFrom(sourceClass) ||
|
||||
sourceClass.isEnum() || ObjectToObjectConverter.hasValueOfMethodOrConstructor(sourceClass, String.class);
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
|
|
|
|||
|
|
@ -75,10 +75,10 @@ public class PropertyTypeDescriptor extends TypeDescriptor {
|
|||
public Annotation[] getAnnotations() {
|
||||
Annotation[] anns = this.cachedAnnotations;
|
||||
if (anns == null) {
|
||||
Map<Class, Annotation> annMap = new LinkedHashMap<Class, Annotation>();
|
||||
Map<Class<?>, Annotation> annMap = new LinkedHashMap<Class<?>, Annotation>();
|
||||
String name = this.propertyDescriptor.getName();
|
||||
if (StringUtils.hasLength(name)) {
|
||||
Class clazz = getMethodParameter().getMethod().getDeclaringClass();
|
||||
Class<?> clazz = getMethodParameter().getMethod().getDeclaringClass();
|
||||
Field field = ReflectionUtils.findField(clazz, name);
|
||||
if (field == null) {
|
||||
// Same lenient fallback checking as in CachedIntrospectionResults...
|
||||
|
|
|
|||
|
|
@ -20,10 +20,9 @@ import java.lang.reflect.Array;
|
|||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
|
|
@ -34,9 +33,9 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
final class StringToArrayConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final GenericConversionService conversionService;
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public StringToArrayConverter(GenericConversionService conversionService) {
|
||||
public StringToArrayConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
|
|
@ -50,25 +49,17 @@ final class StringToArrayConverter implements ConditionalGenericConverter {
|
|||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
||||
return null;
|
||||
}
|
||||
String string = (String) source;
|
||||
String[] fields = StringUtils.commaDelimitedListToStringArray(string);
|
||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
||||
if (sourceType.isAssignableTo(targetElementType)) {
|
||||
return fields;
|
||||
}
|
||||
else {
|
||||
Object target = Array.newInstance(targetElementType.getType(), fields.length);
|
||||
GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType);
|
||||
if (converter == null) {
|
||||
throw new ConverterNotFoundException(sourceType, targetElementType);
|
||||
}
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
Array.set(target, i, ConversionUtils.invokeConverter(converter, fields[i], sourceType, targetElementType));
|
||||
}
|
||||
return target;
|
||||
Object target = Array.newInstance(targetType.getElementType(), fields.length);
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
Object sourceElement = fields[i];
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType, targetType.getElementTypeDescriptor());
|
||||
Array.set(target, i, targetElement);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,10 +21,9 @@ import java.util.Collections;
|
|||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
|
|
@ -35,9 +34,9 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
final class StringToCollectionConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final GenericConversionService conversionService;
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public StringToCollectionConverter(GenericConversionService conversionService) {
|
||||
public StringToCollectionConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
|
|
@ -52,27 +51,14 @@ final class StringToCollectionConverter implements ConditionalGenericConverter {
|
|||
@SuppressWarnings("unchecked")
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return this.conversionService.convertNullSource(sourceType, targetType);
|
||||
return null;
|
||||
}
|
||||
String string = (String) source;
|
||||
String[] fields = StringUtils.commaDelimitedListToStringArray(string);
|
||||
Collection target = CollectionFactory.createCollection(targetType.getType(), fields.length);
|
||||
TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
|
||||
if (targetElementType == TypeDescriptor.NULL || sourceType.isAssignableTo(targetElementType)) {
|
||||
for (String field : fields) {
|
||||
target.add(field);
|
||||
}
|
||||
}
|
||||
else {
|
||||
GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType);
|
||||
if (converter == null) {
|
||||
throw new ConverterNotFoundException(sourceType, targetElementType);
|
||||
}
|
||||
for (String sourceElement : fields) {
|
||||
Object targetElement = ConversionUtils.invokeConverter(
|
||||
converter, sourceElement, sourceType, targetElementType);
|
||||
target.add(targetElement);
|
||||
}
|
||||
for (String sourceElement : fields) {
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType, targetType.getElementTypeDescriptor(sourceElement));
|
||||
target.add(targetElement);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public class TypeDescriptorTests {
|
|||
assertTrue(typeDescriptor.isArray());
|
||||
assertEquals(Integer.TYPE,typeDescriptor.getElementType());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void complexTypeDescriptors() throws Exception {
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(TypeDescriptorTests.class.getDeclaredField("arrayOfListOfString"));
|
||||
|
|
|
|||
|
|
@ -39,19 +39,20 @@ public class GenericConversionServiceTests {
|
|||
private GenericConversionService conversionService = new GenericConversionService();
|
||||
|
||||
@Test
|
||||
public void executeConversion() {
|
||||
public void convert() {
|
||||
conversionService.addConverterFactory(new StringToNumberConverterFactory());
|
||||
assertEquals(new Integer(3), conversionService.convert("3", Integer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeConversionNullSource() {
|
||||
public void convertNullSource() {
|
||||
assertEquals(null, conversionService.convert(null, Integer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeCompatibleSource() {
|
||||
public void convertAssignableSource() {
|
||||
assertEquals(Boolean.FALSE, conversionService.convert(false, boolean.class));
|
||||
assertEquals(Boolean.FALSE, conversionService.convert(false, Boolean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -189,7 +190,7 @@ public class GenericConversionServiceTests {
|
|||
input.put("key", "value");
|
||||
Object converted = conversionService.convert(input, TypeDescriptor.forObject(input),
|
||||
new TypeDescriptor(getClass().getField("wildcardMap")));
|
||||
assertSame(input, converted);
|
||||
assertEquals(input, converted);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ public class TypedValue {
|
|||
@Override
|
||||
public String toString() {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append("TypedValue: ").append(this.value).append(" of type ").append(this.getTypeDescriptor().asString());
|
||||
str.append("TypedValue: ").append(this.value).append(" of ").append(this.getTypeDescriptor());
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,12 +29,12 @@ import org.springframework.expression.ParseException;
|
|||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypedValue;
|
||||
import org.springframework.expression.spel.ast.FormatHelper;
|
||||
import org.springframework.expression.spel.standard.SpelExpression;
|
||||
import org.springframework.expression.spel.support.ReflectionHelper;
|
||||
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeConverter;
|
||||
import org.springframework.expression.spel.support.ReflectionHelper.ArgsMatchKind;
|
||||
import org.springframework.expression.spel.standard.SpelExpression;
|
||||
|
||||
/**
|
||||
* Tests for any helper code.
|
||||
|
|
@ -94,7 +94,7 @@ public class HelperTests extends ExpressionTestCase {
|
|||
public void testTypedValue() {
|
||||
TypedValue tValue = new TypedValue("hello");
|
||||
Assert.assertEquals(String.class,tValue.getTypeDescriptor().getType());
|
||||
Assert.assertEquals("TypedValue: hello of type java.lang.String",tValue.toString());
|
||||
Assert.assertEquals("TypedValue: hello of [TypeDescriptor java.lang.String]",tValue.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue