diff --git a/spring-core/src/main/java/org/springframework/core/CollectionFactory.java b/spring-core/src/main/java/org/springframework/core/CollectionFactory.java
index 998bd813e49..39994a3d76d 100644
--- a/spring-core/src/main/java/org/springframework/core/CollectionFactory.java
+++ b/spring-core/src/main/java/org/springframework/core/CollectionFactory.java
@@ -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.
- *
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 Collection createApproximateCollection(Object collection, int initialCapacity) {
+ public static Collection createApproximateCollection(Object collection, int capacity) {
if (collection instanceof LinkedList) {
return new LinkedList();
}
else if (collection instanceof List) {
- return new ArrayList(initialCapacity);
+ return new ArrayList(capacity);
+ }
+ else if (collection instanceof EnumSet) {
+ return EnumSet.copyOf((Collection) collection);
}
else if (collection instanceof SortedSet) {
return new TreeSet(((SortedSet) collection).comparator());
}
else {
- return new LinkedHashSet(initialCapacity);
+ return new LinkedHashSet(capacity);
}
}
/**
* Create the most appropriate collection for the given collection type.
- *
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
+ *
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 Collection 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 Collection createCollection(Class> collectionType, int initialCapacity) {
- if (collectionType.isInterface()) {
- if (List.class.equals(collectionType)) {
- return new ArrayList(initialCapacity);
+ public static Collection createCollection(Class> collectionClass, Class> elementType, int capacity) {
+ if (collectionClass.isInterface()) {
+ if (Set.class.equals(collectionClass) || Collection.class.equals(collectionClass)) {
+ return new LinkedHashSet(capacity);
}
- else if (SortedSet.class.equals(collectionType) || NavigableSet.class.equals(collectionType)) {
- return new TreeSet();
+ else if (List.class.equals(collectionClass)) {
+ return new ArrayList(capacity);
}
- else if (Set.class.equals(collectionType) || Collection.class.equals(collectionType)) {
- return new LinkedHashSet(initialCapacity);
+ else if (SortedSet.class.equals(collectionClass) || NavigableSet.class.equals(collectionClass)) {
+ return new TreeSet();
}
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) collectionType.newInstance();
+ return (Collection) 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.
- *
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 Map createApproximateMap(Object map, int initialCapacity) {
- if (map instanceof SortedMap) {
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public static Map createApproximateMap(Object map, int capacity) {
+ if (map instanceof EnumMap) {
+ return new EnumMap((Map) map);
+ }
+ else if (map instanceof SortedMap) {
return new TreeMap(((SortedMap) map).comparator());
}
else {
- return new LinkedHashMap(initialCapacity);
+ return new LinkedHashMap(capacity);
}
}
/**
* Create the most approximate map for the given map.
- *
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
+ *
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
+ */
+ public static Map 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.TreeMap
* @see java.util.LinkedHashMap
+ * @see java.util.TreeMap
+ * @see java.util.EnumMap
+ * @see org.springframework.util.LinkedMultiValueMap
*/
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static Map createMap(Class> mapType, int initialCapacity) {
- if (mapType.isInterface()) {
- if (Map.class.equals(mapType)) {
- return new LinkedHashMap(initialCapacity);
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public static Map createMap(Class> mapClass, Class> keyType, int capacity) {
+ if (mapClass.isInterface()) {
+ if (Map.class.equals(mapClass)) {
+ return new LinkedHashMap(capacity);
}
- else if (SortedMap.class.equals(mapType) || NavigableMap.class.equals(mapType)) {
+ else if (SortedMap.class.equals(mapClass) || NavigableMap.class.equals(mapClass)) {
return new TreeMap();
}
- 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) mapType.newInstance();
+ return (Map) 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);
}
}
}
diff --git a/spring-core/src/main/java/org/springframework/core/convert/support/ArrayToCollectionConverter.java b/spring-core/src/main/java/org/springframework/core/convert/support/ArrayToCollectionConverter.java
index 30f3de5593d..22373712694 100644
--- a/spring-core/src/main/java/org/springframework/core/convert/support/ArrayToCollectionConverter.java
+++ b/spring-core/src/main/java/org/springframework/core/convert/support/ArrayToCollectionConverter.java
@@ -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.
*
- *
First, creates a new Collection of the requested targetType.
+ *
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 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