[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();
|
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 java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.collections4.Bag;
|
import org.apache.commons.collections4.Bag;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.collections4.Factory;
|
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.MultiValuedMap;
|
||||||
import org.apache.commons.collections4.Transformer;
|
import org.apache.commons.collections4.Transformer;
|
||||||
import org.apache.commons.collections4.bag.HashBag;
|
import org.apache.commons.collections4.bag.HashBag;
|
||||||
import org.apache.commons.collections4.functors.InstantiateFactory;
|
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.IteratorChain;
|
||||||
import org.apache.commons.collections4.iterators.LazyIteratorChain;
|
import org.apache.commons.collections4.iterators.LazyIteratorChain;
|
||||||
import org.apache.commons.collections4.iterators.TransformIterator;
|
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
|
* 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);
|
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.
|
* Gets the map being wrapped.
|
||||||
*
|
*
|
||||||
|
@ -119,7 +148,7 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public boolean containsMapping(Object key, Object value) {
|
public boolean containsMapping(Object key, Object value) {
|
||||||
final Collection<V> col = get(key);
|
final Collection<V> col = getMap().get(key);
|
||||||
if (col == null) {
|
if (col == null) {
|
||||||
return false;
|
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
|
* @param key the key to retrieve
|
||||||
* @return the <code>Collection</code> of values, will return
|
* @return the <code>Collection</code> of values, will return an empty
|
||||||
* <code>null</code> for no mapping
|
* <code>Collection</code> for no mapping
|
||||||
* @throws ClassCastException if the key is of an invalid type
|
* @throws ClassCastException if the key is of an invalid type
|
||||||
*/
|
*/
|
||||||
public Collection<V> get(Object key) {
|
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) {
|
public boolean removeMapping(K key, V item) {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
final Collection<V> col = get(key);
|
final Collection<V> col = getMap().get(key);
|
||||||
if (col == null) {
|
if (col == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -245,7 +275,7 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
||||||
*/
|
*/
|
||||||
public V put(K key, V value) {
|
public V put(K key, V value) {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
Collection<V> coll = get(key);
|
Collection<V> coll = getMap().get(key);
|
||||||
if (coll == null) {
|
if (coll == null) {
|
||||||
coll = createCollection();
|
coll = createCollection();
|
||||||
coll.add(value);
|
coll.add(value);
|
||||||
|
@ -312,6 +342,13 @@ public class AbstractMultiValuedMap<K, V> implements MultiValuedMap<K, V>, Seria
|
||||||
return keysBagView != null ? keysBagView : (keysBagView = new KeysBag());
|
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.
|
* 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();
|
Iterator<? extends V> it = values.iterator();
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
Collection<V> coll = get(key);
|
Collection<V> coll = getMap().get(key);
|
||||||
if (coll == null) {
|
if (coll == null) {
|
||||||
coll = createCollection(); // might produce a non-empty collection
|
coll = createCollection(); // might produce a non-empty collection
|
||||||
while (it.hasNext()) {
|
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.
|
* {@inheritDoc}
|
||||||
*
|
|
||||||
* @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
|
|
||||||
*/
|
*/
|
||||||
public Iterator<V> iterator(final Object key) {
|
public MapIterator<K, V> mapIterator() {
|
||||||
if (!containsKey(key)) {
|
if (size() == 0) {
|
||||||
return EmptyIterator.<V> emptyIterator();
|
return EmptyMapIterator.<K, V>emptyMapIterator();
|
||||||
}
|
}
|
||||||
return new ValuesIterator(key);
|
return new MultiValuedMapIterator();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@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
|
* 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() {
|
public Set<K> uniqueSet() {
|
||||||
return keySet();
|
return UnmodifiableSet.<K>unmodifiableSet(keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
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>>() {
|
final Transformer<V, Entry<K, V>> entryTransformer = new Transformer<V, Entry<K, V>>() {
|
||||||
|
|
||||||
public Entry<K, V> transform(final V input) {
|
public Entry<K, V> transform(final V input) {
|
||||||
return new Entry<K, V>() {
|
return new MultiValuedMapEntry(key, input);
|
||||||
|
|
||||||
public K getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public V getValue() {
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
public V setValue(V value) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
return new TransformIterator<V, Entry<K, V>>(new ValuesIterator(key), entryTransformer);
|
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.
|
* 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) {
|
public ValuesIterator(final Object key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.values = get(key);
|
this.values = getMap().get(key);
|
||||||
this.iterator = values.iterator();
|
this.iterator = values.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,14 @@ import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.collections4.Bag;
|
import org.apache.commons.collections4.Bag;
|
||||||
|
import org.apache.commons.collections4.MapIterator;
|
||||||
import org.apache.commons.collections4.MultiValuedMap;
|
import org.apache.commons.collections4.MultiValuedMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decorates another <code>MultiValuedMap</code> to provide additional behaviour.
|
* Decorates another <code>MultiValuedMap</code> to provide additional behaviour.
|
||||||
* <p>
|
* <p>
|
||||||
* Each method call made on this <code>MultiValuedMap</code> is forwarded to the
|
* Each method call made on this <code>MultiValuedMap</code> is forwarded to the decorated <code>MultiValuedMap</code>.
|
||||||
* decorated <code>MultiValuedMap</code>. This class is used as a framework to
|
* This class is used as a framework to build to extensions such as synchronized and unmodifiable behaviour.
|
||||||
* build to extensions such as synchronized and unmodifiable behaviour.
|
|
||||||
*
|
*
|
||||||
* @param <K> the type of key elements
|
* @param <K> the type of key elements
|
||||||
* @param <V> the type of value elements
|
* @param <V> the type of value elements
|
||||||
|
@ -55,7 +55,8 @@ public class AbstractMultiValuedMapDecorator<K, V>
|
||||||
*/
|
*/
|
||||||
protected AbstractMultiValuedMapDecorator(final MultiValuedMap<K, V> map) {
|
protected AbstractMultiValuedMapDecorator(final MultiValuedMap<K, V> map) {
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
throw new IllegalArgumentException("MultiValuedMap must not be null");
|
throw new IllegalArgumentException(
|
||||||
|
"MultiValuedMap must not be null");
|
||||||
}
|
}
|
||||||
this.map = map;
|
this.map = map;
|
||||||
}
|
}
|
||||||
|
@ -120,6 +121,10 @@ public class AbstractMultiValuedMapDecorator<K, V>
|
||||||
return decorated().values();
|
return decorated().values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<K, Collection<V>> asMap() {
|
||||||
|
return decorated().asMap();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean putAll(K key, Iterable<? extends V> values) {
|
public boolean putAll(K key, Iterable<? extends V> values) {
|
||||||
return decorated().putAll(key, values);
|
return decorated().putAll(key, values);
|
||||||
}
|
}
|
||||||
|
@ -132,6 +137,10 @@ public class AbstractMultiValuedMapDecorator<K, V>
|
||||||
decorated().putAll(m);
|
decorated().putAll(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MapIterator<K, V> mapIterator() {
|
||||||
|
return decorated().mapIterator();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object object) {
|
public boolean equals(final Object object) {
|
||||||
if (object == this) {
|
if (object == this) {
|
||||||
|
|
|
@ -50,6 +50,16 @@ public class MultiValuedHashMap<K, V> extends AbstractMultiValuedMap<K, V> imple
|
||||||
/** Serialization Version */
|
/** Serialization Version */
|
||||||
private static final long serialVersionUID = -5845183518195365857L;
|
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
|
* Creates a MultiValuedHashMap which maps keys to collections of type
|
||||||
* <code>collectionClass</code>.
|
* <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(
|
public static <K, V, C extends Collection<V>> MultiValuedMap<K, V> multiValuedMap(
|
||||||
final Class<C> collectionClass) {
|
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
|
* Creates a MultiValueMap based on a <code>HashMap</code> with the default
|
||||||
* multiple values in an <code>ArrayList</code>.
|
* initial capacity (16) and the default load factor (0.75), which stores
|
||||||
|
* the multiple values in an <code>ArrayList</code>.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public MultiValuedHashMap() {
|
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")
|
@SuppressWarnings("unchecked")
|
||||||
public MultiValuedHashMap(final MultiValuedMap<? extends K, ? extends V> map) {
|
public MultiValuedHashMap(final MultiValuedMap<? extends K, ? extends V> map) {
|
||||||
this(ArrayList.class);
|
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, ArrayList.class);
|
||||||
super.putAll(map);
|
super.putAll(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +143,7 @@ public class MultiValuedHashMap<K, V> extends AbstractMultiValuedMap<K, V> imple
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public MultiValuedHashMap(final Map<? extends K, ? extends V> map) {
|
public MultiValuedHashMap(final Map<? extends K, ? extends V> map) {
|
||||||
this(ArrayList.class);
|
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, ArrayList.class);
|
||||||
super.putAll(map);
|
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
|
* Creates a MultiValuedHashMap which creates the value collections using
|
||||||
* the supplied <code>collectionClazz</code>.
|
* the supplied <code>collectionClazz</code>.
|
||||||
*
|
*
|
||||||
* @param <C> the collection type
|
* @param initialCapacity the initial capacity of the underlying
|
||||||
* @param collectionClazz the class of the <code>Collection</code> to use to
|
* <code>HashMap</code>
|
||||||
* create the value collections
|
* @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) {
|
protected <C extends Collection<V>> MultiValuedHashMap(int initialCapacity, float loadFactor,
|
||||||
super(new HashMap<K, Collection<V>>(), collectionClazz);
|
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 java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.collections4.Bag;
|
import org.apache.commons.collections4.Bag;
|
||||||
|
import org.apache.commons.collections4.MapIterator;
|
||||||
import org.apache.commons.collections4.MultiValuedMap;
|
import org.apache.commons.collections4.MultiValuedMap;
|
||||||
import org.apache.commons.collections4.Unmodifiable;
|
import org.apache.commons.collections4.Unmodifiable;
|
||||||
import org.apache.commons.collections4.bag.UnmodifiableBag;
|
import org.apache.commons.collections4.bag.UnmodifiableBag;
|
||||||
import org.apache.commons.collections4.collection.UnmodifiableCollection;
|
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;
|
import org.apache.commons.collections4.set.UnmodifiableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,6 +94,11 @@ public class UnmodifiableMultiValuedMap<K, V>
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<V> get(Object key) {
|
||||||
|
return UnmodifiableCollection.<V>unmodifiableCollection(decorated().get(key));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V put(K key, V value) {
|
public V put(K key, V value) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
@ -116,6 +124,16 @@ public class UnmodifiableMultiValuedMap<K, V>
|
||||||
return UnmodifiableCollection.<V>unmodifiableCollection(decorated().values());
|
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
|
@Override
|
||||||
public boolean putAll(K key, Iterable<? extends V> values) {
|
public boolean putAll(K key, Iterable<? extends V> values) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|
|
@ -703,7 +703,7 @@ public abstract class AbstractCollectionTest<E> extends AbstractObjectTest {
|
||||||
// make sure calls to "containsAll" don't change anything
|
// make sure calls to "containsAll" don't change anything
|
||||||
verify();
|
verify();
|
||||||
|
|
||||||
final int min = getFullElements().length < 2 ? 0 : 2;
|
final int min = getFullElements().length < 4 ? 0 : 2;
|
||||||
final int max = getFullElements().length == 1 ? 1 :
|
final int max = getFullElements().length == 1 ? 1 :
|
||||||
getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
|
getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
|
||||||
col = Arrays.asList(getFullElements()).subList(min, max);
|
col = Arrays.asList(getFullElements()).subList(min, max);
|
||||||
|
@ -931,7 +931,7 @@ public abstract class AbstractCollectionTest<E> extends AbstractObjectTest {
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
final int size = getCollection().size();
|
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 :
|
final int max = getFullElements().length == 1 ? 1 :
|
||||||
getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
|
getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
|
||||||
final Collection<E> all = Arrays.asList(getFullElements()).subList(min, max);
|
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) {
|
if (getFullElements().length > 1) {
|
||||||
resetFull();
|
resetFull();
|
||||||
size = getCollection().size();
|
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;
|
final int max = getFullElements().length <= 5 ? getFullElements().length - 1 : 5;
|
||||||
assertTrue("Collection should changed by partial retainAll",
|
assertTrue("Collection should changed by partial retainAll",
|
||||||
getCollection().retainAll(elements.subList(min, max)));
|
getCollection().retainAll(elements.subList(min, max)));
|
||||||
|
|
|
@ -23,11 +23,20 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.collections4.AbstractObjectTest;
|
import org.apache.commons.collections4.AbstractObjectTest;
|
||||||
import org.apache.commons.collections4.Bag;
|
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.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.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.
|
* 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 {
|
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) {
|
public AbstractMultiValuedMapTest(String testName) {
|
||||||
super(testName);
|
super(testName);
|
||||||
}
|
}
|
||||||
|
@ -76,25 +91,108 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
||||||
return true;
|
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() {
|
protected MultiValuedMap<K, V> makeFullMap() {
|
||||||
final MultiValuedMap<K, V> map = makeObject();
|
final MultiValuedMap<K, V> map = makeObject();
|
||||||
addSampleMappings(map);
|
addSampleMappings(map);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected void addSampleMappings(MultiValuedMap<? super K, ? super V> map) {
|
protected void addSampleMappings(MultiValuedMap<? super K, ? super V> map) {
|
||||||
map.put((K) "one", (V) "uno");
|
final K[] keys = getSampleKeys();
|
||||||
map.put((K) "one", (V) "un");
|
final V[] values = getSampleValues();
|
||||||
map.put((K) "two", (V) "dos");
|
for (int i = 0; i < keys.length; i++) {
|
||||||
map.put((K) "two", (V) "deux");
|
map.put(keys[i], values[i]);
|
||||||
map.put((K) "three", (V) "tres");
|
}
|
||||||
map.put((K) "three", (V) "trois");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
final MultiValuedMap<K, V> map = makeFullMap();
|
||||||
assertNull(map.get("whatever"));
|
assertTrue(map.get("whatever").isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMultipleValues() {
|
public void testMultipleValues() {
|
||||||
|
@ -114,6 +212,69 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
||||||
assertTrue(map.get("three").contains("trois"));
|
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() {
|
public void testContainsValue() {
|
||||||
final MultiValuedMap<K, V> map = makeFullMap();
|
final MultiValuedMap<K, V> map = makeFullMap();
|
||||||
assertTrue(map.containsValue("uno"));
|
assertTrue(map.containsValue("uno"));
|
||||||
|
@ -158,7 +319,7 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
||||||
// assertEquals(expected, actual);
|
// assertEquals(expected, actual);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public void testRemoveAllViaIterator() {
|
public void testRemoveAllViaValuesIterator() {
|
||||||
if (!isRemoveSupported()) {
|
if (!isRemoveSupported()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -167,10 +328,34 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
||||||
i.next();
|
i.next();
|
||||||
i.remove();
|
i.remove();
|
||||||
}
|
}
|
||||||
assertNull(map.get("one"));
|
assertTrue(map.get("one").isEmpty());
|
||||||
assertTrue(map.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() {
|
// public void testRemoveAllViaKeyedIterator() {
|
||||||
// if (!isRemoveSupported()) {
|
// if (!isRemoveSupported()) {
|
||||||
// return;
|
// return;
|
||||||
|
@ -210,7 +395,7 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
||||||
i.next();
|
i.next();
|
||||||
i.remove();
|
i.remove();
|
||||||
}
|
}
|
||||||
assertNull(map.get("one"));
|
assertTrue(map.get("one").isEmpty());
|
||||||
assertEquals(0, map.size());
|
assertEquals(0, map.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,11 +644,93 @@ public abstract class AbstractMultiValuedMapTest<K, V> extends AbstractObjectTes
|
||||||
assertTrue(keyBag.containsAll(col));
|
assertTrue(keyBag.containsAll(col));
|
||||||
}
|
}
|
||||||
|
|
||||||
// public void testMapEqulas() {
|
public void testAsMapGet() {
|
||||||
// MultiValuedMap<K, V> map1 = makeFullMap();
|
resetEmpty();
|
||||||
// MultiValuedMap<K, V> map2 = makeFullMap();
|
Map<K, Collection<V>> mapCol = getMap().asMap();
|
||||||
// assertEquals(true, map1.equals(map2));
|
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
|
// 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 {
|
public void testEmptyMapCompatibility() throws Exception {
|
||||||
final MultiValuedMap<?, ?> map = makeObject();
|
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());
|
assertEquals("Map is empty", 0, map2.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFullMapCompatibility() throws Exception {
|
public void testFullMapCompatibility() throws Exception {
|
||||||
final MultiValuedMap<?, ?> map = (MultiValuedMap<?, ?>) makeFullMap();
|
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());
|
assertEquals("Map is the right size", map.size(), map2.size());
|
||||||
for (final Object key : map.keySet()) {
|
for (final Object key : map.keySet()) {
|
||||||
assertEquals("Map had inequal elements", map.get(key), map2.get(key));
|
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;
|
package org.apache.commons.collections4.multimap;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.BulkTest;
|
||||||
import org.apache.commons.collections4.MultiValuedMap;
|
import org.apache.commons.collections4.MultiValuedMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,13 +36,17 @@ public class MultiValuedHashMapTest<K, V> extends AbstractMultiValuedMapTest<K,
|
||||||
super(testName);
|
super(testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Test suite() {
|
||||||
|
return BulkTest.makeSuite(MultiValuedHashMapTest.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MultiValuedMap<K, V> makeObject() {
|
public MultiValuedMap<K, V> makeObject() {
|
||||||
final MultiValuedMap<K, V> m = new MultiValuedHashMap<K, V>();
|
final MultiValuedMap<K, V> m = new MultiValuedHashMap<K, V>();
|
||||||
return m;
|
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 =
|
final MultiValuedHashMap<K, V> map =
|
||||||
(MultiValuedHashMap<K, V>) MultiValuedHashMap.<K, V, C> multiValuedMap(collectionClass);
|
(MultiValuedHashMap<K, V>) MultiValuedHashMap.<K, V, C> multiValuedMap(collectionClass);
|
||||||
addSampleMappings(map);
|
addSampleMappings(map);
|
||||||
|
@ -52,26 +57,28 @@ public class MultiValuedHashMapTest<K, V> extends AbstractMultiValuedMapTest<K,
|
||||||
public void testValueCollectionType() {
|
public void testValueCollectionType() {
|
||||||
final MultiValuedHashMap<K, V> map = createTestMap(LinkedList.class);
|
final MultiValuedHashMap<K, V> map = createTestMap(LinkedList.class);
|
||||||
assertTrue(map.get("one") instanceof LinkedList);
|
assertTrue(map.get("one") instanceof LinkedList);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void testPutWithList() {
|
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("a", test.put((K) "A", (V) "a"));
|
||||||
assertEquals("b", test.put((K) "A", (V) "b"));
|
assertEquals("b", test.put((K) "A", (V) "b"));
|
||||||
assertEquals(1, test.keySet().size());
|
assertEquals(1, test.keySet().size());
|
||||||
assertEquals(2, test.size("A"));
|
assertEquals(2, test.get("A").size());
|
||||||
assertEquals(2, test.size());
|
assertEquals(2, test.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void testPutWithSet() {
|
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("a", test.put((K) "A", (V) "a"));
|
||||||
assertEquals("b", test.put((K) "A", (V) "b"));
|
assertEquals("b", test.put((K) "A", (V) "b"));
|
||||||
assertEquals(null, test.put((K) "A", (V) "a"));
|
assertEquals(null, test.put((K) "A", (V) "a"));
|
||||||
assertEquals(1, test.keySet().size());
|
assertEquals(1, test.keySet().size());
|
||||||
assertEquals(2, test.size("A"));
|
assertEquals(2, test.get("A").size());
|
||||||
assertEquals(2, test.size());
|
assertEquals(2, test.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.commons.collections4.multimap;
|
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.MultiValuedMap;
|
||||||
import org.apache.commons.collections4.Transformer;
|
import org.apache.commons.collections4.Transformer;
|
||||||
import org.apache.commons.collections4.TransformerUtils;
|
import org.apache.commons.collections4.TransformerUtils;
|
||||||
|
@ -34,6 +37,10 @@ public class TransformedMultiValuedMapTest<K, V> extends AbstractMultiValuedMapT
|
||||||
super(testName);
|
super(testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Test suite() {
|
||||||
|
return BulkTest.makeSuite(TransformedMultiValuedMapTest.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MultiValuedMap<K, V> makeObject() {
|
public MultiValuedMap<K, V> makeObject() {
|
||||||
return TransformedMultiValuedMap.transformingMap(new MultiValuedHashMap<K, V>(),
|
return TransformedMultiValuedMap.transformingMap(new MultiValuedHashMap<K, V>(),
|
||||||
|
|
|
@ -16,6 +16,18 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.commons.collections4.multimap;
|
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.MultiValuedMap;
|
||||||
import org.apache.commons.collections4.Unmodifiable;
|
import org.apache.commons.collections4.Unmodifiable;
|
||||||
|
|
||||||
|
@ -31,6 +43,10 @@ public class UnmodifiableMultiValuedMapTest<K, V> extends AbstractMultiValuedMap
|
||||||
super(testName);
|
super(testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Test suite() {
|
||||||
|
return BulkTest.makeSuite(UnmodifiableMultiValuedMapTest.class);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isAddSupported() {
|
public boolean isAddSupported() {
|
||||||
return false;
|
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 {
|
// public void testCreate() throws Exception {
|
||||||
// writeExternalFormToDisk((java.io.Serializable) makeObject(),
|
// writeExternalFormToDisk((java.io.Serializable) makeObject(),
|
||||||
// "src/test/resources/data/test/UnmodifiableMultiValuedMap.emptyCollection.version4.1.obj");
|
// "src/test/resources/data/test/UnmodifiableMultiValuedMap.emptyCollection.version4.1.obj");
|
||||||
|
|
Loading…
Reference in New Issue