[COLLECTIONS-508] Improved original contribution after feedback. Thanks to Dipanjan Laha.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@1585335 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
82b547ad25
commit
fc4bd9b4d0
|
@ -284,4 +284,24 @@ public interface MultiValuedMap<K, V> {
|
|||
*/
|
||||
Collection<V> values();
|
||||
|
||||
/**
|
||||
* Returns a {@link Map} view of this MultiValuedMap with a Collection as
|
||||
* its value. The Collection holds all the values mapped to that key.
|
||||
*
|
||||
* @return a Map view of the mappings in this MultiValuedMap
|
||||
*/
|
||||
Map<K, Collection<V>> asMap();
|
||||
|
||||
// Iterators
|
||||
|
||||
/**
|
||||
* Obtains a <code>MapIterator</code> over the map.
|
||||
* <p>
|
||||
* A map iterator is an efficient way of iterating over maps. There is no
|
||||
* need to access the entries collection or use Map Entry objects.
|
||||
*
|
||||
* @return a map iterator
|
||||
*/
|
||||
MapIterator<K, V> mapIterator();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.Set;
|
||||
|
||||
/**
|
||||
* Defines a map that holds a set of values against each key.
|
||||
* <p>
|
||||
* A <code>SetValuedMap</code> is a Map with slightly different semantics:
|
||||
* <ul>
|
||||
* <li>Putting a value into the map will add the value to a <code>Set</code> at
|
||||
* that key.</li>
|
||||
* <li>Getting a value will return a <code>Set</code>, holding all the values
|
||||
* put to that key.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @since 4.1
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface SetValuedMap<K, V> extends MultiValuedMap<K, V> {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <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
|
||||
* @throws ClassCastException if the key is of an invalid type
|
||||
* @throws NullPointerException if the key is null and null keys are invalid
|
||||
*/
|
||||
Set<V> get(Object key);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param key the key to remove values from
|
||||
* @return the <code>Set</code> of values removed, implementations should
|
||||
* return <code>null</code> for no mapping found, but may return an
|
||||
* empty collection
|
||||
* @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
|
||||
*/
|
||||
Set<V> remove(Object key);
|
||||
}
|
|
@ -27,15 +27,20 @@ import java.util.Map.Entry;
|
|||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.collections4.Bag;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.Factory;
|
||||
import org.apache.commons.collections4.IteratorUtils;
|
||||
import org.apache.commons.collections4.MapIterator;
|
||||
import org.apache.commons.collections4.MultiValuedMap;
|
||||
import org.apache.commons.collections4.Transformer;
|
||||
import org.apache.commons.collections4.bag.HashBag;
|
||||
import org.apache.commons.collections4.functors.InstantiateFactory;
|
||||
import org.apache.commons.collections4.iterators.EmptyIterator;
|
||||
import org.apache.commons.collections4.iterators.EmptyMapIterator;
|
||||
import org.apache.commons.collections4.iterators.IteratorChain;
|
||||
import org.apache.commons.collections4.iterators.LazyIteratorChain;
|
||||
import org.apache.commons.collections4.iterators.TransformIterator;
|
||||
import org.apache.commons.collections4.keyvalue.AbstractMapEntry;
|
||||
import org.apache.commons.collections4.set.UnmodifiableSet;
|
||||
|
||||
/**
|
||||
* Abstract implementation of the {@link MultiValuedMap} interface to simplify
|
||||
|
@ -84,6 +89,30 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
this.collectionFactory = new InstantiateFactory<C>(collectionClazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that wraps (not copies).
|
||||
*
|
||||
* @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
|
||||
* @throws IllegalArgumentException if the map is null or if
|
||||
* initialCollectionCapacity is negetive
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <C extends Collection<V>> AbstractMultiValuedMap(final Map<K, ? super C> map,
|
||||
int initialCollectionCapacity, final Class<C> collectionClazz) {
|
||||
if (map == null) {
|
||||
throw new IllegalArgumentException("Map must not be null");
|
||||
}
|
||||
if (initialCollectionCapacity < 0) {
|
||||
throw new IllegalArgumentException("Illegal Capacity: " + initialCollectionCapacity);
|
||||
}
|
||||
this.map = (Map<K, Collection<V>>) map;
|
||||
this.collectionFactory = new InstantiateFactory<C>(collectionClazz, new Class[] { Integer.TYPE },
|
||||
new Object[] { new Integer(initialCollectionCapacity) });
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the map being wrapped.
|
||||
*
|
||||
|
@ -119,7 +148,7 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean containsMapping(Object key, Object value) {
|
||||
final Collection<V> col = get(key);
|
||||
final Collection<V> col = getMap().get(key);
|
||||
if (col == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -134,15 +163,16 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the collection of values associated with the specified key.
|
||||
* Gets the collection of values associated with the specified key. This
|
||||
* would return an empty collection in case the mapping is not present
|
||||
*
|
||||
* @param key the key to retrieve
|
||||
* @return the <code>Collection</code> of values, will return
|
||||
* <code>null</code> for no mapping
|
||||
* @return the <code>Collection</code> of values, will return an empty
|
||||
* <code>Collection</code> for no mapping
|
||||
* @throws ClassCastException if the key is of an invalid type
|
||||
*/
|
||||
public Collection<V> get(Object key) {
|
||||
return getMap().get(key);
|
||||
return new WrappedCollection(key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -174,7 +204,7 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
*/
|
||||
public boolean removeMapping(K key, V item) {
|
||||
boolean result = false;
|
||||
final Collection<V> col = get(key);
|
||||
final Collection<V> col = getMap().get(key);
|
||||
if (col == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -245,7 +275,7 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
*/
|
||||
public V put(K key, V value) {
|
||||
boolean result = false;
|
||||
Collection<V> coll = get(key);
|
||||
Collection<V> coll = getMap().get(key);
|
||||
if (coll == null) {
|
||||
coll = createCollection();
|
||||
coll.add(value);
|
||||
|
@ -312,6 +342,13 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
return keysBagView != null ? keysBagView : (keysBagView = new KeysBag());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Map<K, Collection<V>> asMap() {
|
||||
return getMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Iterable values to the collection associated with the specified key.
|
||||
*
|
||||
|
@ -326,7 +363,7 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
}
|
||||
Iterator<? extends V> it = values.iterator();
|
||||
boolean result = false;
|
||||
Collection<V> coll = get(key);
|
||||
Collection<V> coll = getMap().get(key);
|
||||
if (coll == null) {
|
||||
coll = createCollection(); // might produce a non-empty collection
|
||||
while (it.hasNext()) {
|
||||
|
@ -351,31 +388,13 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets an iterator for the collection mapped to the specified key.
|
||||
*
|
||||
* @param key the key to get an iterator for
|
||||
* @return the iterator of the collection at the key, empty iterator if key
|
||||
* not in map
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Iterator<V> iterator(final Object key) {
|
||||
if (!containsKey(key)) {
|
||||
return EmptyIterator.<V> emptyIterator();
|
||||
public MapIterator<K, V> mapIterator() {
|
||||
if (size() == 0) {
|
||||
return EmptyMapIterator.<K, V>emptyMapIterator();
|
||||
}
|
||||
return new ValuesIterator(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the collection mapped to the specified key.
|
||||
*
|
||||
* @param key the key to get size for
|
||||
* @return the size of the collection at the key, zero if key not in map
|
||||
*/
|
||||
public int size(final Object key) {
|
||||
final Collection<V> coll = get(key);
|
||||
if (coll == null) {
|
||||
return 0;
|
||||
}
|
||||
return coll.size();
|
||||
return new MultiValuedMapIterator();
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
@ -432,6 +451,190 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Wrapped collection to handle add and remove on the collection returned by get(object)
|
||||
*/
|
||||
private class WrappedCollection implements Collection<V> {
|
||||
|
||||
private final Object key;
|
||||
|
||||
public WrappedCollection(Object key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
private Collection<V> getMapping() {
|
||||
return getMap().get(key);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean add(V value) {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
V addedVal = AbstractMultiValuedMap.this.put((K) key, value);
|
||||
return addedVal != null ? true : false;
|
||||
}
|
||||
return col.add(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean addAll(Collection<? extends V> c) {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return AbstractMultiValuedMap.this.putAll((K) key, c);
|
||||
}
|
||||
return col.addAll(c);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col != null) {
|
||||
col.clear();
|
||||
AbstractMultiValuedMap.this.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator<V> iterator() {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return (Iterator<V>) IteratorUtils.EMPTY_ITERATOR;
|
||||
}
|
||||
return new ValuesIterator(key);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return 0;
|
||||
}
|
||||
return col.size();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return false;
|
||||
}
|
||||
return col.contains(o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> o) {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return false;
|
||||
}
|
||||
return col.containsAll(o);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return true;
|
||||
}
|
||||
return col.isEmpty();
|
||||
}
|
||||
|
||||
public boolean remove(Object item) {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = col.remove(item);
|
||||
if (col.isEmpty()) {
|
||||
AbstractMultiValuedMap.this.remove(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = col.removeAll(c);
|
||||
if (col.isEmpty()) {
|
||||
AbstractMultiValuedMap.this.remove(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = col.retainAll(c);
|
||||
if (col.isEmpty()) {
|
||||
AbstractMultiValuedMap.this.remove(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return CollectionUtils.EMPTY_COLLECTION.toArray();
|
||||
}
|
||||
return col.toArray();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T[] toArray(T[] a) {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return (T[]) CollectionUtils.EMPTY_COLLECTION.toArray(a);
|
||||
}
|
||||
return col.toArray(a);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return CollectionUtils.EMPTY_COLLECTION.equals(other);
|
||||
}
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
if(!(other instanceof Collection)){
|
||||
return false;
|
||||
}
|
||||
Collection otherCol = (Collection) other;
|
||||
if (col.size() != otherCol.size()) {
|
||||
return false;
|
||||
}
|
||||
for (Object value : col) {
|
||||
if (!otherCol.contains(value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return CollectionUtils.EMPTY_COLLECTION.hashCode();
|
||||
}
|
||||
return col.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final Collection<V> col = getMapping();
|
||||
if (col == null) {
|
||||
return CollectionUtils.EMPTY_COLLECTION.toString();
|
||||
}
|
||||
return col.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class that provides a Bag<K> keys view
|
||||
*/
|
||||
|
@ -519,7 +722,7 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
}
|
||||
|
||||
public Set<K> uniqueSet() {
|
||||
return keySet();
|
||||
return UnmodifiableSet.<K>unmodifiableSet(keySet());
|
||||
}
|
||||
|
||||
public int size() {
|
||||
|
@ -609,21 +812,9 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
final Transformer<V, Entry<K, V>> entryTransformer = new Transformer<V, Entry<K, V>>() {
|
||||
|
||||
public Entry<K, V> transform(final V input) {
|
||||
return new Entry<K, V>() {
|
||||
|
||||
public K getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public V getValue() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public V setValue(V value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
return new MultiValuedMapEntry(key, input);
|
||||
}
|
||||
|
||||
};
|
||||
return new TransformIterator<V, Entry<K, V>>(new ValuesIterator(key), entryTransformer);
|
||||
}
|
||||
|
@ -637,6 +828,71 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class for MultiValuedMap Entries
|
||||
*/
|
||||
private class MultiValuedMapEntry extends AbstractMapEntry<K, V> {
|
||||
|
||||
public MultiValuedMapEntry(K key, V value) {
|
||||
super(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V setValue(V value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class for MapIterator
|
||||
*/
|
||||
private class MultiValuedMapIterator implements MapIterator<K, V> {
|
||||
|
||||
private final Iterator<Entry<K, V>> it;
|
||||
|
||||
private Entry<K, V> current = null;
|
||||
|
||||
public MultiValuedMapIterator() {
|
||||
this.it = AbstractMultiValuedMap.this.entries().iterator();
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
public K next() {
|
||||
current = it.next();
|
||||
return current.getKey();
|
||||
}
|
||||
|
||||
public K getKey() {
|
||||
if (current == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return current.getKey();
|
||||
}
|
||||
|
||||
public V getValue() {
|
||||
if (current == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return current.getValue();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
it.remove();
|
||||
}
|
||||
|
||||
public V setValue(V value) {
|
||||
if (current == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return current.setValue(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class that provides the values view.
|
||||
*/
|
||||
|
@ -671,7 +927,7 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
|||
|
||||
public ValuesIterator(final Object key) {
|
||||
this.key = key;
|
||||
this.values = get(key);
|
||||
this.values = getMap().get(key);
|
||||
this.iterator = values.iterator();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,14 +23,14 @@ import java.util.Map.Entry;
|
|||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.collections4.Bag;
|
||||
import org.apache.commons.collections4.MapIterator;
|
||||
import org.apache.commons.collections4.MultiValuedMap;
|
||||
|
||||
/**
|
||||
* Decorates another <code>MultiValuedMap</code> to provide additional behaviour.
|
||||
* <p>
|
||||
* Each method call made on this <code>MultiValuedMap</code> is forwarded to the
|
||||
* decorated <code>MultiValuedMap</code>. This class is used as a framework to
|
||||
* build to extensions such as synchronized and unmodifiable behaviour.
|
||||
* Each method call made on this <code>MultiValuedMap</code> is forwarded to the decorated <code>MultiValuedMap</code>.
|
||||
* This class is used as a framework to build to extensions such as synchronized and unmodifiable behaviour.
|
||||
*
|
||||
* @param <K> the type of key elements
|
||||
* @param <V> the type of value elements
|
||||
|
@ -55,7 +55,8 @@ public class AbstractMultiValuedMapDecorator<K, V>
|
|||
*/
|
||||
protected AbstractMultiValuedMapDecorator(final MultiValuedMap<K, V> map) {
|
||||
if (map == null) {
|
||||
throw new IllegalArgumentException("MultiValuedMap must not be null");
|
||||
throw new IllegalArgumentException(
|
||||
"MultiValuedMap must not be null");
|
||||
}
|
||||
this.map = map;
|
||||
}
|
||||
|
@ -120,6 +121,10 @@ public class AbstractMultiValuedMapDecorator<K, V>
|
|||
return decorated().values();
|
||||
}
|
||||
|
||||
public Map<K, Collection<V>> asMap() {
|
||||
return decorated().asMap();
|
||||
}
|
||||
|
||||
public boolean putAll(K key, Iterable<? extends V> values) {
|
||||
return decorated().putAll(key, values);
|
||||
}
|
||||
|
@ -132,6 +137,10 @@ public class AbstractMultiValuedMapDecorator<K, V>
|
|||
decorated().putAll(m);
|
||||
}
|
||||
|
||||
public MapIterator<K, V> mapIterator() {
|
||||
return decorated().mapIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object object) {
|
||||
if (object == this) {
|
||||
|
|
|
@ -50,6 +50,16 @@ public class MultiValuedHashMap<K, V> extends AbstractMultiValuedMap<K, V> imple
|
|||
/** Serialization Version */
|
||||
private static final long serialVersionUID = -5845183518195365857L;
|
||||
|
||||
/**
|
||||
* The initial capacity used when none specified in constructor.
|
||||
*/
|
||||
static final int DEFAULT_INITIAL_CAPACITY = 16;
|
||||
|
||||
/**
|
||||
* The load factor used when none specified in constructor.
|
||||
*/
|
||||
static final float DEFAULT_LOAD_FACTOR = 0.75f;
|
||||
|
||||
/**
|
||||
* Creates a MultiValuedHashMap which maps keys to collections of type
|
||||
* <code>collectionClass</code>.
|
||||
|
@ -62,16 +72,57 @@ public class MultiValuedHashMap<K, V> extends AbstractMultiValuedMap<K, V> imple
|
|||
*/
|
||||
public static <K, V, C extends Collection<V>> MultiValuedMap<K, V> multiValuedMap(
|
||||
final Class<C> collectionClass) {
|
||||
return new MultiValuedHashMap<K, V>(collectionClass);
|
||||
return new MultiValuedHashMap<K, V>(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, collectionClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MultiValueMap based on a <code>HashMap</code> which stores the
|
||||
* multiple values in an <code>ArrayList</code>.
|
||||
* Creates a MultiValueMap based on a <code>HashMap</code> with the default
|
||||
* initial capacity (16) and the default load factor (0.75), which stores
|
||||
* the multiple values in an <code>ArrayList</code>.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public MultiValuedHashMap() {
|
||||
this(ArrayList.class);
|
||||
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, ArrayList.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MultiValueMap based on a <code>HashMap</code> with the initial
|
||||
* capacity and the default load factor (0.75), which stores the multiple
|
||||
* values in an <code>ArrayList</code>.
|
||||
*
|
||||
* @param initialCapacity the initial capacity of the underlying hash map
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public MultiValuedHashMap(int initialCapacity) {
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR, ArrayList.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MultiValueMap based on a <code>HashMap</code> with the initial
|
||||
* capacity and the load factor, which stores the multiple values in an
|
||||
* <code>ArrayList</code>.
|
||||
*
|
||||
* @param initialCapacity the initial capacity of the underlying hash map
|
||||
* @param loadFactor the load factor of the underlying hash map
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public MultiValuedHashMap(int initialCapacity, float loadFactor) {
|
||||
this(initialCapacity, loadFactor, ArrayList.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MultiValueMap based on a <code>HashMap</code> with the initial
|
||||
* capacity and the load factor, which stores the multiple values in an
|
||||
* <code>ArrayList</code> with the initial collection capacity.
|
||||
*
|
||||
* @param initialCapacity the initial capacity of the underlying hash map
|
||||
* @param loadFactor the load factor of the underlying hash map
|
||||
* @param initialCollectionCapacity the initial capacity of the Collection
|
||||
* of values
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public MultiValuedHashMap(int initialCapacity, float loadFactor, int initialCollectionCapacity) {
|
||||
this(initialCapacity, loadFactor, initialCollectionCapacity, ArrayList.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,7 +132,7 @@ public class MultiValuedHashMap<K, V> extends AbstractMultiValuedMap<K, V> imple
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public MultiValuedHashMap(final MultiValuedMap<? extends K, ? extends V> map) {
|
||||
this(ArrayList.class);
|
||||
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, ArrayList.class);
|
||||
super.putAll(map);
|
||||
}
|
||||
|
||||
|
@ -92,7 +143,7 @@ public class MultiValuedHashMap<K, V> extends AbstractMultiValuedMap<K, V> imple
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public MultiValuedHashMap(final Map<? extends K, ? extends V> map) {
|
||||
this(ArrayList.class);
|
||||
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, ArrayList.class);
|
||||
super.putAll(map);
|
||||
}
|
||||
|
||||
|
@ -100,12 +151,35 @@ public class MultiValuedHashMap<K, V> extends AbstractMultiValuedMap<K, V> imple
|
|||
* Creates a MultiValuedHashMap which creates the value collections using
|
||||
* the supplied <code>collectionClazz</code>.
|
||||
*
|
||||
* @param <C> the collection type
|
||||
* @param collectionClazz the class of the <code>Collection</code> to use to
|
||||
* create the value collections
|
||||
* @param initialCapacity the initial capacity of the underlying
|
||||
* <code>HashMap</code>
|
||||
* @param loadFactor the load factor of the underlying <code>HashMap</code>
|
||||
* @param <C> the collection type
|
||||
* @param collectionClazz the class of the <code>Collection</code> to use to
|
||||
* create the value collections
|
||||
*/
|
||||
protected <C extends Collection<V>> MultiValuedHashMap(final Class<C> collectionClazz) {
|
||||
super(new HashMap<K, Collection<V>>(), collectionClazz);
|
||||
protected <C extends Collection<V>> MultiValuedHashMap(int initialCapacity, float loadFactor,
|
||||
final Class<C> collectionClazz) {
|
||||
super(new HashMap<K, Collection<V>>(initialCapacity, loadFactor), collectionClazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MultiValuedHashMap which creates the value collections using
|
||||
* the supplied <code>collectionClazz</code> and the initial collection
|
||||
* capacity .
|
||||
*
|
||||
* @param initialCapacity the initial capacity of the underlying
|
||||
* <code>HashMap</code>
|
||||
* @param loadFactor the load factor of the underlying <code>HashMap</code>
|
||||
* @param initialCollectionCapacity the initial capacity of the
|
||||
* <code>Collection</code>
|
||||
* @param <C> the collection type
|
||||
* @param collectionClazz the class of the <code>Collection</code> to use to
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,10 +22,13 @@ import java.util.Map.Entry;
|
|||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.collections4.Bag;
|
||||
import org.apache.commons.collections4.MapIterator;
|
||||
import org.apache.commons.collections4.MultiValuedMap;
|
||||
import org.apache.commons.collections4.Unmodifiable;
|
||||
import org.apache.commons.collections4.bag.UnmodifiableBag;
|
||||
import org.apache.commons.collections4.collection.UnmodifiableCollection;
|
||||
import org.apache.commons.collections4.iterators.UnmodifiableMapIterator;
|
||||
import org.apache.commons.collections4.map.UnmodifiableMap;
|
||||
import org.apache.commons.collections4.set.UnmodifiableSet;
|
||||
|
||||
/**
|
||||
|
@ -91,6 +94,11 @@ public class UnmodifiableMultiValuedMap<K, V>
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> get(Object key) {
|
||||
return UnmodifiableCollection.<V>unmodifiableCollection(decorated().get(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
@ -116,6 +124,16 @@ public class UnmodifiableMultiValuedMap<K, V>
|
|||
return UnmodifiableCollection.<V>unmodifiableCollection(decorated().values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<K, Collection<V>> asMap() {
|
||||
return UnmodifiableMap.<K, Collection<V>>unmodifiableMap(decorated().asMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapIterator<K, V> mapIterator() {
|
||||
return UnmodifiableMapIterator.<K, V>unmodifiableMapIterator(decorated().mapIterator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putAll(K key, Iterable<? extends V> values) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
|
@ -703,7 +703,7 @@ public abstract class AbstractCollectionTest<E> extends AbstractObjectTest {
|
|||
// make sure calls to "containsAll" don't change anything
|
||||
verify();
|
||||
|
||||
final int min = getFullElements().length < 2 ? 0 : 2;
|
||||
final int min = getFullElements().length < 4 ? 0 : 2;
|
||||
final int max = getFullElements().length == 1 ? 1 :
|
||||
getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
|
||||
col = Arrays.asList(getFullElements()).subList(min, max);
|
||||
|
@ -931,7 +931,7 @@ public abstract class AbstractCollectionTest<E> extends AbstractObjectTest {
|
|||
|
||||
resetFull();
|
||||
final int size = getCollection().size();
|
||||
final int min = getFullElements().length < 2 ? 0 : 2;
|
||||
final int min = getFullElements().length < 4 ? 0 : 2;
|
||||
final int max = getFullElements().length == 1 ? 1 :
|
||||
getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
|
||||
final Collection<E> all = Arrays.asList(getFullElements()).subList(min, max);
|
||||
|
@ -985,7 +985,7 @@ public abstract class AbstractCollectionTest<E> extends AbstractObjectTest {
|
|||
if (getFullElements().length > 1) {
|
||||
resetFull();
|
||||
size = getCollection().size();
|
||||
final int min = getFullElements().length < 2 ? 0 : 2;
|
||||
final int min = getFullElements().length < 4 ? 0 : 2;
|
||||
final int max = getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
|
||||
assertTrue("Collection should changed by partial retainAll",
|
||||
getCollection().retainAll(elements.subList(min, max)));
|
||||
|
|
|
@ -23,11 +23,20 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.collections4.AbstractObjectTest;
|
||||
import org.apache.commons.collections4.Bag;
|
||||
import org.apache.commons.collections4.BulkTest;
|
||||
import org.apache.commons.collections4.MapIterator;
|
||||
import org.apache.commons.collections4.MultiValuedMap;
|
||||
import org.apache.commons.collections4.bag.AbstractBagTest;
|
||||
import org.apache.commons.collections4.bag.CollectionBag;
|
||||
import org.apache.commons.collections4.bag.HashBag;
|
||||
import org.apache.commons.collections4.collection.AbstractCollectionTest;
|
||||
import org.apache.commons.collections4.map.AbstractMapTest;
|
||||
import org.apache.commons.collections4.set.AbstractSetTest;
|
||||
|
||||
/**
|
||||
* Abstract test class for {@link MultiValuedMap} contract and methods.
|
||||
|
@ -40,6 +49,12 @@ import org.apache.commons.collections4.bag.HashBag;
|
|||
*/
|
||||
public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTest {
|
||||
|
||||
/** Map created by reset(). */
|
||||
protected MultiValuedMap<K, V> map;
|
||||
|
||||
/** MultiValuedHashMap created by reset(). */
|
||||
protected MultiValuedMap<K, V> confirmed;
|
||||
|
||||
public AbstractMultiValuedMapTest(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
@ -76,25 +91,108 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the maps produced by {@link #makeObject()} and
|
||||
* {@link #makeFullMap()} supports null keys.
|
||||
* <p>
|
||||
* Default implementation returns true. Override if your collection class
|
||||
* does not support null keys.
|
||||
*/
|
||||
public boolean isAllowNullKey() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of keys in the mappings used to test the map. This method
|
||||
* must return an array with the same length as {@link #getSampleValues()}
|
||||
* and all array elements must be different. The default implementation
|
||||
* constructs a set of String keys, and includes a single null key if
|
||||
* {@link #isAllowNullKey()} returns <code>true</code>.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public K[] getSampleKeys() {
|
||||
final Object[] result = new Object[] {
|
||||
"one", "one", "two", "two",
|
||||
"three", "three"
|
||||
};
|
||||
return (K[]) result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of values in the mappings used to test the map. This
|
||||
* method must return an array with the same length as
|
||||
* {@link #getSampleKeys()}. The default implementation constructs a set of
|
||||
* String values
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public V[] getSampleValues() {
|
||||
final Object[] result = new Object[] {
|
||||
"uno", "un", "dos", "deux",
|
||||
"tres", "trois"
|
||||
};
|
||||
return (V[]) result;
|
||||
}
|
||||
|
||||
protected MultiValuedMap<K, V> makeFullMap() {
|
||||
final MultiValuedMap<K, V> map = makeObject();
|
||||
addSampleMappings(map);
|
||||
return map;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void addSampleMappings(MultiValuedMap<? super K, ? super V> map) {
|
||||
map.put((K) "one", (V) "uno");
|
||||
map.put((K) "one", (V) "un");
|
||||
map.put((K) "two", (V) "dos");
|
||||
map.put((K) "two", (V) "deux");
|
||||
map.put((K) "three", (V) "tres");
|
||||
map.put((K) "three", (V) "trois");
|
||||
final K[] keys = getSampleKeys();
|
||||
final V[] values = getSampleValues();
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
map.put(keys[i], values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void testNoMappingReturnsNull() {
|
||||
/**
|
||||
* Override to return a MultiValuedMap other than MultiValuedHashMap as the
|
||||
* confirmed map.
|
||||
*
|
||||
* @return a MultiValuedMap that is known to be valid
|
||||
*/
|
||||
public MultiValuedMap<K, V> makeConfirmedMap() {
|
||||
return new MultiValuedHashMap<K, V>();
|
||||
}
|
||||
|
||||
public MultiValuedMap<K, V> getConfirmed() {
|
||||
return this.confirmed;
|
||||
}
|
||||
|
||||
public void setConfirmed(MultiValuedMap<K, V> map) {
|
||||
this.confirmed = map;
|
||||
}
|
||||
|
||||
public MultiValuedMap<K, V> getMap() {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the {@link #map} and {@link #confirmed} fields to empty.
|
||||
*/
|
||||
public void resetEmpty() {
|
||||
this.map = makeObject();
|
||||
this.confirmed = makeConfirmedMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the {@link #map} and {@link #confirmed} fields to full.
|
||||
*/
|
||||
public void resetFull() {
|
||||
this.map = makeFullMap();
|
||||
this.confirmed = makeConfirmedMap();
|
||||
final K[] k = getSampleKeys();
|
||||
final V[] v = getSampleValues();
|
||||
for (int i = 0; i < k.length; i++) {
|
||||
confirmed.put(k[i], v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void testNoMappingReturnsEmptyCol() {
|
||||
final MultiValuedMap<K, V> map = makeFullMap();
|
||||
assertNull(map.get("whatever"));
|
||||
assertTrue(map.get("whatever").isEmpty());
|
||||
}
|
||||
|
||||
public void testMultipleValues() {
|
||||
|
@ -114,6 +212,69 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
|||
assertTrue(map.get("three").contains("trois"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testAddMappingThroughGet(){
|
||||
if (!isAddSupported()) {
|
||||
return;
|
||||
}
|
||||
resetEmpty();
|
||||
final MultiValuedMap<K, V> map = getMap();
|
||||
Collection<V> col1 = map.get("one");
|
||||
Collection<V> col2 = map.get("one");
|
||||
assertTrue(col1.isEmpty());
|
||||
assertTrue(col2.isEmpty());
|
||||
assertEquals(0, map.size());
|
||||
col1.add((V) "uno");
|
||||
col2.add((V) "un");
|
||||
assertTrue(map.containsKey("one"));
|
||||
assertTrue(map.containsMapping("one", "uno"));
|
||||
assertTrue(map.containsMapping("one", "un"));
|
||||
assertTrue(map.containsValue("uno"));
|
||||
assertTrue(map.containsValue("un"));
|
||||
assertTrue(col1.contains("un"));
|
||||
assertTrue(col2.contains("uno"));
|
||||
}
|
||||
|
||||
public void testRemoveMappingThroughGet() {
|
||||
if (!isRemoveSupported()) {
|
||||
return;
|
||||
}
|
||||
resetFull();
|
||||
final MultiValuedMap<K, V> map = getMap();
|
||||
Collection<V> col = map.get("one");
|
||||
assertEquals(2, col.size());
|
||||
assertEquals(6, map.size());
|
||||
col.remove("uno");
|
||||
col.remove("un");
|
||||
assertFalse(map.containsKey("one"));
|
||||
assertFalse(map.containsMapping("one", "uno"));
|
||||
assertFalse(map.containsMapping("one", "un"));
|
||||
assertFalse(map.containsValue("uno"));
|
||||
assertFalse(map.containsValue("un"));
|
||||
assertEquals(4, map.size());
|
||||
assertNull(map.remove("one"));
|
||||
}
|
||||
|
||||
public void testRemoveMappingThroughGetIterator() {
|
||||
if (!isRemoveSupported()) {
|
||||
return;
|
||||
}
|
||||
resetFull();
|
||||
final MultiValuedMap<K, V> map = getMap();
|
||||
Iterator<V> it = map.get("one").iterator();
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
it.remove();
|
||||
}
|
||||
assertFalse(map.containsKey("one"));
|
||||
assertFalse(map.containsMapping("one", "uno"));
|
||||
assertFalse(map.containsMapping("one", "un"));
|
||||
assertFalse(map.containsValue("uno"));
|
||||
assertFalse(map.containsValue("un"));
|
||||
assertEquals(4, map.size());
|
||||
assertNull(map.remove("one"));
|
||||
}
|
||||
|
||||
public void testContainsValue() {
|
||||
final MultiValuedMap<K, V> map = makeFullMap();
|
||||
assertTrue(map.containsValue("uno"));
|
||||
|
@ -158,7 +319,7 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
|||
// assertEquals(expected, actual);
|
||||
// }
|
||||
|
||||
public void testRemoveAllViaIterator() {
|
||||
public void testRemoveAllViaValuesIterator() {
|
||||
if (!isRemoveSupported()) {
|
||||
return;
|
||||
}
|
||||
|
@ -167,10 +328,34 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
|||
i.next();
|
||||
i.remove();
|
||||
}
|
||||
assertNull(map.get("one"));
|
||||
assertTrue(map.get("one").isEmpty());
|
||||
assertTrue(map.isEmpty());
|
||||
}
|
||||
|
||||
public void testRemoveViaValuesRemove() {
|
||||
if (!isRemoveSupported()) {
|
||||
return;
|
||||
}
|
||||
final MultiValuedMap<K, V> map = makeFullMap();
|
||||
Collection<V> values = map.values();
|
||||
values.remove("uno");
|
||||
values.remove("un");
|
||||
assertFalse(map.containsKey("one"));
|
||||
assertEquals(4, map.size());
|
||||
}
|
||||
|
||||
/*public void testRemoveViaGetCollectionRemove() {
|
||||
if (!isRemoveSupported()) {
|
||||
return;
|
||||
}
|
||||
final MultiValuedMap<K, V> map = makeFullMap();
|
||||
Collection<V> values = map.get("one");
|
||||
values.remove("uno");
|
||||
values.remove("un");
|
||||
assertFalse(map.containsKey("one"));
|
||||
assertEquals(4, map.size());
|
||||
}*/
|
||||
|
||||
// public void testRemoveAllViaKeyedIterator() {
|
||||
// if (!isRemoveSupported()) {
|
||||
// return;
|
||||
|
@ -210,7 +395,7 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
|||
i.next();
|
||||
i.remove();
|
||||
}
|
||||
assertNull(map.get("one"));
|
||||
assertTrue(map.get("one").isEmpty());
|
||||
assertEquals(0, map.size());
|
||||
}
|
||||
|
||||
|
@ -459,11 +644,93 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
|||
assertTrue(keyBag.containsAll(col));
|
||||
}
|
||||
|
||||
// public void testMapEqulas() {
|
||||
// MultiValuedMap<K, V> map1 = makeFullMap();
|
||||
// MultiValuedMap<K, V> map2 = makeFullMap();
|
||||
// assertEquals(true, map1.equals(map2));
|
||||
// }
|
||||
public void testAsMapGet() {
|
||||
resetEmpty();
|
||||
Map<K, Collection<V>> mapCol = getMap().asMap();
|
||||
assertNull(mapCol.get("one"));
|
||||
assertEquals(0, mapCol.size());
|
||||
|
||||
resetFull();
|
||||
mapCol = getMap().asMap();
|
||||
Collection<V> col = mapCol.get("one");
|
||||
assertNotNull(col);
|
||||
assertTrue(col.contains("un"));
|
||||
assertTrue(col.contains("uno"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testAsMapPut() {
|
||||
if (!isAddSupported()) {
|
||||
return;
|
||||
}
|
||||
resetEmpty();
|
||||
Map<K, Collection<V>> mapCol = getMap().asMap();
|
||||
Collection<V> col = (Collection<V>) Arrays.asList("un", "uno");
|
||||
mapCol.put((K) "one", col);
|
||||
assertEquals(2, getMap().size());
|
||||
assertTrue(getMap().containsKey("one"));
|
||||
assertTrue(getMap().containsValue("un"));
|
||||
assertTrue(getMap().containsValue("uno"));
|
||||
|
||||
resetFull();
|
||||
mapCol = getMap().asMap();
|
||||
col = mapCol.get("one");
|
||||
col.add((V) "one");
|
||||
assertEquals(7, getMap().size());
|
||||
assertTrue(getMap().containsValue("one"));
|
||||
assertTrue(getMap().containsValue("un"));
|
||||
assertTrue(getMap().containsValue("uno"));
|
||||
}
|
||||
|
||||
public void testAsMapRemove() {
|
||||
if (!isRemoveSupported()) {
|
||||
return;
|
||||
}
|
||||
resetFull();
|
||||
Map<K, Collection<V>> mapCol = getMap().asMap();
|
||||
mapCol.remove("one");
|
||||
assertFalse(getMap().containsKey("one"));
|
||||
assertEquals(4, getMap().size());
|
||||
}
|
||||
|
||||
public void testMapIterator() {
|
||||
resetEmpty();
|
||||
MapIterator<K, V> mapIt = getMap().mapIterator();
|
||||
assertFalse(mapIt.hasNext());
|
||||
|
||||
resetFull();
|
||||
mapIt = getMap().mapIterator();
|
||||
while (mapIt.hasNext()) {
|
||||
K key = mapIt.next();
|
||||
V value = mapIt.getValue();
|
||||
assertTrue(getMap().containsMapping(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
public void testMapIteratorRemove() {
|
||||
if (!isRemoveSupported()) {
|
||||
return;
|
||||
}
|
||||
resetFull();
|
||||
MapIterator<K, V> mapIt = getMap().mapIterator();
|
||||
while (mapIt.hasNext()) {
|
||||
mapIt.next();
|
||||
mapIt.remove();
|
||||
}
|
||||
assertTrue(getMap().isEmpty());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testMapIteratorUnsupportedSet() {
|
||||
resetFull();
|
||||
MapIterator<K, V> mapIt = getMap().mapIterator();
|
||||
mapIt.next();
|
||||
try {
|
||||
mapIt.setValue((V) "some value");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Manual serialization testing as this class cannot easily
|
||||
|
@ -472,13 +739,15 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
|||
|
||||
public void testEmptyMapCompatibility() throws Exception {
|
||||
final MultiValuedMap<?, ?> map = makeObject();
|
||||
final MultiValuedMap<?, ?> map2 = (MultiValuedMap<?, ?>) readExternalFormFromDisk(getCanonicalEmptyCollectionName(map));
|
||||
final MultiValuedMap<?, ?> map2 =
|
||||
(MultiValuedMap<?, ?>) readExternalFormFromDisk(getCanonicalEmptyCollectionName(map));
|
||||
assertEquals("Map is empty", 0, map2.size());
|
||||
}
|
||||
|
||||
public void testFullMapCompatibility() throws Exception {
|
||||
final MultiValuedMap<?, ?> map = (MultiValuedMap<?, ?>) makeFullMap();
|
||||
final MultiValuedMap<?, ?> map2 = (MultiValuedMap<?, ?>) readExternalFormFromDisk(getCanonicalFullCollectionName(map));
|
||||
final MultiValuedMap<?, ?> map2 =
|
||||
(MultiValuedMap<?, ?>) readExternalFormFromDisk(getCanonicalFullCollectionName(map));
|
||||
assertEquals("Map is the right size", map.size(), map2.size());
|
||||
for (final Object key : map.keySet()) {
|
||||
assertEquals("Map had inequal elements", map.get(key), map2.get(key));
|
||||
|
@ -491,4 +760,371 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
|||
}
|
||||
}
|
||||
|
||||
// Bulk Tests
|
||||
/**
|
||||
* Bulk test {@link MultiValuedMap#entries()}. This method runs through all
|
||||
* of the tests in {@link AbstractCollectionTest}. After modification
|
||||
* operations, {@link #verify()} is invoked to ensure that the map and the
|
||||
* other collection views are still valid.
|
||||
*
|
||||
* @return a {@link AbstractCollectionTest} instance for testing the map's
|
||||
* values collection
|
||||
*/
|
||||
public BulkTest bulkTestMultiValuedMapEntries() {
|
||||
return new TestMultiValuedMapEntries();
|
||||
}
|
||||
|
||||
public class TestMultiValuedMapEntries extends AbstractCollectionTest<Entry<K, V>> {
|
||||
public TestMultiValuedMapEntries() {
|
||||
super("");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Entry<K, V>[] getFullElements() {
|
||||
return makeFullMap().entries().toArray(new Entry[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Entry<K, V>> makeObject() {
|
||||
return AbstractMultiValuedMapTest.this.makeObject().entries();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Entry<K, V>> makeFullCollection() {
|
||||
return AbstractMultiValuedMapTest.this.makeFullMap().entries();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullSupported() {
|
||||
return AbstractMultiValuedMapTest.this.isAllowNullKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAddSupported() {
|
||||
// Add not supported in entries view
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemoveSupported() {
|
||||
return AbstractMultiValuedMapTest.this.isRemoveSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTestSerialization() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetFull() {
|
||||
AbstractMultiValuedMapTest.this.resetFull();
|
||||
setCollection(AbstractMultiValuedMapTest.this.getMap().entries());
|
||||
TestMultiValuedMapEntries.this.setConfirmed(AbstractMultiValuedMapTest.this.getConfirmed().entries());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetEmpty() {
|
||||
AbstractMultiValuedMapTest.this.resetEmpty();
|
||||
setCollection(AbstractMultiValuedMapTest.this.getMap().entries());
|
||||
TestMultiValuedMapEntries.this.setConfirmed(AbstractMultiValuedMapTest.this.getConfirmed().entries());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Entry<K, V>> makeConfirmedCollection() {
|
||||
// never gets called, reset methods are overridden
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Entry<K, V>> makeConfirmedFullCollection() {
|
||||
// never gets called, reset methods are overridden
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk test {@link MultiValuedMap#keySet()}. This method runs through all
|
||||
* of the tests in {@link AbstractSetTest}. After modification operations,
|
||||
* {@link #verify()} is invoked to ensure that the map and the other
|
||||
* collection views are still valid.
|
||||
*
|
||||
* @return a {@link AbstractSetTest} instance for testing the map's key set
|
||||
*/
|
||||
public BulkTest bulkTestMultiValuedMapKeySet() {
|
||||
return new TestMultiValuedMapKeySet();
|
||||
}
|
||||
|
||||
public class TestMultiValuedMapKeySet extends AbstractSetTest<K> {
|
||||
public TestMultiValuedMapKeySet() {
|
||||
super("");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public K[] getFullElements() {
|
||||
return (K[]) AbstractMultiValuedMapTest.this.makeFullMap().keySet().toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<K> makeObject() {
|
||||
return AbstractMultiValuedMapTest.this.makeObject().keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<K> makeFullCollection() {
|
||||
return AbstractMultiValuedMapTest.this.makeFullMap().keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullSupported() {
|
||||
return AbstractMultiValuedMapTest.this.isAllowNullKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAddSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemoveSupported() {
|
||||
return AbstractMultiValuedMapTest.this.isRemoveSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTestSerialization() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk test {@link MultiValuedMap#values()}. This method runs through all
|
||||
* of the tests in {@link AbstractCollectionTest}. After modification
|
||||
* operations, {@link #verify()} is invoked to ensure that the map and the
|
||||
* other collection views are still valid.
|
||||
*
|
||||
* @return a {@link AbstractCollectionTest} instance for testing the map's
|
||||
* values collection
|
||||
*/
|
||||
public BulkTest bulkTestMultiValuedMapValues() {
|
||||
return new TestMultiValuedMapValues();
|
||||
}
|
||||
|
||||
public class TestMultiValuedMapValues extends AbstractCollectionTest<V> {
|
||||
public TestMultiValuedMapValues() {
|
||||
super("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public V[] getFullElements() {
|
||||
return getSampleValues();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> makeObject() {
|
||||
return AbstractMultiValuedMapTest.this.makeObject().values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> makeFullCollection() {
|
||||
return AbstractMultiValuedMapTest.this.makeFullMap().values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullSupported() {
|
||||
return AbstractMultiValuedMapTest.this.isAllowNullKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAddSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemoveSupported() {
|
||||
return AbstractMultiValuedMapTest.this.isRemoveSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTestSerialization() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetFull() {
|
||||
AbstractMultiValuedMapTest.this.resetFull();
|
||||
setCollection(AbstractMultiValuedMapTest.this.getMap().values());
|
||||
TestMultiValuedMapValues.this.setConfirmed(AbstractMultiValuedMapTest.this.getConfirmed().values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetEmpty() {
|
||||
AbstractMultiValuedMapTest.this.resetEmpty();
|
||||
setCollection(AbstractMultiValuedMapTest.this.getMap().values());
|
||||
TestMultiValuedMapValues.this.setConfirmed(AbstractMultiValuedMapTest.this.getConfirmed().values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> makeConfirmedCollection() {
|
||||
// never gets called, reset methods are overridden
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> makeConfirmedFullCollection() {
|
||||
// never gets called, reset methods are overridden
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk test {@link MultiValuedMap#keys()}. This method runs through all of
|
||||
* the tests in {@link AbstractBagTest}. After modification operations,
|
||||
* {@link #verify()} is invoked to ensure that the map and the other
|
||||
* collection views are still valid.
|
||||
*
|
||||
* @return a {@link AbstractBagTest} instance for testing the map's values
|
||||
* collection
|
||||
*/
|
||||
public BulkTest bulkTestMultiValuedMapKeys() {
|
||||
return new TestMultiValuedMapKeys();
|
||||
}
|
||||
|
||||
public class TestMultiValuedMapKeys extends AbstractBagTest<K> {
|
||||
|
||||
public TestMultiValuedMapKeys() {
|
||||
super("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public K[] getFullElements() {
|
||||
return getSampleKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bag<K> makeObject() {
|
||||
return AbstractMultiValuedMapTest.this.makeObject().keys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bag<K> makeFullCollection() {
|
||||
return AbstractMultiValuedMapTest.this.makeFullMap().keys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullSupported() {
|
||||
return AbstractMultiValuedMapTest.this.isAllowNullKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAddSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemoveSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTestSerialization() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetFull() {
|
||||
AbstractMultiValuedMapTest.this.resetFull();
|
||||
// wrapping with CollectionBag as otherwise the Collection tests
|
||||
// would fail
|
||||
setCollection(CollectionBag.<K>collectionBag(AbstractMultiValuedMapTest.this.getMap().keys()));
|
||||
TestMultiValuedMapKeys.this.setConfirmed(AbstractMultiValuedMapTest.this.getConfirmed().keys());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetEmpty() {
|
||||
AbstractMultiValuedMapTest.this.resetEmpty();
|
||||
setCollection(CollectionBag.<K>collectionBag(AbstractMultiValuedMapTest.this.getMap().keys()));
|
||||
TestMultiValuedMapKeys.this.setConfirmed(AbstractMultiValuedMapTest.this.getConfirmed().keys());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public BulkTest bulkTestAsMap() {
|
||||
return new TestMultiValuedMapAsMap();
|
||||
}
|
||||
|
||||
public class TestMultiValuedMapAsMap extends AbstractMapTest<K, Collection<V>> {
|
||||
|
||||
public TestMultiValuedMapAsMap() {
|
||||
super("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<K, Collection<V>> makeObject() {
|
||||
return AbstractMultiValuedMapTest.this.makeObject().asMap();
|
||||
}
|
||||
|
||||
public Map<K, Collection<V>> makeFullMap() {
|
||||
return AbstractMultiValuedMapTest.this.makeFullMap().asMap();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public K[] getSampleKeys() {
|
||||
K[] samplekeys = AbstractMultiValuedMapTest.this.getSampleKeys();
|
||||
Object[] finalKeys = new Object[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
finalKeys[i] = samplekeys[i * 2];
|
||||
}
|
||||
return (K[]) finalKeys;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<V>[] getSampleValues() {
|
||||
V[] sampleValues = AbstractMultiValuedMapTest.this.getSampleValues();
|
||||
Collection<V>[] colArr = new Collection[3];
|
||||
for(int i = 0; i < 3; i++) {
|
||||
colArr[i] = Arrays.asList(sampleValues[i*2], sampleValues[i*2 + 1]);
|
||||
}
|
||||
return colArr;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<V>[] getNewSampleValues() {
|
||||
Object[] sampleValues = { "ein", "ek", "zwei", "duey", "drei", "teen" };
|
||||
Collection<V>[] colArr = new Collection[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
colArr[i] = Arrays.asList((V) sampleValues[i * 2], (V) sampleValues[i * 2 + 1]);
|
||||
}
|
||||
return colArr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowNullKey() {
|
||||
return AbstractMultiValuedMapTest.this.isAllowNullKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPutAddSupported() {
|
||||
return AbstractMultiValuedMapTest.this.isAddSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPutChangeSupported() {
|
||||
return AbstractMultiValuedMapTest.this.isAddSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemoveSupported() {
|
||||
return AbstractMultiValuedMapTest.this.isRemoveSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTestSerialization() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,11 @@
|
|||
package org.apache.commons.collections4.multimap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.commons.collections4.BulkTest;
|
||||
import org.apache.commons.collections4.MultiValuedMap;
|
||||
|
||||
/**
|
||||
|
@ -35,13 +36,17 @@ public class MultiValuedHashMapTest<K, V> extends AbstractMultiValuedMapTest<K,
|
|||
super(testName);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return BulkTest.makeSuite(MultiValuedHashMapTest.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiValuedMap<K, V> makeObject() {
|
||||
final MultiValuedMap<K, V> m = new MultiValuedHashMap<K, V>();
|
||||
return m;
|
||||
}
|
||||
|
||||
private <C extends Collection<V>> MultiValuedHashMap<K, V> createTestMap(final Class<C> collectionClass) {
|
||||
/*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);
|
||||
|
@ -52,26 +57,28 @@ public class MultiValuedHashMapTest<K, V> extends AbstractMultiValuedMapTest<K,
|
|||
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);
|
||||
final MultiValuedHashMap<K, V> test =
|
||||
(MultiValuedHashMap<K, V>) MultiValuedHashMap.multiValuedMap(ArrayList.class);
|
||||
assertEquals("a", test.put((K) "A", (V) "a"));
|
||||
assertEquals("b", test.put((K) "A", (V) "b"));
|
||||
assertEquals(1, test.keySet().size());
|
||||
assertEquals(2, test.size("A"));
|
||||
assertEquals(2, test.get("A").size());
|
||||
assertEquals(2, test.size());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testPutWithSet() {
|
||||
final MultiValuedHashMap<K, V> test = (MultiValuedHashMap<K, V>) MultiValuedHashMap.multiValuedMap(HashSet.class);
|
||||
final MultiValuedHashMap<K, V> test =
|
||||
(MultiValuedHashMap<K, V>) MultiValuedHashMap.multiValuedMap(HashSet.class);
|
||||
assertEquals("a", test.put((K) "A", (V) "a"));
|
||||
assertEquals("b", test.put((K) "A", (V) "b"));
|
||||
assertEquals(null, test.put((K) "A", (V) "a"));
|
||||
assertEquals(1, test.keySet().size());
|
||||
assertEquals(2, test.size("A"));
|
||||
assertEquals(2, test.get("A").size());
|
||||
assertEquals(2, test.size());
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
*/
|
||||
package org.apache.commons.collections4.multimap;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.commons.collections4.BulkTest;
|
||||
import org.apache.commons.collections4.MultiValuedMap;
|
||||
import org.apache.commons.collections4.Transformer;
|
||||
import org.apache.commons.collections4.TransformerUtils;
|
||||
|
@ -34,6 +37,10 @@ public class TransformedMultiValuedMapTest<K, V> extends AbstractMultiValuedMapT
|
|||
super(testName);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return BulkTest.makeSuite(TransformedMultiValuedMapTest.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiValuedMap<K, V> makeObject() {
|
||||
return TransformedMultiValuedMap.transformingMap(new MultiValuedHashMap<K, V>(),
|
||||
|
|
|
@ -16,6 +16,18 @@
|
|||
*/
|
||||
package org.apache.commons.collections4.multimap;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.commons.collections4.Bag;
|
||||
import org.apache.commons.collections4.BulkTest;
|
||||
import org.apache.commons.collections4.MapIterator;
|
||||
import org.apache.commons.collections4.MultiValuedMap;
|
||||
import org.apache.commons.collections4.Unmodifiable;
|
||||
|
||||
|
@ -31,6 +43,10 @@ public class UnmodifiableMultiValuedMapTest<K, V> extends AbstractMultiValuedMap
|
|||
super(testName);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return BulkTest.makeSuite(UnmodifiableMultiValuedMapTest.class);
|
||||
}
|
||||
|
||||
public boolean isAddSupported() {
|
||||
return false;
|
||||
}
|
||||
|
@ -78,6 +94,167 @@ public class UnmodifiableMultiValuedMapTest<K, V> extends AbstractMultiValuedMap
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testUnmodifiableEntries() {
|
||||
resetFull();
|
||||
Collection<Entry<K, V>> entries = getMap().entries();
|
||||
try {
|
||||
entries.clear();
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
Iterator<Entry<K, V>> it = entries.iterator();
|
||||
Entry<K, V> entry = it.next();
|
||||
try {
|
||||
it.remove();
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
entry.setValue((V) "three");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testUnmodifiableMapIterator() {
|
||||
resetFull();
|
||||
MapIterator<K, V> mapIt = getMap().mapIterator();
|
||||
try {
|
||||
mapIt.remove();
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
mapIt.setValue((V) "three");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testUnmodifiableKeySet() {
|
||||
resetFull();
|
||||
Set<K> keySet = getMap().keySet();
|
||||
try {
|
||||
keySet.add((K) "four");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
keySet.remove("four");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
keySet.clear();
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
Iterator<K> it = keySet.iterator();
|
||||
try {
|
||||
it.remove();
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testUnmodifiableValues() {
|
||||
resetFull();
|
||||
Collection<V> values = getMap().values();
|
||||
try {
|
||||
values.add((V) "four");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
values.remove("four");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
values.clear();
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
Iterator<V> it = values.iterator();
|
||||
try {
|
||||
it.remove();
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testUnmodifiableAsMap() {
|
||||
resetFull();
|
||||
Map<K, Collection<V>> mapCol = getMap().asMap();
|
||||
try {
|
||||
mapCol.put((K) "four", (Collection<V>) Arrays.asList("four"));
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
mapCol.remove("four");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
mapCol.clear();
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
mapCol.clear();
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testUnmodifiableKeys() {
|
||||
resetFull();
|
||||
Bag<K> keys = getMap().keys();
|
||||
try {
|
||||
keys.add((K) "four");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
keys.remove("four");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
keys.clear();
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
|
||||
Iterator<K> it = keys.iterator();
|
||||
try {
|
||||
it.remove();
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
}
|
||||
|
||||
// public void testCreate() throws Exception {
|
||||
// writeExternalFormToDisk((java.io.Serializable) makeObject(),
|
||||
// "src/test/resources/data/test/UnmodifiableMultiValuedMap.emptyCollection.version4.1.obj");
|
||||
|
|
Loading…
Reference in New Issue