Default conversion support for EnumSet / EnumMap
Issue: SPR-12483
This commit is contained in:
parent
717b2af50f
commit
fef4cd0ed6
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
|
|
@ -18,6 +18,8 @@ package org.springframework.core;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
|
|
@ -33,6 +35,7 @@ import java.util.SortedSet;
|
|||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
|
|
@ -72,9 +75,11 @@ public abstract class CollectionFactory {
|
|||
approximableCollectionTypes.add(HashSet.class);
|
||||
approximableCollectionTypes.add(LinkedHashSet.class);
|
||||
approximableCollectionTypes.add(TreeSet.class);
|
||||
approximableCollectionTypes.add(EnumSet.class);
|
||||
approximableMapTypes.add(HashMap.class);
|
||||
approximableMapTypes.add(LinkedHashMap.class);
|
||||
approximableMapTypes.add(TreeMap.class);
|
||||
approximableMapTypes.add(EnumMap.class);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -91,68 +96,87 @@ public abstract class CollectionFactory {
|
|||
|
||||
/**
|
||||
* Create the most approximate collection for the given collection.
|
||||
* <p>Creates an ArrayList, TreeSet or linked Set for a List, SortedSet
|
||||
* or Set, respectively.
|
||||
* @param collection the original Collection object
|
||||
* @param initialCapacity the initial capacity
|
||||
* @param capacity the initial capacity
|
||||
* @return the new Collection instance
|
||||
* @see java.util.ArrayList
|
||||
* @see java.util.TreeSet
|
||||
* @see java.util.LinkedHashSet
|
||||
* @see java.util.TreeSet
|
||||
* @see java.util.EnumSet
|
||||
* @see java.util.ArrayList
|
||||
* @see java.util.LinkedList
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E> Collection<E> createApproximateCollection(Object collection, int initialCapacity) {
|
||||
public static <E> Collection<E> createApproximateCollection(Object collection, int capacity) {
|
||||
if (collection instanceof LinkedList) {
|
||||
return new LinkedList<E>();
|
||||
}
|
||||
else if (collection instanceof List) {
|
||||
return new ArrayList<E>(initialCapacity);
|
||||
return new ArrayList<E>(capacity);
|
||||
}
|
||||
else if (collection instanceof EnumSet) {
|
||||
return EnumSet.copyOf((Collection) collection);
|
||||
}
|
||||
else if (collection instanceof SortedSet) {
|
||||
return new TreeSet<E>(((SortedSet<E>) collection).comparator());
|
||||
}
|
||||
else {
|
||||
return new LinkedHashSet<E>(initialCapacity);
|
||||
return new LinkedHashSet<E>(capacity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the most appropriate collection for the given collection type.
|
||||
* <p>Creates an ArrayList, TreeSet or linked Set for a List, SortedSet
|
||||
* or Set, respectively.
|
||||
* @param collectionType the desired type of the target Collection
|
||||
* @param initialCapacity the initial capacity
|
||||
* <p>Delegates to {@link #createCollection(Class, Class, int)} with a
|
||||
* {@code null} element type.
|
||||
* @param collectionClass the desired type of the target Collection
|
||||
* @param capacity the initial capacity
|
||||
* @return the new Collection instance
|
||||
*/
|
||||
public static <E> Collection<E> createCollection(Class<?> collectionClass, int capacity) {
|
||||
return createCollection(collectionClass, null, capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the most appropriate collection for the given collection type.
|
||||
* @param collectionClass the desired type of the target Collection
|
||||
* @param elementType the collection's element type, or {@code null} if not known
|
||||
* @param capacity the initial capacity
|
||||
* @return the new Collection instance
|
||||
* @see java.util.ArrayList
|
||||
* @see java.util.TreeSet
|
||||
* @see java.util.LinkedHashSet
|
||||
* @see java.util.TreeSet
|
||||
* @see java.util.EnumSet
|
||||
* @see java.util.ArrayList
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E> Collection<E> createCollection(Class<?> collectionType, int initialCapacity) {
|
||||
if (collectionType.isInterface()) {
|
||||
if (List.class.equals(collectionType)) {
|
||||
return new ArrayList<E>(initialCapacity);
|
||||
public static <E> Collection<E> createCollection(Class<?> collectionClass, Class<?> elementType, int capacity) {
|
||||
if (collectionClass.isInterface()) {
|
||||
if (Set.class.equals(collectionClass) || Collection.class.equals(collectionClass)) {
|
||||
return new LinkedHashSet<E>(capacity);
|
||||
}
|
||||
else if (SortedSet.class.equals(collectionType) || NavigableSet.class.equals(collectionType)) {
|
||||
else if (List.class.equals(collectionClass)) {
|
||||
return new ArrayList<E>(capacity);
|
||||
}
|
||||
else if (SortedSet.class.equals(collectionClass) || NavigableSet.class.equals(collectionClass)) {
|
||||
return new TreeSet<E>();
|
||||
}
|
||||
else if (Set.class.equals(collectionType) || Collection.class.equals(collectionType)) {
|
||||
return new LinkedHashSet<E>(initialCapacity);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unsupported Collection interface: " + collectionType.getName());
|
||||
throw new IllegalArgumentException("Unsupported Collection interface: " + collectionClass.getName());
|
||||
}
|
||||
}
|
||||
else if (EnumSet.class.equals(collectionClass)) {
|
||||
Assert.notNull(elementType, "Cannot create EnumSet for unknown element type");
|
||||
return EnumSet.noneOf((Class) elementType);
|
||||
}
|
||||
else {
|
||||
if (!Collection.class.isAssignableFrom(collectionType)) {
|
||||
throw new IllegalArgumentException("Unsupported Collection type: " + collectionType.getName());
|
||||
if (!Collection.class.isAssignableFrom(collectionClass)) {
|
||||
throw new IllegalArgumentException("Unsupported Collection type: " + collectionClass.getName());
|
||||
}
|
||||
try {
|
||||
return (Collection<E>) collectionType.newInstance();
|
||||
return (Collection<E>) collectionClass.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalArgumentException("Could not instantiate Collection type: " +
|
||||
collectionType.getName(), ex);
|
||||
throw new IllegalArgumentException(
|
||||
"Could not instantiate Collection type: " + collectionClass.getName(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -170,58 +194,78 @@ public abstract class CollectionFactory {
|
|||
|
||||
/**
|
||||
* Create the most approximate map for the given map.
|
||||
* <p>Creates a TreeMap or linked Map for a SortedMap or Map, respectively.
|
||||
* @param map the original Map object
|
||||
* @param initialCapacity the initial capacity
|
||||
* @param capacity the initial capacity
|
||||
* @return the new Map instance
|
||||
* @see java.util.TreeMap
|
||||
* @see java.util.LinkedHashMap
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K, V> Map<K, V> createApproximateMap(Object map, int initialCapacity) {
|
||||
if (map instanceof SortedMap) {
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static <K, V> Map<K, V> createApproximateMap(Object map, int capacity) {
|
||||
if (map instanceof EnumMap) {
|
||||
return new EnumMap((Map) map);
|
||||
}
|
||||
else if (map instanceof SortedMap) {
|
||||
return new TreeMap<K, V>(((SortedMap<K, V>) map).comparator());
|
||||
}
|
||||
else {
|
||||
return new LinkedHashMap<K, V>(initialCapacity);
|
||||
return new LinkedHashMap<K, V>(capacity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the most approximate map for the given map.
|
||||
* <p>Creates a TreeMap or linked Map for a SortedMap or Map, respectively.
|
||||
* @param mapType the desired type of the target Map
|
||||
* @param initialCapacity the initial capacity
|
||||
* <p>Delegates to {@link #createMap(Class, Class, int)} with a
|
||||
* {@code null} key type.
|
||||
* @param mapClass the desired type of the target Map
|
||||
* @param capacity the initial capacity
|
||||
* @return the new Map instance
|
||||
* @see java.util.TreeMap
|
||||
* @see java.util.LinkedHashMap
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public static <K, V> Map<K, V> createMap(Class<?> mapType, int initialCapacity) {
|
||||
if (mapType.isInterface()) {
|
||||
if (Map.class.equals(mapType)) {
|
||||
return new LinkedHashMap<K, V>(initialCapacity);
|
||||
public static <K, V> Map<K, V> createMap(Class<?> mapClass, int capacity) {
|
||||
return createMap(mapClass, null, capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the most approximate map for the given map.
|
||||
* @param mapClass the desired type of the target Map
|
||||
* @param keyType the map's key type, or {@code null} if not known
|
||||
* @param capacity the initial capacity
|
||||
* @return the new Map instance
|
||||
* @see java.util.LinkedHashMap
|
||||
* @see java.util.TreeMap
|
||||
* @see java.util.EnumMap
|
||||
* @see org.springframework.util.LinkedMultiValueMap
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static <K, V> Map<K, V> createMap(Class<?> mapClass, Class<?> keyType, int capacity) {
|
||||
if (mapClass.isInterface()) {
|
||||
if (Map.class.equals(mapClass)) {
|
||||
return new LinkedHashMap<K, V>(capacity);
|
||||
}
|
||||
else if (SortedMap.class.equals(mapType) || NavigableMap.class.equals(mapType)) {
|
||||
else if (SortedMap.class.equals(mapClass) || NavigableMap.class.equals(mapClass)) {
|
||||
return new TreeMap<K, V>();
|
||||
}
|
||||
else if (MultiValueMap.class.equals(mapType)) {
|
||||
else if (MultiValueMap.class.equals(mapClass)) {
|
||||
return new LinkedMultiValueMap();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unsupported Map interface: " + mapType.getName());
|
||||
throw new IllegalArgumentException("Unsupported Map interface: " + mapClass.getName());
|
||||
}
|
||||
}
|
||||
else if (EnumMap.class.equals(mapClass)) {
|
||||
Assert.notNull(keyType, "Cannot create EnumMap for unknown key type");
|
||||
return new EnumMap(keyType);
|
||||
}
|
||||
else {
|
||||
if (!Map.class.isAssignableFrom(mapType)) {
|
||||
throw new IllegalArgumentException("Unsupported Map type: " + mapType.getName());
|
||||
if (!Map.class.isAssignableFrom(mapClass)) {
|
||||
throw new IllegalArgumentException("Unsupported Map type: " + mapClass.getName());
|
||||
}
|
||||
try {
|
||||
return (Map<K, V>) mapType.newInstance();
|
||||
return (Map<K, V>) mapClass.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalArgumentException("Could not instantiate Map type: " +
|
||||
mapType.getName(), ex);
|
||||
throw new IllegalArgumentException(
|
||||
"Could not instantiate Map type: " + mapClass.getName(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
|
|
@ -27,23 +27,27 @@ import org.springframework.core.convert.TypeDescriptor;
|
|||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
|
||||
/**
|
||||
* Converts an Array to a Collection.
|
||||
* Converts an array to a Collection.
|
||||
*
|
||||
* <p>First, creates a new Collection of the requested targetType.
|
||||
* <p>First, creates a new Collection of the requested target type.
|
||||
* 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
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
final class ArrayToCollectionConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final ConversionService conversionService;
|
||||
|
||||
|
||||
public ArrayToCollectionConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
return Collections.singleton(new ConvertiblePair(Object[].class, Collection.class));
|
||||
|
|
@ -60,9 +64,13 @@ final class ArrayToCollectionConverter implements ConditionalGenericConverter {
|
|||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int length = Array.getLength(source);
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), length);
|
||||
if (targetType.getElementTypeDescriptor() == null) {
|
||||
TypeDescriptor elementDesc = targetType.getElementTypeDescriptor();
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(),
|
||||
(elementDesc != null ? elementDesc.getType() : null), length);
|
||||
|
||||
if (elementDesc == null) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object sourceElement = Array.get(source, i);
|
||||
target.add(sourceElement);
|
||||
|
|
@ -72,7 +80,7 @@ final class ArrayToCollectionConverter implements ConditionalGenericConverter {
|
|||
for (int i = 0; i < length; i++) {
|
||||
Object sourceElement = Array.get(source, i);
|
||||
Object targetElement = this.conversionService.convert(sourceElement,
|
||||
sourceType.elementTypeDescriptor(sourceElement), targetType.getElementTypeDescriptor());
|
||||
sourceType.elementTypeDescriptor(sourceElement), elementDesc);
|
||||
target.add(targetElement);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,9 @@ final class CollectionToCollectionConverter implements ConditionalGenericConvert
|
|||
}
|
||||
|
||||
// At this point, we need a collection copy in any case, even if just for finding out about element copies...
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(),
|
||||
(elementDesc != null ? elementDesc.getType() : null), sourceCollection.size());
|
||||
|
||||
if (elementDesc == null) {
|
||||
target.addAll(sourceCollection);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
|||
* map's parameterized types K,V if necessary.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
final class MapToMapConverter implements ConditionalGenericConverter {
|
||||
|
|
@ -64,17 +65,22 @@ final class MapToMapConverter implements ConditionalGenericConverter {
|
|||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
boolean copyRequired = !targetType.getType().isInstance(source);
|
||||
Map<Object, Object> sourceMap = (Map<Object, Object>) source;
|
||||
|
||||
// Shortcut if possible...
|
||||
boolean copyRequired = !targetType.getType().isInstance(source);
|
||||
if (!copyRequired && sourceMap.isEmpty()) {
|
||||
return sourceMap;
|
||||
}
|
||||
TypeDescriptor keyDesc = targetType.getMapKeyTypeDescriptor();
|
||||
TypeDescriptor valueDesc = targetType.getMapValueTypeDescriptor();
|
||||
|
||||
List<MapEntry> targetEntries = new ArrayList<MapEntry>(sourceMap.size());
|
||||
for (Map.Entry<Object, Object> entry : sourceMap.entrySet()) {
|
||||
Object sourceKey = entry.getKey();
|
||||
Object sourceValue = entry.getValue();
|
||||
Object targetKey = convertKey(sourceKey, sourceType, targetType.getMapKeyTypeDescriptor());
|
||||
Object targetValue = convertValue(sourceValue, sourceType, targetType.getMapValueTypeDescriptor());
|
||||
Object targetKey = convertKey(sourceKey, sourceType, keyDesc);
|
||||
Object targetValue = convertValue(sourceValue, sourceType, valueDesc);
|
||||
targetEntries.add(new MapEntry(targetKey, targetValue));
|
||||
if (sourceKey != targetKey || sourceValue != targetValue) {
|
||||
copyRequired = true;
|
||||
|
|
@ -83,7 +89,10 @@ final class MapToMapConverter implements ConditionalGenericConverter {
|
|||
if (!copyRequired) {
|
||||
return sourceMap;
|
||||
}
|
||||
Map<Object, Object> targetMap = CollectionFactory.createMap(targetType.getType(), sourceMap.size());
|
||||
|
||||
Map<Object, Object> targetMap = CollectionFactory.createMap(targetType.getType(),
|
||||
(keyDesc != null ? keyDesc.getType() : null), sourceMap.size());
|
||||
|
||||
for (MapEntry entry : targetEntries) {
|
||||
entry.addToMap(targetMap);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
|
|
@ -37,10 +37,12 @@ final class ObjectToCollectionConverter implements ConditionalGenericConverter {
|
|||
|
||||
private final ConversionService conversionService;
|
||||
|
||||
|
||||
public ObjectToCollectionConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
return Collections.singleton(new ConvertiblePair(Object.class, Collection.class));
|
||||
|
|
@ -56,12 +58,16 @@ final class ObjectToCollectionConverter implements ConditionalGenericConverter {
|
|||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), 1);
|
||||
if (targetType.getElementTypeDescriptor() == null || targetType.getElementTypeDescriptor().isCollection()) {
|
||||
|
||||
TypeDescriptor elementDesc = targetType.getElementTypeDescriptor();
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(),
|
||||
(elementDesc != null ? elementDesc.getType() : null), 1);
|
||||
|
||||
if (elementDesc == null || elementDesc.isCollection()) {
|
||||
target.add(source);
|
||||
}
|
||||
else {
|
||||
Object singleElement = this.conversionService.convert(source, sourceType, targetType.getElementTypeDescriptor());
|
||||
Object singleElement = this.conversionService.convert(source, sourceType, elementDesc);
|
||||
target.add(singleElement);
|
||||
}
|
||||
return target;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import org.springframework.util.StringUtils;
|
|||
* {@code String.class} can be converted to it.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
final class StringToCollectionConverter implements ConditionalGenericConverter {
|
||||
|
|
@ -61,16 +62,20 @@ final class StringToCollectionConverter implements ConditionalGenericConverter {
|
|||
return null;
|
||||
}
|
||||
String string = (String) source;
|
||||
|
||||
String[] fields = StringUtils.commaDelimitedListToStringArray(string);
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), fields.length);
|
||||
if (targetType.getElementTypeDescriptor() == null) {
|
||||
TypeDescriptor elementDesc = targetType.getElementTypeDescriptor();
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(),
|
||||
(elementDesc != null ? elementDesc.getType() : null), fields.length);
|
||||
|
||||
if (elementDesc == null) {
|
||||
for (String field : fields) {
|
||||
target.add(field.trim());
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (String field : fields) {
|
||||
Object targetElement = this.conversionService.convert(field.trim(), sourceType, targetType.getElementTypeDescriptor());
|
||||
Object targetElement = this.conversionService.convert(field.trim(), sourceType, elementDesc);
|
||||
target.add(targetElement);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
|
@ -199,7 +200,7 @@ public class CollectionToCollectionConverterTests {
|
|||
public void listToCollectionNoCopyRequired() throws NoSuchFieldException {
|
||||
List<?> input = new ArrayList<String>(Arrays.asList("foo", "bar"));
|
||||
assertSame(input, conversionService.convert(input, TypeDescriptor.forObject(input),
|
||||
new TypeDescriptor(getClass().getField("wildCardCollection"))));
|
||||
new TypeDescriptor(getClass().getField("wildcardCollection"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -232,7 +233,7 @@ public class CollectionToCollectionConverterTests {
|
|||
assertSame(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
|
||||
}
|
||||
|
||||
@Test(expected=ConverterNotFoundException.class)
|
||||
@Test(expected = ConverterNotFoundException.class)
|
||||
public void elementTypesNotConvertible() throws Exception {
|
||||
List<String> resources = new ArrayList<String>();
|
||||
resources.add(null);
|
||||
|
|
@ -241,7 +242,7 @@ public class CollectionToCollectionConverterTests {
|
|||
assertEquals(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
|
||||
}
|
||||
|
||||
@Test(expected=ConversionFailedException.class)
|
||||
@Test(expected = ConversionFailedException.class)
|
||||
public void nothingInCommon() throws Exception {
|
||||
List<Object> resources = new ArrayList<Object>();
|
||||
resources.add(new ClassPathResource("test"));
|
||||
|
|
@ -250,22 +251,15 @@ public class CollectionToCollectionConverterTests {
|
|||
assertEquals(resources, conversionService.convert(resources, sourceType, new TypeDescriptor(getClass().getField("resources"))));
|
||||
}
|
||||
|
||||
|
||||
public ArrayList<Integer> scalarListTarget;
|
||||
|
||||
public List<Integer> emptyListTarget;
|
||||
|
||||
public LinkedList<Integer> emptyListDifferentTarget;
|
||||
|
||||
public List<List<List<Integer>>> objectToCollection;
|
||||
|
||||
public List<String> strings;
|
||||
|
||||
public List list = Collections.emptyList();
|
||||
|
||||
public Collection<?> wildCardCollection = Collections.emptyList();
|
||||
|
||||
public List<Resource> resources;
|
||||
@Test
|
||||
public void testStringToEnumSet() throws Exception {
|
||||
conversionService.addConverterFactory(new StringToEnumConverterFactory());
|
||||
List<String> list = new ArrayList<String>();
|
||||
list.add("A");
|
||||
list.add("C");
|
||||
assertEquals(EnumSet.of(MyEnum.A, MyEnum.C),
|
||||
conversionService.convert(list, TypeDescriptor.forObject(list), new TypeDescriptor(getClass().getField("enumSet"))));
|
||||
}
|
||||
|
||||
|
||||
public static abstract class BaseResource implements Resource {
|
||||
|
|
@ -335,4 +329,26 @@ public class CollectionToCollectionConverterTests {
|
|||
public static class TestResource extends BaseResource {
|
||||
}
|
||||
|
||||
|
||||
public static enum MyEnum {A, B, C}
|
||||
|
||||
|
||||
public ArrayList<Integer> scalarListTarget;
|
||||
|
||||
public List<Integer> emptyListTarget;
|
||||
|
||||
public LinkedList<Integer> emptyListDifferentTarget;
|
||||
|
||||
public List<List<List<Integer>>> objectToCollection;
|
||||
|
||||
public List<String> strings;
|
||||
|
||||
public List list = Collections.emptyList();
|
||||
|
||||
public Collection<?> wildcardCollection = Collections.emptyList();
|
||||
|
||||
public List<Resource> resources;
|
||||
|
||||
public EnumSet<MyEnum> enumSet;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
|
@ -445,8 +446,6 @@ public class GenericConversionServiceTests {
|
|||
System.out.println(watch.prettyPrint());
|
||||
}
|
||||
|
||||
public static List<Integer> list;
|
||||
|
||||
@Test
|
||||
public void testPerformance3() throws Exception {
|
||||
Assume.group(TestGroup.PERFORMANCE);
|
||||
|
|
@ -473,8 +472,6 @@ public class GenericConversionServiceTests {
|
|||
System.out.println(watch.prettyPrint());
|
||||
}
|
||||
|
||||
public static Map<String, Integer> map;
|
||||
|
||||
@Test
|
||||
public void emptyListToArray() {
|
||||
conversionService.addConverter(new CollectionToArrayConverter(conversionService));
|
||||
|
|
@ -483,7 +480,7 @@ public class GenericConversionServiceTests {
|
|||
TypeDescriptor sourceType = TypeDescriptor.forObject(list);
|
||||
TypeDescriptor targetType = TypeDescriptor.valueOf(String[].class);
|
||||
assertTrue(conversionService.canConvert(sourceType, targetType));
|
||||
assertEquals(0, ((String[])conversionService.convert(list, sourceType, targetType)).length);
|
||||
assertEquals(0, ((String[]) conversionService.convert(list, sourceType, targetType)).length);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -497,82 +494,6 @@ public class GenericConversionServiceTests {
|
|||
assertNull(conversionService.convert(list, sourceType, targetType));
|
||||
}
|
||||
|
||||
private interface MyBaseInterface {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private interface MyInterface extends MyBaseInterface {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class MyInterfaceImplementer implements MyInterface {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class MyBaseInterfaceConverter implements Converter<MyBaseInterface, String> {
|
||||
|
||||
@Override
|
||||
public String convert(MyBaseInterface source) {
|
||||
return "RESULT";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyStringArrayToResourceArrayConverter implements Converter<String[], Resource[]> {
|
||||
|
||||
@Override
|
||||
public Resource[] convert(String[] source) {
|
||||
Resource[] result = new Resource[source.length];
|
||||
for (int i = 0; i < source.length; i++) {
|
||||
result[i] = new DescriptiveResource(source[i].substring(1));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyStringArrayToIntegerArrayConverter implements Converter<String[], Integer[]> {
|
||||
|
||||
@Override
|
||||
public Integer[] convert(String[] source) {
|
||||
Integer[] result = new Integer[source.length];
|
||||
for (int i = 0; i < source.length; i++) {
|
||||
result[i] = Integer.parseInt(source[i].substring(1));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyStringToIntegerArrayConverter implements Converter<String, Integer[]> {
|
||||
|
||||
@Override
|
||||
public Integer[] convert(String source) {
|
||||
String[] srcArray = StringUtils.commaDelimitedListToStringArray(source);
|
||||
Integer[] result = new Integer[srcArray.length];
|
||||
for (int i = 0; i < srcArray.length; i++) {
|
||||
result[i] = Integer.parseInt(srcArray[i].substring(1));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class WithCopyConstructor {
|
||||
|
||||
public WithCopyConstructor() {
|
||||
}
|
||||
|
||||
public WithCopyConstructor(WithCopyConstructor value) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Map<String, ?> wildcardMap;
|
||||
|
||||
@Test
|
||||
public void stringToArrayCanConvert() {
|
||||
conversionService.addConverter(new StringToArrayConverter(conversionService));
|
||||
|
|
@ -585,14 +506,12 @@ public class GenericConversionServiceTests {
|
|||
public void stringToCollectionCanConvert() throws Exception {
|
||||
conversionService.addConverter(new StringToCollectionConverter(conversionService));
|
||||
assertTrue(conversionService.canConvert(String.class, Collection.class));
|
||||
TypeDescriptor targetType = new TypeDescriptor(getClass().getField("stringToCollection"));
|
||||
TypeDescriptor targetType = new TypeDescriptor(getClass().getField("integerCollection"));
|
||||
assertFalse(conversionService.canConvert(TypeDescriptor.valueOf(String.class), targetType));
|
||||
conversionService.addConverterFactory(new StringToNumberConverterFactory());
|
||||
assertTrue(conversionService.canConvert(TypeDescriptor.valueOf(String.class), targetType));
|
||||
}
|
||||
|
||||
public Collection<Integer> stringToCollection;
|
||||
|
||||
@Test
|
||||
public void testConvertiblePairsInSet() {
|
||||
Set<GenericConverter.ConvertiblePair> set = new HashSet<GenericConverter.ConvertiblePair>();
|
||||
|
|
@ -781,6 +700,13 @@ public class GenericConversionServiceTests {
|
|||
assertEquals(MyEnum.A, conversionService.convert("base1", MyEnum.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringToEnumSet() throws Exception {
|
||||
DefaultConversionService.addDefaultConverters(conversionService);
|
||||
assertEquals(EnumSet.of(MyEnum.A),
|
||||
conversionService.convert("A", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("enumSet"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertNullAnnotatedStringToString() throws Exception {
|
||||
DefaultConversionService.addDefaultConverters(conversionService);
|
||||
|
|
@ -870,15 +796,80 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
|
||||
|
||||
@ExampleAnnotation
|
||||
public String annotatedString;
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public static @interface ExampleAnnotation {
|
||||
}
|
||||
|
||||
|
||||
private interface MyBaseInterface {
|
||||
}
|
||||
|
||||
|
||||
private interface MyInterface extends MyBaseInterface {
|
||||
}
|
||||
|
||||
|
||||
private static class MyInterfaceImplementer implements MyInterface {
|
||||
}
|
||||
|
||||
|
||||
private static class MyBaseInterfaceConverter implements Converter<MyBaseInterface, String> {
|
||||
|
||||
@Override
|
||||
public String convert(MyBaseInterface source) {
|
||||
return "RESULT";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyStringArrayToResourceArrayConverter implements Converter<String[], Resource[]> {
|
||||
|
||||
@Override
|
||||
public Resource[] convert(String[] source) {
|
||||
Resource[] result = new Resource[source.length];
|
||||
for (int i = 0; i < source.length; i++) {
|
||||
result[i] = new DescriptiveResource(source[i].substring(1));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyStringArrayToIntegerArrayConverter implements Converter<String[], Integer[]> {
|
||||
|
||||
@Override
|
||||
public Integer[] convert(String[] source) {
|
||||
Integer[] result = new Integer[source.length];
|
||||
for (int i = 0; i < source.length; i++) {
|
||||
result[i] = Integer.parseInt(source[i].substring(1));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MyStringToIntegerArrayConverter implements Converter<String, Integer[]> {
|
||||
|
||||
@Override
|
||||
public Integer[] convert(String source) {
|
||||
String[] srcArray = StringUtils.commaDelimitedListToStringArray(source);
|
||||
Integer[] result = new Integer[srcArray.length];
|
||||
for (int i = 0; i < srcArray.length; i++) {
|
||||
result[i] = Integer.parseInt(srcArray[i].substring(1));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class WithCopyConstructor {
|
||||
|
||||
public WithCopyConstructor() {
|
||||
}
|
||||
|
||||
public WithCopyConstructor(WithCopyConstructor value) {
|
||||
}
|
||||
}
|
||||
private static class MyConditionalConverter implements Converter<String, Color>, ConditionalConverter {
|
||||
|
||||
private int matchAttempts = 0;
|
||||
|
|
@ -1062,6 +1053,7 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
|
||||
private static class StringToMyEnumBaseInterfaceConverter<T extends Enum<?> & MyEnumBaseInterface> implements Converter<String, T> {
|
||||
|
||||
private final Class<T> enumType;
|
||||
|
||||
public StringToMyEnumBaseInterfaceConverter(Class<T> enumType) {
|
||||
|
|
@ -1098,6 +1090,17 @@ public class GenericConversionServiceTests {
|
|||
}
|
||||
|
||||
|
||||
@ExampleAnnotation
|
||||
public String annotatedString;
|
||||
|
||||
public List<Integer> list;
|
||||
|
||||
public Map<String, Integer> map;
|
||||
|
||||
public Map<String, ?> wildcardMap;
|
||||
|
||||
public EnumSet<MyEnum> enumSet;
|
||||
|
||||
public Collection rawCollection;
|
||||
|
||||
public Collection<?> genericCollection;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
|
|
@ -18,6 +18,7 @@ package org.springframework.core.convert.support;
|
|||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
|
@ -39,11 +40,13 @@ public class MapToMapConverterTests {
|
|||
|
||||
private GenericConversionService conversionService = new GenericConversionService();
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
conversionService.addConverter(new MapToMapConverter(conversionService));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void scalarMap() throws Exception {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
|
|
@ -66,8 +69,6 @@ public class MapToMapConverterTests {
|
|||
assertEquals((Integer) 37, result.get(2));
|
||||
}
|
||||
|
||||
public Map<Integer, Integer> scalarMapTarget;
|
||||
|
||||
@Test
|
||||
public void scalarMapNotGenericTarget() throws Exception {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
|
|
@ -99,8 +100,6 @@ public class MapToMapConverterTests {
|
|||
assertEquals((Integer) 37, result.get(2));
|
||||
}
|
||||
|
||||
public Map notGenericMapSource;
|
||||
|
||||
@Test
|
||||
public void collectionMap() throws Exception {
|
||||
Map<String, List<String>> map = new HashMap<String, List<String>>();
|
||||
|
|
@ -124,8 +123,6 @@ public class MapToMapConverterTests {
|
|||
assertEquals(Arrays.asList(37, 23), result.get(2));
|
||||
}
|
||||
|
||||
public Map<Integer, List<Integer>> collectionMapTarget;
|
||||
|
||||
@Test
|
||||
public void collectionMapSourceTarget() throws Exception {
|
||||
Map<String, List<String>> map = new HashMap<String, List<String>>();
|
||||
|
|
@ -137,8 +134,9 @@ public class MapToMapConverterTests {
|
|||
try {
|
||||
conversionService.convert(map, sourceType, targetType);
|
||||
fail("Should have failed");
|
||||
} catch (ConverterNotFoundException e) {
|
||||
|
||||
}
|
||||
catch (ConverterNotFoundException ex) {
|
||||
// expected
|
||||
}
|
||||
conversionService.addConverter(new CollectionToCollectionConverter(conversionService));
|
||||
conversionService.addConverterFactory(new StringToNumberConverterFactory());
|
||||
|
|
@ -150,8 +148,6 @@ public class MapToMapConverterTests {
|
|||
assertEquals(Arrays.asList(37, 23), result.get(2));
|
||||
}
|
||||
|
||||
public Map<String, List<String>> sourceCollectionMapTarget;
|
||||
|
||||
@Test
|
||||
public void collectionMapNotGenericTarget() throws Exception {
|
||||
Map<String, List<String>> map = new HashMap<String, List<String>>();
|
||||
|
|
@ -181,8 +177,6 @@ public class MapToMapConverterTests {
|
|||
assertSame(map, conversionService.convert(map, sourceType, targetType));
|
||||
}
|
||||
|
||||
public Map<String, String> emptyMapTarget;
|
||||
|
||||
@Test
|
||||
public void emptyMapNoTargetGenericInfo() throws Exception {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
|
|
@ -202,8 +196,6 @@ public class MapToMapConverterTests {
|
|||
assertEquals(LinkedHashMap.class, result.getClass());
|
||||
}
|
||||
|
||||
public LinkedHashMap<String, String> emptyMapDifferentTarget;
|
||||
|
||||
@Test
|
||||
public void noDefaultConstructorCopyNotRequired() throws Exception {
|
||||
// SPR-9284
|
||||
|
|
@ -220,8 +212,6 @@ public class MapToMapConverterTests {
|
|||
assertEquals(NoDefaultConstructorMap.class, result.getClass());
|
||||
}
|
||||
|
||||
public MultiValueMap<String, String> multiValueMapTarget;
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void multiValueMapToMultiValueMap() throws Exception {
|
||||
|
|
@ -250,11 +240,46 @@ public class MapToMapConverterTests {
|
|||
assertThat(converted.get("b"), equalTo(Arrays.asList("2")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringToEnumMap() throws Exception {
|
||||
conversionService.addConverterFactory(new StringToEnumConverterFactory());
|
||||
Map<String, Integer> source = new HashMap<String, Integer>();
|
||||
source.put("A", 1);
|
||||
source.put("C", 2);
|
||||
EnumMap<MyEnum, Integer> result = new EnumMap<MyEnum, Integer>(MyEnum.class);
|
||||
result.put(MyEnum.A, 1);
|
||||
result.put(MyEnum.C, 2);
|
||||
assertEquals(result,
|
||||
conversionService.convert(source, TypeDescriptor.forObject(source), new TypeDescriptor(getClass().getField("enumMap"))));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class NoDefaultConstructorMap<K, V> extends HashMap<K, V> {
|
||||
public NoDefaultConstructorMap(Map<? extends K, ? extends V> m) {
|
||||
super(m);
|
||||
|
||||
public NoDefaultConstructorMap(Map<? extends K, ? extends V> map) {
|
||||
super(map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static enum MyEnum {A, B, C}
|
||||
|
||||
|
||||
public Map<Integer, Integer> scalarMapTarget;
|
||||
|
||||
public Map<Integer, List<Integer>> collectionMapTarget;
|
||||
|
||||
public Map<String, List<String>> sourceCollectionMapTarget;
|
||||
|
||||
public Map<String, String> emptyMapTarget;
|
||||
|
||||
public LinkedHashMap<String, String> emptyMapDifferentTarget;
|
||||
|
||||
public MultiValueMap<String, String> multiValueMapTarget;
|
||||
|
||||
public Map notGenericMapSource;
|
||||
|
||||
public EnumMap<MyEnum, Integer> enumMap;
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue