You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tn...@apache.org on 2014/04/17 21:45:56 UTC
svn commit: r1588354 - in /commons/proper/collections/trunk/src:
main/java/org/apache/commons/collections4/
main/java/org/apache/commons/collections4/multimap/
test/java/org/apache/commons/collections4/
test/java/org/apache/commons/collections4/multimap/
Author: tn
Date: Thu Apr 17 19:45:56 2014
New Revision: 1588354
URL: http://svn.apache.org/r1588354
Log:
[COLLECTIONS-508] Further additions.
Added:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiMapUtils.java (with props)
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java (with props)
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java (with props)
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java (with props)
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/ListValuedMap.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiValuedMap.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/SetValuedMap.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/MultiValuedHashMap.java
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/MultiValuedHashMapTest.java
Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/ListValuedMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/ListValuedMap.java?rev=1588354&r1=1588353&r2=1588354&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/ListValuedMap.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/ListValuedMap.java Thu Apr 17 19:45:56 2014
@@ -35,15 +35,14 @@ public interface ListValuedMap<K, V> ext
/**
* Gets the list of values associated with the specified key.
* <p>
- * Implementations typically return <code>null</code> if no values have been
- * mapped to the key, however the implementation may choose to return an
- * empty collection.
- * <p>
- * Implementations may choose to return a clone of the internal collection.
+ * This method will return an <b>empty</b> list if
+ * {@link #containsKey(Object)} returns {@code false}. Changes to the
+ * returned list will update the underlying {@code ListValuedMap} and
+ * vice-versa.
*
* @param key the key to retrieve
- * @return the <code>Collection</code> of values, implementations should
- * return <code>null</code> for no mapping, but may return an empty collection
+ * @return the <code>List</code> of values, implementations should return an
+ * empty list for no mapping
* @throws ClassCastException if the key is of an invalid type
* @throws NullPointerException if the key is null and null keys are invalid
*/
@@ -52,14 +51,13 @@ public interface ListValuedMap<K, V> ext
/**
* Removes all values associated with the specified key.
* <p>
- * Implementations typically return <code>null</code> from a subsequent
- * <code>get(Object)</code>, however they may choose to return an empty
- * collection.
+ * The returned list <i>may</i> be modifiable, but updates will not be
+ * propagated to this list-valued map. In case no mapping was stored for the
+ * specified key, an empty, unmodifiable list will be returned.
*
* @param key the key to remove values from
- * @return the <code>Collection</code> of values removed, implementations
- * should return <code>null</code> for no mapping found, but may
- * return an empty collection
+ * @return the <code>List</code> of values removed, implementations
+ * typically return an empty, unmodifiable List for no mapping found
* @throws UnsupportedOperationException if the map is unmodifiable
* @throws ClassCastException if the key is of an invalid type
* @throws NullPointerException if the key is null and null keys are invalid
Added: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiMapUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiMapUtils.java?rev=1588354&view=auto
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiMapUtils.java (added)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiMapUtils.java Thu Apr 17 19:45:56 2014
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections4;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.collections4.bag.HashBag;
+import org.apache.commons.collections4.multimap.MultiValuedHashMap;
+import org.apache.commons.collections4.multimap.TransformedMultiValuedMap;
+import org.apache.commons.collections4.multimap.UnmodifiableMultiValuedMap;
+
+/**
+ * Provides utility methods and decorators for {@link MultiValuedMap} instances.
+ * <p>
+ * It contains various type safe and null safe methods.
+ * <p>
+ * It also provides the following decorators:
+ *
+ * <ul>
+ * <li>{@link #unmodifiableMultiValuedMap(MultiValuedMap)}</li>
+ * <li>{@link #transformedMultiValuedMap(MultiValuedMap, Transformer, Transformer)}</li>
+ * </ul>
+ *
+ * @since 4.1
+ * @version $Id$
+ */
+public class MultiMapUtils {
+
+ /**
+ * <code>MultiMapUtils</code> should not normally be instantiated.
+ */
+ private MultiMapUtils() {
+ }
+
+ /**
+ * An empty {@link UnmodifiableMultiValuedMap}.
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public static final MultiValuedMap EMPTY_MULTI_VALUED_MAP =
+ UnmodifiableMultiValuedMap.unmodifiableMultiValuedMap(new MultiValuedHashMap());
+
+ /**
+ * Returns immutable EMPTY_MULTI_VALUED_MAP with generic type safety.
+ *
+ * @param <K> the type of key in the map
+ * @param <V> the type of value in the map
+ * @return immutable and empty <code>MultiValuedMap</code>
+ */
+ @SuppressWarnings("unchecked")
+ public static <K, V> MultiValuedMap<K, V> emptyMultiValuedMap() {
+ return EMPTY_MULTI_VALUED_MAP;
+ }
+
+ // Null safe methods
+
+ /**
+ * Returns an immutable empty <code>MultiValuedMap</code> if the argument is
+ * <code>null</code>, or the argument itself otherwise.
+ *
+ * @param <K> the type of key in the map
+ * @param <V> the type of value in the map
+ * @param map the map, possibly <code>null</code>
+ * @return an empty <code>MultiValuedMap</code> if the argument is <code>null</code>
+ */
+ @SuppressWarnings("unchecked")
+ public static <K, V> MultiValuedMap<K, V> emptyIfNull(final MultiValuedMap<K, V> map) {
+ return map == null ? EMPTY_MULTI_VALUED_MAP : map;
+ }
+
+ /**
+ * Null-safe check if the specified <code>MultiValuedMap</code> is empty.
+ * <p>
+ * Null returns true.
+ *
+ * @param map the map to check, may be null
+ * @return true if empty or null
+ */
+ public static boolean isEmpty(final MultiValuedMap<?, ?> map) {
+ return map == null || map.isEmpty();
+ }
+
+ // Null safe getters
+ // -------------------------------------------------------------------------
+
+ /**
+ * Gets a Collection from <code>MultiValuedMap</code> in a null-safe manner.
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @param map the <code>MultiValuedMap</code> to use
+ * @param key the key to look up
+ * @return the Collection in the <code>MultiValuedMap</code>, <code>null</code> if map input is null
+ */
+ public static <K, V> Collection<V> getCollection(final MultiValuedMap<K, V> map, final K key) {
+ if (map != null) {
+ return map.get(key);
+ }
+ return null;
+ }
+
+ /**
+ * Gets a List from <code>MultiValuedMap</code> in a null-safe manner.
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @param map the <code>MultiValuedMap</code> to use
+ * @param key the key to look up
+ * @return the Collection in the <code>MultiValuedMap</code> as List,
+ * <code>null</code> if map input is null
+ */
+ public static <K, V> List<V> getList(MultiValuedMap<K, V> map, K key) {
+ if (map != null) {
+ Collection<V> col = map.get(key);
+ if (col instanceof List) {
+ return (List<V>) col;
+ }
+ return new ArrayList<V>(col);
+ }
+ return null;
+ }
+
+ /**
+ * Gets a Set from <code>MultiValuedMap</code> in a null-safe manner.
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @param map the <code>MultiValuedMap</code> to use
+ * @param key the key to look up
+ * @return the Collection in the <code>MultiValuedMap</code> as Set,
+ * <code>null</code> if map input is null
+ */
+ public static <K, V> Set<V> getSet(MultiValuedMap<K, V> map, K key) {
+ if (map != null) {
+ Collection<V> col = map.get(key);
+ if (col instanceof Set) {
+ return (Set<V>) col;
+ }
+ return new HashSet<V>(col);
+ }
+ return null;
+ }
+
+ /**
+ * Gets a Bag from <code>MultiValuedMap</code> in a null-safe manner.
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @param map the <code>MultiValuedMap</code> to use
+ * @param key the key to look up
+ * @return the Collection in the <code>MultiValuedMap</code> as Bag,
+ * <code>null</code> if map input is null
+ */
+ public static <K, V> Bag<V> getBag(MultiValuedMap<K, V> map, K key) {
+ if (map != null) {
+ Collection<V> col = map.get(key);
+ if (col instanceof Bag) {
+ return (Bag<V>) col;
+ }
+ return new HashBag<V>(col);
+ }
+ return null;
+ }
+
+ // Factory Methods
+ // -----------------------------------------------------------------------
+
+ /**
+ * Creates a {@link ListValuedMap} with a {@link HashMap} as its internal storage.
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @return a new <code>ListValuedMap</code>
+ */
+ public static <K, V> ListValuedMap<K, V> createListValuedHashMap() {
+ return MultiValuedHashMap.<K, V>listValuedHashMap();
+ }
+
+ /**
+ * Creates a {@link ListValuedMap} with a {@link HashMap} as its internal
+ * storage which maps the keys to list of type <code>listClass</code>.
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @param <C> the List class type
+ * @param listClass the class of the list
+ * @return a new <code>ListValuedMap</code>
+ */
+ public static <K, V, C extends List<V>> ListValuedMap<K, V> createListValuedHashMap(final Class<C> listClass) {
+ return MultiValuedHashMap.<K, V, C>listValuedHashMap(listClass);
+ }
+
+ /**
+ * Creates a {@link SetValuedMap} with a {@link HashMap} as its internal
+ * storage
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @return a new <code>SetValuedMap</code>
+ */
+ public static <K, V> SetValuedMap<K, V> createSetValuedHashMap() {
+ return MultiValuedHashMap.<K, V>setValuedHashMap();
+ }
+
+ /**
+ * Creates a {@link SetValuedMap} with a {@link HashMap} as its internal
+ * storage which maps the keys to a set of type <code>setClass</code>
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @param <C> the Set class type
+ * @param setClass the class of the set
+ * @return a new <code>SetValuedMap</code>
+ */
+ public static <K, V, C extends Set<V>> SetValuedMap<K, V> createSetValuedHashMap(final Class<C> setClass) {
+ return MultiValuedHashMap.<K, V, C>setValuedHashMap(setClass);
+ }
+
+ // MultiValuedMap Decorators
+ // -----------------------------------------------------------------------
+
+ /**
+ * Returns an <code>UnmodifiableMultiValuedMap</code> backed by the given
+ * map.
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @param map the <code>MultiValuedMap</code> to make unmodifiable, must not
+ * be null
+ * @return an <code>UnmodifiableMultiValuedMap</code> backed by the given
+ * map
+ * @throws IllegalArgumentException if the map is null
+ */
+ public static <K, V> MultiValuedMap<K, V> unmodifiableMultiValuedMap(
+ final MultiValuedMap<? extends K, ? extends V> map) {
+ return UnmodifiableMultiValuedMap.<K, V>unmodifiableMultiValuedMap(map);
+ }
+
+ /**
+ * Returns a <code>TransformedMultiValuedMap</code> backed by the given map.
+ * <p>
+ * This method returns a new <code>MultiValuedMap</code> (decorating the
+ * specified map) that will transform any new entries added to it. Existing
+ * entries in the specified map will not be transformed. If you want that
+ * behaviour, see {@link TransformedMultiValuedMap#transformedMap}.
+ * <p>
+ * Each object is passed through the transformers as it is added to the Map.
+ * It is important not to use the original map after invoking this method,
+ * as it is a back door for adding untransformed objects.
+ * <p>
+ * If there are any elements already in the map being decorated, they are
+ * NOT transformed.
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @param map the <code>MultiValuedMap</code> to transform, must not be
+ * null, typically empty
+ * @param keyTransformer the transformer for the map keys, null means no
+ * transformation
+ * @param valueTransformer the transformer for the map values, null means no
+ * transformation
+ * @return a transformed <code>MultiValuedMap</code> backed by the given map
+ * @throws IllegalArgumentException if the <code>MultiValuedMap</code> is
+ * null
+ */
+ public static <K, V> MultiValuedMap<K, V> transformedMultiValuedMap(final MultiValuedMap<K, V> map,
+ final Transformer<? super K, ? extends K> keyTransformer,
+ final Transformer<? super V, ? extends V> valueTransformer) {
+ return TransformedMultiValuedMap.transformingMap(map, keyTransformer, valueTransformer);
+ }
+
+}
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiMapUtils.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiMapUtils.java
------------------------------------------------------------------------------
svn:keywords = Id Revision HeadURL
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiMapUtils.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiValuedMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiValuedMap.java?rev=1588354&r1=1588353&r2=1588354&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiValuedMap.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiValuedMap.java Thu Apr 17 19:45:56 2014
@@ -102,15 +102,17 @@ public interface MultiValuedMap<K, V> {
boolean containsMapping(Object key, Object value);
/**
- * Returns a view collection of the values associated with the specified key.
+ * Returns a view collection of the values associated with the specified
+ * key.
* <p>
- * This method will return an <b>empty</b> collection if {@link #containsKey(Object)}
- * returns {@code false}. Changes to the returned collection will update the
- * underlying {@code MultiValuedMap} and vice-versa.
+ * This method will return an <b>empty</b> collection if
+ * {@link #containsKey(Object)} returns {@code false}. Changes to the
+ * returned collection will update the underlying {@code MultiValuedMap} and
+ * vice-versa.
*
* @param key the key to retrieve
* @return the <code>Collection</code> of values, implementations should
- * return <code>null</code> for no mapping, but may return an empty collection
+ * return an empty collection for no mapping
* @throws ClassCastException if the key is of an invalid type (optional)
* @throws NullPointerException if the key is null and null keys are invalid (optional)
*/
@@ -220,8 +222,7 @@ public interface MultiValuedMap<K, V> {
* Other values attached to that key are unaffected.
* <p>
* If the last value for a key is removed, implementations typically return
- * <code>null</code> from a subsequent <code>get(Object)</code>, however
- * they may choose to return an empty collection.
+ * an empty collection from a subsequent <code>get(Object)</code>.
*
* @param key the key to remove from
* @param item the item to remove
Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/SetValuedMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/SetValuedMap.java?rev=1588354&r1=1588353&r2=1588354&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/SetValuedMap.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/SetValuedMap.java Thu Apr 17 19:45:56 2014
@@ -37,16 +37,13 @@ public interface SetValuedMap<K, V> exte
/**
* Gets the set of values associated with the specified key.
* <p>
- * Implementations typically return <code>null</code> if no values have been
- * mapped to the key, however the implementation may choose to return an
- * empty collection.
+ * Implementations typically return an empty <code>Set</code> if no values
+ * have been mapped to the key.
* <p>
- * Implementations may choose to return a clone of the internal collection.
*
* @param key the key to retrieve
- * @return the <code>Set</code> of values, implementations should return
- * <code>null</code> for no mapping, but may return an empty
- * collection
+ * @return the <code>Set</code> of values, implementations should return an
+ * empty Set for no mapping
* @throws ClassCastException if the key is of an invalid type
* @throws NullPointerException if the key is null and null keys are invalid
*/
@@ -55,9 +52,9 @@ public interface SetValuedMap<K, V> exte
/**
* Removes all values associated with the specified key.
* <p>
- * Implementations typically return <code>null</code> from a subsequent
- * <code>get(Object)</code>, however they may choose to return an empty
- * collection.
+ * The returned set <i>may</i> be modifiable, but updates will not be
+ * propagated to this set-valued map. In case no mapping was stored for the
+ * specified key, an empty, unmodifiable set will be returned.
*
* @param key the key to remove values from
* @return the <code>Set</code> of values removed, implementations should
Added: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java?rev=1588354&view=auto
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java (added)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java Thu Apr 17 19:45:56 2014
@@ -0,0 +1,246 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections4.multimap;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.apache.commons.collections4.ListUtils;
+import org.apache.commons.collections4.ListValuedMap;
+
+/**
+ * Abstract implementation of the {@link ListValuedMap} interface to simplify
+ * the creation of subclass implementations.
+ * <p>
+ * Subclasses specify a Map implementation to use as the internal storage and
+ * the List implementation to use as values.
+ *
+ * @since 4.1
+ * @version $Id$
+ */
+public abstract class AbstractListValuedMap<K, V> extends AbstractMultiValuedMap<K, V>
+ implements ListValuedMap<K, V>, Serializable {
+
+ /** The serialization version */
+ private static final long serialVersionUID = 6024950625989666915L;
+
+ /**
+ * A constructor that wraps, not copies
+ *
+ * @param <C> the list type
+ * @param map the map to wrap, must not be null
+ * @param listClazz the collection class
+ * @throws IllegalArgumentException if the map is null
+ */
+ protected <C extends List<V>> AbstractListValuedMap(Map<K, ? super C> map, Class<C> listClazz) {
+ super(map, listClazz);
+ }
+
+ /**
+ * A constructor that wraps, not copies
+ *
+ * @param <C> the list type
+ * @param map the map to wrap, must not be null
+ * @param listClazz the collection class
+ * @param initialListCapacity the initial size of the values list
+ * @throws IllegalArgumentException if the map is null or if
+ * initialListCapacity is negative
+ */
+ protected <C extends List<V>> AbstractListValuedMap(Map<K, ? super C> map, Class<C> listClazz,
+ int initialListCapacity) {
+ super(map, listClazz, initialListCapacity);
+ }
+
+ /**
+ * Gets the list of values associated with the specified key. This would
+ * return an empty list in case the mapping is not present
+ *
+ * @param key the key to retrieve
+ * @return the <code>List</code> of values, will return an empty
+ * <code>List</code> for no mapping
+ * @throws ClassCastException if the key is of an invalid type
+ */
+ @Override
+ public List<V> get(Object key) {
+ return new WrappedList(key);
+ }
+
+ /**
+ * Removes all values associated with the specified key.
+ * <p>
+ * A subsequent <code>get(Object)</code> would return an empty list.
+ *
+ * @param key the key to remove values from
+ * @return the <code>List</code> of values removed, will return an empty,
+ * unmodifiable list for no mapping found.
+ * @throws ClassCastException if the key is of an invalid type
+ */
+ @Override
+ public List<V> remove(Object key) {
+ return ListUtils.emptyIfNull((List<V>) getMap().remove(key));
+ }
+
+ /**
+ * Wrapped list to handle add and remove on the list returned by get(object)
+ */
+ private class WrappedList extends WrappedCollection implements List<V> {
+
+ public WrappedList(Object key) {
+ super(key);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void add(int index, V value) {
+ List<V> list = (List<V>) getMapping();
+ if (list == null) {
+ list = (List<V>) AbstractListValuedMap.this.createCollection();
+ list.add(index, value);
+ getMap().put((K) key, list);
+ }
+ list.add(index, value);
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean addAll(int index, Collection<? extends V> c) {
+ List<V> list = (List<V>) getMapping();
+ if (list == null) {
+ list = (List<V>) createCollection();
+ boolean result = list.addAll(index, c);
+ if (result) {
+ getMap().put((K) key, list);
+ }
+ return result;
+ }
+ return list.addAll(index, c);
+ }
+
+ public V get(int index) {
+ final List<V> list = ListUtils.emptyIfNull((List<V>) getMapping());
+ return list.get(index);
+ }
+
+ public int indexOf(Object o) {
+ final List<V> list = ListUtils.emptyIfNull((List<V>) getMapping());
+ return list.indexOf(o);
+ }
+
+ public int lastIndexOf(Object o) {
+ final List<V> list = ListUtils.emptyIfNull((List<V>) getMapping());
+ return list.indexOf(o);
+ }
+
+ public ListIterator<V> listIterator() {
+ return new ValuesListIterator(key);
+ }
+
+ public ListIterator<V> listIterator(int index) {
+ return new ValuesListIterator(key, index);
+ }
+
+ public V remove(int index) {
+ final List<V> list = ListUtils.emptyIfNull((List<V>) getMapping());
+ V value = list.remove(index);
+ if (list.isEmpty()) {
+ AbstractListValuedMap.this.remove(key);
+ }
+ return value;
+ }
+
+ public V set(int index, V value) {
+ final List<V> list = ListUtils.emptyIfNull((List<V>) getMapping());
+ return list.set(index, value);
+ }
+
+ public List<V> subList(int fromIndex, int toIndex) {
+ final List<V> list = ListUtils.emptyIfNull((List<V>) getMapping());
+ return list.subList(fromIndex, toIndex);
+ }
+
+ }
+
+ /** Values ListItrerator */
+ private class ValuesListIterator implements ListIterator<V>{
+
+ private final Object key;
+
+ private List<V> values;
+ private ListIterator<V> iterator;
+
+ public ValuesListIterator(Object key){
+ this.key = key;
+ this.values = ListUtils.emptyIfNull((List<V>) getMap().get(key));
+ this.iterator = values.listIterator();
+ }
+
+ public ValuesListIterator(Object key, int index){
+ this.key = key;
+ this.values = ListUtils.emptyIfNull((List<V>) getMap().get(key));
+ this.iterator = values.listIterator(index);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void add(V value) {
+ if (getMap().get(key) == null) {
+ List<V> list = (List<V>) createCollection();
+ getMap().put((K) key, list);
+ this.values = list;
+ this.iterator = list.listIterator();
+ }
+ this.iterator.add(value);
+ }
+
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ public boolean hasPrevious() {
+ return iterator.hasPrevious();
+ }
+
+ public V next() {
+ return iterator.next();
+ }
+
+ public int nextIndex() {
+ return iterator.nextIndex();
+ }
+
+ public V previous() {
+ return iterator.previous();
+ }
+
+ public int previousIndex() {
+ return iterator.previousIndex();
+ }
+
+ public void remove() {
+ iterator.remove();
+ if (values.isEmpty()) {
+ getMap().remove(key);
+ }
+ }
+
+ public void set(V value) {
+ iterator.set(value);
+ }
+
+ }
+
+}
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java
------------------------------------------------------------------------------
svn:keywords = Id Revision HeadURL
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java?rev=1588354&r1=1588353&r2=1588354&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java Thu Apr 17 19:45:56 2014
@@ -21,7 +21,6 @@ import java.lang.reflect.Array;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
@@ -95,14 +94,14 @@ public class AbstractMultiValuedMap<K, V
*
* @param <C> the collection type
* @param map the map to wrap, must not be null
- * @param initialCollectionCapacity the initial capacity of the collection
* @param collectionClazz the collection class
+ * @param initialCollectionCapacity the initial capacity of the collection
* @throws IllegalArgumentException if the map is null or if
- * initialCollectionCapacity is negetive
+ * initialCollectionCapacity is negative
*/
@SuppressWarnings("unchecked")
protected <C extends Collection<V>> AbstractMultiValuedMap(final Map<K, ? super C> map,
- int initialCollectionCapacity, final Class<C> collectionClazz) {
+ final Class<C> collectionClazz, final int initialCollectionCapacity) {
if (map == null) {
throw new IllegalArgumentException("Map must not be null");
}
@@ -179,16 +178,15 @@ public class AbstractMultiValuedMap<K, V
/**
* Removes all values associated with the specified key.
* <p>
- * A subsequent <code>get(Object)</code> would return null collection.
+ * A subsequent <code>get(Object)</code> would return an empty collection.
*
* @param key the key to remove values from
- * @return the <code>Collection</code> of values removed, will return
- * <code>null</code> for no mapping found.
+ * @return the <code>Collection</code> of values removed, will return an
+ * empty, unmodifiable collection for no mapping found.
* @throws ClassCastException if the key is of an invalid type
*/
public Collection<V> remove(Object key) {
- Collection<V> coll = getMap().remove(key);
- return coll == null ? Collections.<V>emptyList() : coll;
+ return CollectionUtils.emptyIfNull(getMap().remove(key));
}
/**
@@ -197,7 +195,7 @@ public class AbstractMultiValuedMap<K, V
* The item is removed from the collection mapped to the specified key.
* Other values attached to that key are unaffected.
* <p>
- * If the last value for a key is removed, <code>null</code> would be
+ * If the last value for a key is removed, an empty collection would be
* returned from a subsequent <code>get(Object)</code>.
*
* @param key the key to remove from
@@ -455,15 +453,15 @@ public class AbstractMultiValuedMap<K, V
/**
* Wrapped collection to handle add and remove on the collection returned by get(object)
*/
- private class WrappedCollection implements Collection<V> {
+ protected class WrappedCollection implements Collection<V> {
- private final Object key;
+ protected final Object key;
public WrappedCollection(Object key) {
this.key = key;
}
- private Collection<V> getMapping() {
+ protected Collection<V> getMapping() {
return getMap().get(key);
}
Added: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java?rev=1588354&view=auto
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java (added)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java Thu Apr 17 19:45:56 2014
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections4.multimap;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections4.SetUtils;
+import org.apache.commons.collections4.SetValuedMap;
+
+/**
+ * Abstract implementation of the {@link SetValuedMap} interface to simplify the
+ * creation of subclass implementations.
+ * <p>
+ * Subclasses specify a Map implementation to use as the internal storage and
+ * the Set implementation to use as values.
+ *
+ * @since 4.1
+ * @version $Id$
+ */
+public abstract class AbstractSetValuedMap<K, V> extends AbstractMultiValuedMap<K, V> implements SetValuedMap<K, V> {
+
+ /** Serialization version */
+ private static final long serialVersionUID = 3383617478898639862L;
+
+ /**
+ * A constructor that wraps, not copies
+ *
+ * @param <C> the set type
+ * @param map the map to wrap, must not be null
+ * @param setClazz the collection class
+ * @throws IllegalArgumentException if the map is null
+ */
+ protected <C extends Set<V>> AbstractSetValuedMap(Map<K, ? super C> map, Class<C> setClazz) {
+ super(map, setClazz);
+ }
+
+ /**
+ * A constructor that wraps, not copies
+ *
+ * @param <C> the set type
+ * @param map the map to wrap, must not be null
+ * @param setClazz the collection class
+ * @param initialSetCapacity the initial size of the values set
+ * @throws IllegalArgumentException if the map is null or if
+ * initialSetCapacity is negative
+ */
+ protected <C extends Set<V>> AbstractSetValuedMap(Map<K, ? super C> map, Class<C> setClazz,
+ int initialSetCapacity) {
+ super(map, setClazz, initialSetCapacity);
+ }
+
+ /**
+ * Gets the set of values associated with the specified key. This would
+ * return an empty set in case the mapping is not present
+ *
+ * @param key the key to retrieve
+ * @return the <code>Set</code> of values, will return an empty
+ * <code>Set</code> for no mapping
+ * @throws ClassCastException if the key is of an invalid type
+ */
+ @Override
+ public Set<V> get(Object key) {
+ return new WrappedSet(key);
+ }
+
+ /**
+ * Removes all values associated with the specified key.
+ * <p>
+ * A subsequent <code>get(Object)</code> would return an empty set.
+ *
+ * @param key the key to remove values from
+ * @return the <code>Set</code> of values removed, will return an empty,
+ * unmodifiable set for no mapping found.
+ * @throws ClassCastException if the key is of an invalid type
+ */
+ @Override
+ public Set<V> remove(Object key) {
+ return SetUtils.emptyIfNull((Set<V>) getMap().remove(key));
+ }
+
+ /**
+ * Wrapped set to handle add and remove on the collection returned by
+ * get(object)
+ */
+ protected class WrappedSet extends WrappedCollection implements Set<V> {
+
+ public WrappedSet(Object key) {
+ super(key);
+ }
+
+ }
+
+}
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java
------------------------------------------------------------------------------
svn:keywords = Id Revision HeadURL
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/MultiValuedHashMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/MultiValuedHashMap.java?rev=1588354&r1=1588353&r2=1588354&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/MultiValuedHashMap.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/MultiValuedHashMap.java Thu Apr 17 19:45:56 2014
@@ -19,9 +19,14 @@ package org.apache.commons.collections4.
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
+import org.apache.commons.collections4.ListValuedMap;
import org.apache.commons.collections4.MultiValuedMap;
+import org.apache.commons.collections4.SetValuedMap;
/**
* Implements a {@link MultiValuedMap}, using a {@link HashMap} to provide data
@@ -61,18 +66,59 @@ public class MultiValuedHashMap<K, V> ex
static final float DEFAULT_LOAD_FACTOR = 0.75f;
/**
- * Creates a MultiValuedHashMap which maps keys to collections of type
- * <code>collectionClass</code>.
+ * Creates a {@link ListValuedMap} with a {@link HashMap} as its internal
+ * storage
*
* @param <K> the key type
* @param <V> the value type
- * @param <C> the collection class type
- * @param collectionClass the type of the collection class
- * @return a new MultiValuedMap
- */
- public static <K, V, C extends Collection<V>> MultiValuedMap<K, V> multiValuedMap(
- final Class<C> collectionClass) {
- return new MultiValuedHashMap<K, V>(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, collectionClass);
+ * @return a new <code>ListValuedMap</code>
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static <K, V> ListValuedMap<K, V> listValuedHashMap() {
+ return new ListValuedHashMap(ArrayList.class);
+ }
+
+ /**
+ * Creates a {@link ListValuedMap} with a {@link HashMap} as its internal
+ * storage which maps the keys to list of type <code>listClass</code>
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @param <C> the List class type
+ * @param listClass the class of the list
+ * @return a new <code>ListValuedMap</code>
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static <K, V, C extends List<V>> ListValuedMap<K, V> listValuedHashMap(final Class<C> listClass) {
+ return new ListValuedHashMap(listClass);
+ }
+
+ /**
+ * Creates a {@link SetValuedMap} with a {@link HashMap} as its internal
+ * storage
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @return a new <code>SetValuedMap</code>
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static <K, V> SetValuedMap<K, V> setValuedHashMap() {
+ return new SetValuedHashMap(HashSet.class);
+ }
+
+ /**
+ * Creates a {@link SetValuedMap} with a {@link HashMap} as its internal
+ * storage which maps the keys to a set of type <code>setClass</code>
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @param <C> the Set class type
+ * @param setClass the class of the set
+ * @return a new <code>SetValuedMap</code>
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static <K, V, C extends Set<V>> SetValuedMap<K, V> setValuedHashMap(final Class<C> setClass) {
+ return new SetValuedHashMap(setClass);
}
/**
@@ -122,7 +168,7 @@ public class MultiValuedHashMap<K, V> ex
*/
@SuppressWarnings("unchecked")
public MultiValuedHashMap(int initialCapacity, float loadFactor, int initialCollectionCapacity) {
- this(initialCapacity, loadFactor, initialCollectionCapacity, ArrayList.class);
+ this(initialCapacity, loadFactor, ArrayList.class, initialCollectionCapacity);
}
/**
@@ -178,8 +224,40 @@ public class MultiValuedHashMap<K, V> ex
* create the value collections
*/
protected <C extends Collection<V>> MultiValuedHashMap(int initialCapacity, float loadFactor,
- int initialCollectionCapacity, final Class<C> collectionClazz) {
- super(new HashMap<K, Collection<V>>(initialCapacity, loadFactor), initialCollectionCapacity, collectionClazz);
+ final Class<C> collectionClazz, int initialCollectionCapacity) {
+ super(new HashMap<K, Collection<V>>(initialCapacity, loadFactor), collectionClazz, initialCollectionCapacity);
+ }
+
+ /** Inner class for ListValuedMap */
+ private static class ListValuedHashMap<K, V> extends AbstractListValuedMap<K, V> {
+
+ private static final long serialVersionUID = 3667581458573135234L;
+
+ public <C extends List<V>> ListValuedHashMap(Class<C> listClazz) {
+ super(new HashMap<K, List<V>>(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR), listClazz);
+ }
+
+ public <C extends List<V>> ListValuedHashMap(Class<C> listClazz, int initialListCapacity) {
+ super(new HashMap<K, List<V>>(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR), listClazz,
+ initialListCapacity);
+ }
+
+ }
+
+ /** Inner class for SetValuedMap */
+ private static class SetValuedHashMap<K, V> extends AbstractSetValuedMap<K, V> {
+
+ private static final long serialVersionUID = -3817515514829894543L;
+
+ public <C extends Set<V>> SetValuedHashMap(Class<C> setClazz) {
+ super(new HashMap<K, Set<V>>(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR), setClazz);
+ }
+
+ public <C extends Set<V>> SetValuedHashMap(Class<C> setClazz, int initialSetCapacity) {
+ super(new HashMap<K, Set<V>>(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR), setClazz,
+ initialSetCapacity);
+ }
+
}
}
Added: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java?rev=1588354&view=auto
==============================================================================
--- commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java (added)
+++ commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java Thu Apr 17 19:45:56 2014
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections4;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.collections4.multimap.MultiValuedHashMap;
+
+import junit.framework.Test;
+
+/**
+ * Tests for MultiMapUtils
+ *
+ * @since 4.1
+ * @version $Id$
+ */
+public class MultiMapUtilsTest extends BulkTest {
+
+ public static Test suite() {
+ return BulkTest.makeSuite(MultiMapUtilsTest.class);
+ }
+
+ public MultiMapUtilsTest(String name) {
+ super(name);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public void testEmptyUnmodifiableMultiValuedMap() {
+ final MultiValuedMap map = MultiMapUtils.EMPTY_MULTI_VALUED_MAP;
+ assertTrue(map.isEmpty());
+ try {
+ map.put("key", "value");
+ fail("Should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testTypeSafeEmptyMultiValuedMap() {
+ final MultiValuedMap<String, String> map = MultiMapUtils.<String, String>emptyMultiValuedMap();
+ assertTrue(map.isEmpty());
+ try {
+ map.put("key", "value");
+ fail("Should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testEmptyIfNull() {
+ assertTrue(MultiMapUtils.emptyIfNull(null).isEmpty());
+
+ final MultiValuedMap<String, String> map = new MultiValuedHashMap<String, String>();
+ map.put("item", "value");
+ assertFalse(MultiMapUtils.emptyIfNull(map).isEmpty());
+ }
+
+ public void testIsEmptyWithEmptyMap() {
+ final MultiValuedMap<Object, Object> map = new MultiValuedHashMap<Object, Object>();
+ assertEquals(true, MultiMapUtils.isEmpty(map));
+ }
+
+ public void testIsEmptyWithNonEmptyMap() {
+ final MultiValuedMap<String, String> map = new MultiValuedHashMap<String, String>();
+ map.put("item", "value");
+ assertEquals(false, MultiMapUtils.isEmpty(map));
+ }
+
+ public void testIsEmptyWithNull() {
+ final MultiValuedMap<Object, Object> map = null;
+ assertEquals(true, MultiMapUtils.isEmpty(map));
+ }
+
+ public void testGetCollection() {
+ assertNull(MultiMapUtils.getCollection(null, "key1"));
+
+ String values[] = { "v1", "v2", "v3" };
+ final MultiValuedMap<String, String> map = new MultiValuedHashMap<String, String>();
+ for (String val : values) {
+ map.put("key1", val);
+ }
+
+ Collection<String> col = MultiMapUtils.getCollection(map, "key1");
+ for (String val : values) {
+ assertTrue(col.contains(val));
+ }
+ }
+
+ public void testGetList() {
+ assertNull(MultiMapUtils.getList(null, "key1"));
+
+ String values[] = { "v1", "v2", "v3" };
+ final MultiValuedMap<String, String> map = new MultiValuedHashMap<String, String>();
+ for (String val : values) {
+ map.put("key1", val);
+ }
+
+ List<String> list = MultiMapUtils.getList(map, "key1");
+ int i = 0;
+ for (String val : list) {
+ assertTrue(val.equals(values[i++]));
+ }
+ }
+
+ public void testGetSet() {
+ assertNull(MultiMapUtils.getList(null, "key1"));
+
+ String values[] = { "v1", "v2", "v3" };
+ final MultiValuedMap<String, String> map = new MultiValuedHashMap<String, String>();
+ for (String val : values) {
+ map.put("key1", val);
+ map.put("key1", val);
+ }
+
+ Set<String> set = MultiMapUtils.getSet(map, "key1");
+ assertEquals(3, set.size());
+ for (String val : values) {
+ assertTrue(set.contains(val));
+ }
+ }
+
+ public void testGetBag() {
+ assertNull(MultiMapUtils.getBag(null, "key1"));
+
+ String values[] = { "v1", "v2", "v3" };
+ final MultiValuedMap<String, String> map = new MultiValuedHashMap<String, String>();
+ for (String val : values) {
+ map.put("key1", val);
+ map.put("key1", val);
+ }
+
+ Bag<String> bag = MultiMapUtils.getBag(map, "key1");
+ assertEquals(6, bag.size());
+ for (String val : values) {
+ assertTrue(bag.contains(val));
+ assertEquals(2, bag.getCount(val));
+ }
+ }
+
+}
Propchange: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java
------------------------------------------------------------------------------
svn:keywords = Id Revision HeadURL
Propchange: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java?rev=1588354&r1=1588353&r2=1588354&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java (original)
+++ commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java Thu Apr 17 19:45:56 2014
@@ -43,7 +43,7 @@ import org.apache.commons.collections4.s
* <p>
* To use, extend this class and implement the {@link #makeObject} method and if
* necessary override the {@link #makeFullMap()} method.
- *
+ *
* @since 4.1
* @version $Id$
*/
Modified: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/MultiValuedHashMapTest.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/MultiValuedHashMapTest.java?rev=1588354&r1=1588353&r2=1588354&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/MultiValuedHashMapTest.java (original)
+++ commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/MultiValuedHashMapTest.java Thu Apr 17 19:45:56 2014
@@ -16,17 +16,21 @@
*/
package org.apache.commons.collections4.multimap;
-import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
import junit.framework.Test;
import org.apache.commons.collections4.BulkTest;
+import org.apache.commons.collections4.ListValuedMap;
import org.apache.commons.collections4.MultiValuedMap;
+import org.apache.commons.collections4.SetValuedMap;
/**
* Test MultValuedHashMap
- *
+ *
* @since 4.1
* @version $Id$
*/
@@ -46,41 +50,117 @@ public class MultiValuedHashMapTest<K, V
return m;
}
- /*private <C extends Collection<V>> MultiValuedHashMap<K, V> createTestMap(final Class<C> collectionClass) {
- final MultiValuedHashMap<K, V> map =
- (MultiValuedHashMap<K, V>) MultiValuedHashMap.<K, V, C> multiValuedMap(collectionClass);
- addSampleMappings(map);
- return map;
+ @SuppressWarnings("unchecked")
+ public void testSetValuedMapAdd() {
+ final SetValuedMap<K, V> setMap = MultiValuedHashMap.setValuedHashMap();
+ assertTrue(setMap.get("whatever") instanceof Set);
+
+ Set<V> set = setMap.get("A");
+ assertTrue(set.add((V) "a1"));
+ assertTrue(set.add((V) "a2"));
+ assertFalse(set.add((V) "a1"));
+ assertEquals(2, setMap.size());
+ assertTrue(setMap.containsKey("A"));
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testSetValuedMapRemove() {
+ final SetValuedMap<K, V> setMap = MultiValuedHashMap.setValuedHashMap();
+ assertTrue(setMap.get("whatever") instanceof Set);
+
+ Set<V> set = setMap.get("A");
+ assertTrue(set.add((V) "a1"));
+ assertTrue(set.add((V) "a2"));
+ assertFalse(set.add((V) "a1"));
+ assertEquals(2, setMap.size());
+ assertTrue(setMap.containsKey("A"));
+
+ assertTrue(set.remove("a1"));
+ assertTrue(set.remove("a2"));
+ assertFalse(set.remove("a1"));
+
+ assertEquals(0, setMap.size());
+ assertFalse(setMap.containsKey("A"));
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testSetValuedMapRemoveViaIterator() {
+ final SetValuedMap<K, V> setMap = MultiValuedHashMap.setValuedHashMap();
+ assertTrue(setMap.get("whatever") instanceof Set);
+
+ Set<V> set = setMap.get("A");
+ set.add((V) "a1");
+ set.add((V) "a2");
+ set.add((V) "a1");
+
+ Iterator<V> it = set.iterator();
+ while (it.hasNext()) {
+ it.next();
+ it.remove();
+ }
+ assertEquals(0, setMap.size());
+ assertFalse(setMap.containsKey("A"));
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testListValuedMapAdd() {
+ final ListValuedMap<K, V> listMap = MultiValuedHashMap.listValuedHashMap();
+ assertTrue(listMap.get("whatever") instanceof List);
+ List<V> list = listMap.get("A");
+ list.add((V) "a1");
+ assertEquals(1, listMap.size());
+ assertTrue(listMap.containsKey("A"));
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testListValuedMapAddViaListIterator() {
+ final ListValuedMap<K, V> listMap = MultiValuedHashMap.listValuedHashMap();
+ ListIterator<V> listIt = listMap.get("B").listIterator();
+ assertFalse(listIt.hasNext());
+ listIt.add((V) "b1");
+ listIt.add((V) "b2");
+ listIt.add((V) "b3");
+ assertEquals(3, listMap.size());
+ assertTrue(listMap.containsKey("B"));
+ // As ListIterator always adds before the current cursor
+ assertFalse(listIt.hasNext());
}
@SuppressWarnings("unchecked")
- public void testValueCollectionType() {
- final MultiValuedHashMap<K, V> map = createTestMap(LinkedList.class);
- assertTrue(map.get("one") instanceof LinkedList);
- }*/
-
- @SuppressWarnings("unchecked")
- public void testPutWithList() {
- final MultiValuedHashMap<K, V> test =
- (MultiValuedHashMap<K, V>) MultiValuedHashMap.multiValuedMap(ArrayList.class);
- assertEquals(true, test.put((K) "A", (V) "a"));
- assertEquals(true, test.put((K) "A", (V) "b"));
- assertEquals(true, test.put((K) "A", (V) "a"));
- assertEquals(1, test.keySet().size());
- assertEquals(3, test.get("A").size());
- assertEquals(3, test.size());
+ public void testListValuedMapRemove() {
+ final ListValuedMap<K, V> listMap = MultiValuedHashMap.listValuedHashMap();
+ List<V> list = listMap.get("A");
+ list.add((V) "a1");
+ list.add((V) "a2");
+ list.add((V) "a3");
+ assertEquals(3, listMap.size());
+ assertEquals("a1", list.remove(0));
+ assertEquals(2, listMap.size());
+ assertEquals("a2", list.remove(0));
+ assertEquals(1, listMap.size());
+ assertEquals("a3", list.remove(0));
+ assertEquals(0, listMap.size());
+ assertFalse(listMap.containsKey("A"));
}
@SuppressWarnings("unchecked")
- public void testPutWithSet() {
- final MultiValuedHashMap<K, V> test =
- (MultiValuedHashMap<K, V>) MultiValuedHashMap.multiValuedMap(HashSet.class);
- assertEquals(true, test.put((K) "A", (V) "a"));
- assertEquals(true, test.put((K) "A", (V) "b"));
- assertEquals(false, test.put((K) "A", (V) "a"));
- assertEquals(1, test.keySet().size());
- assertEquals(2, test.get("A").size());
- assertEquals(2, test.size());
+ public void testListValuedMapRemoveViaListIterator() {
+ final ListValuedMap<K, V> listMap = MultiValuedHashMap.listValuedHashMap();
+ ListIterator<V> listIt = listMap.get("B").listIterator();
+ listIt.add((V) "b1");
+ listIt.add((V) "b2");
+ assertEquals(2, listMap.size());
+ assertTrue(listMap.containsKey("B"));
+ listIt = listMap.get("B").listIterator();
+ while (listIt.hasNext()) {
+ listIt.next();
+ listIt.remove();
+ }
+ assertFalse(listMap.containsKey("B"));
+ listIt.add((V) "b1");
+ listIt.add((V) "b2");
+ assertTrue(listMap.containsKey("B"));
+ assertEquals(2, listMap.get("B").size());
}
// public void testCreate() throws Exception {