diff --git a/org.springframework.core/src/main/java/org/springframework/util/CollectionUtils.java b/org.springframework.core/src/main/java/org/springframework/util/CollectionUtils.java index a6d87b323c..5d57fbba6b 100644 --- a/org.springframework.core/src/main/java/org/springframework/util/CollectionUtils.java +++ b/org.springframework.core/src/main/java/org/springframework/util/CollectionUtils.java @@ -16,14 +16,19 @@ package org.springframework.util; +import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; /** * Miscellaneous collection utility methods. @@ -31,6 +36,7 @@ import java.util.Properties; * * @author Juergen Hoeller * @author Rob Harrop + * @author Arjen Poutsma * @since 1.1.3 */ public abstract class CollectionUtils { @@ -323,6 +329,35 @@ public abstract class CollectionUtils { return new EnumerationIterator(enumeration); } + /** + * Adapts a {@code Map>} to an {@code MultiValueMap}. + * + * @param map the map + * @return the multi-value map + */ + public static MultiValueMap toMultiValueMap(Map> map) { + return new MultiValueMapAdapter(map); + + } + + /** + * Returns an unmodifiable view of the specified multi-value map. + * + * @param map the map for which an unmodifiable view is to be returned. + * @return an unmodifiable view of the specified multi-value map. + */ + public static MultiValueMap unmodifiableMultiValueMap(MultiValueMap map) { + Assert.notNull(map, "'map' must not be null"); + Map> result = new LinkedHashMap>(map.size()); + for (Map.Entry> entry : map.entrySet()) { + List values = Collections.unmodifiableList(entry.getValue()); + result.put(entry.getKey(), values); + } + Map> unmodifiableMap = Collections.unmodifiableMap(result); + return toMultiValueMap(unmodifiableMap); + } + + /** * Iterator wrapping an Enumeration. @@ -348,4 +383,117 @@ public abstract class CollectionUtils { } } + /** + * Adapts a Map to the MultiValueMap contract. + */ + private static class MultiValueMapAdapter implements MultiValueMap, Serializable { + + private final Map> map; + + public MultiValueMapAdapter(Map> map) { + Assert.notNull(map, "'map' must not be null"); + this.map = map; + } + + public void add(K key, V value) { + List values = this.map.get(key); + if (values == null) { + values = new LinkedList(); + this.map.put(key, values); + } + values.add(value); + } + + public V getFirst(K key) { + List values = this.map.get(key); + return (values != null ? values.get(0) : null); + } + + public void set(K key, V value) { + List values = new LinkedList(); + values.add(value); + this.map.put(key, values); + } + + public void setAll(Map values) { + for (Entry entry : values.entrySet()) { + set(entry.getKey(), entry.getValue()); + } + } + + public Map toSingleValueMap() { + LinkedHashMap singleValueMap = new LinkedHashMap(this.map.size()); + for (Entry> entry : map.entrySet()) { + singleValueMap.put(entry.getKey(), entry.getValue().get(0)); + } + return singleValueMap; + } + + public int size() { + return this.map.size(); + } + + public boolean isEmpty() { + return this.map.isEmpty(); + } + + public boolean containsKey(Object key) { + return this.map.containsKey(key); + } + + public boolean containsValue(Object value) { + return this.map.containsValue(value); + } + + public List get(Object key) { + return this.map.get(key); + } + + public List put(K key, List value) { + return this.map.put(key, value); + } + + public List remove(Object key) { + return this.map.remove(key); + } + + public void putAll(Map> m) { + this.map.putAll(m); + } + + public void clear() { + this.map.clear(); + } + + public Set keySet() { + return this.map.keySet(); + } + + public Collection> values() { + return this.map.values(); + } + + public Set>> entrySet() { + return this.map.entrySet(); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + return map.equals(other); + } + + @Override + public int hashCode() { + return this.map.hashCode(); + } + + @Override + public String toString() { + return this.map.toString(); + } + } + }