[COLLECTIONS-424] CompositeSet: remove inheritance from CompositeCollection, update mutator class and unit tests.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@1457410 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
fb7bae91d7
commit
0f0b8710e2
|
@ -73,7 +73,8 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
* @param compositeCollection1 the Collection to be appended to the composite
|
* @param compositeCollection1 the Collection to be appended to the composite
|
||||||
* @param compositeCollection2 the Collection to be appended to the composite
|
* @param compositeCollection2 the Collection to be appended to the composite
|
||||||
*/
|
*/
|
||||||
public CompositeCollection(final Collection<E> compositeCollection1, final Collection<E> compositeCollection2) {
|
public CompositeCollection(final Collection<E> compositeCollection1,
|
||||||
|
final Collection<E> compositeCollection2) {
|
||||||
super();
|
super();
|
||||||
addComposited(compositeCollection1, compositeCollection2);
|
addComposited(compositeCollection1, compositeCollection2);
|
||||||
}
|
}
|
||||||
|
@ -88,16 +89,6 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
addComposited(compositeCollections);
|
addComposited(compositeCollections);
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Create a Composite Collection extracting the collections from an iterable.
|
|
||||||
// *
|
|
||||||
// * @param compositeCollections the collections to composite
|
|
||||||
// */
|
|
||||||
// public CompositeCollection(Iterable<Collection<E>> compositeCollections) {
|
|
||||||
// super();
|
|
||||||
// addComposited(compositeCollections);
|
|
||||||
// }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* Gets the size of this composite collection.
|
* Gets the size of this composite collection.
|
||||||
|
@ -122,7 +113,7 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
* @return true if all of the contained collections are empty
|
* @return true if all of the contained collections are empty
|
||||||
*/
|
*/
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
for (final Collection<? extends E> item : all) {
|
for (final Collection<E> item : all) {
|
||||||
if (item.isEmpty() == false) {
|
if (item.isEmpty() == false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +130,7 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
* @return true if obj is contained in any of the contained collections
|
* @return true if obj is contained in any of the contained collections
|
||||||
*/
|
*/
|
||||||
public boolean contains(final Object obj) {
|
public boolean contains(final Object obj) {
|
||||||
for (final Collection<? extends E> item : all) {
|
for (final Collection<E> item : all) {
|
||||||
if (item.contains(obj)) {
|
if (item.contains(obj)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +153,7 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
return EmptyIterator.<E>emptyIterator();
|
return EmptyIterator.<E>emptyIterator();
|
||||||
}
|
}
|
||||||
final IteratorChain<E> chain = new IteratorChain<E>();
|
final IteratorChain<E> chain = new IteratorChain<E>();
|
||||||
for (final Collection<? extends E> item : all) {
|
for (final Collection<E> item : all) {
|
||||||
chain.addIterator(item.iterator());
|
chain.addIterator(item.iterator());
|
||||||
}
|
}
|
||||||
return chain;
|
return chain;
|
||||||
|
@ -201,7 +192,7 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (final Collection<? extends E> item : all) {
|
for (final Collection<E> item : all) {
|
||||||
for (final E e : item) {
|
for (final E e : item) {
|
||||||
result[offset++] = e;
|
result[offset++] = e;
|
||||||
}
|
}
|
||||||
|
@ -303,7 +294,7 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
for (final Collection<? extends E> item : all) {
|
for (final Collection<E> item : all) {
|
||||||
changed |= item.removeAll(coll);
|
changed |= item.removeAll(coll);
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
|
@ -321,7 +312,7 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
*/
|
*/
|
||||||
public boolean retainAll(final Collection<?> coll) {
|
public boolean retainAll(final Collection<?> coll) {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
for (final Collection<? extends E> item : all) {
|
for (final Collection<E> item : all) {
|
||||||
changed |= item.retainAll(coll);
|
changed |= item.retainAll(coll);
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
|
@ -335,7 +326,7 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
* @throws UnsupportedOperationException if clear is unsupported
|
* @throws UnsupportedOperationException if clear is unsupported
|
||||||
*/
|
*/
|
||||||
public void clear() {
|
public void clear() {
|
||||||
for (final Collection<? extends E> coll : all) {
|
for (final Collection<E> coll : all) {
|
||||||
coll.clear();
|
coll.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,7 +356,8 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
* @param compositeCollection1 the Collection to be appended to the composite
|
* @param compositeCollection1 the Collection to be appended to the composite
|
||||||
* @param compositeCollection2 the Collection to be appended to the composite
|
* @param compositeCollection2 the Collection to be appended to the composite
|
||||||
*/
|
*/
|
||||||
public void addComposited(final Collection<E> compositeCollection1, final Collection<E> compositeCollection2) {
|
public void addComposited(final Collection<E> compositeCollection1,
|
||||||
|
final Collection<E> compositeCollection2) {
|
||||||
all.add(compositeCollection1);
|
all.add(compositeCollection1);
|
||||||
all.add(compositeCollection2);
|
all.add(compositeCollection2);
|
||||||
}
|
}
|
||||||
|
@ -379,17 +371,6 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
all.addAll(Arrays.asList(compositeCollections));
|
all.addAll(Arrays.asList(compositeCollections));
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Add these Collections to the list of collections in this composite
|
|
||||||
// *
|
|
||||||
// * @param compositeCollections the Collections to be appended to the composite
|
|
||||||
// */
|
|
||||||
// public void addComposited(Iterable<Collection<E>> compositeCollections) {
|
|
||||||
// for (Collection<E> item : compositeCollections) {
|
|
||||||
// all.add(item);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a collection from the those being decorated in this composite.
|
* Removes a collection from the those being decorated in this composite.
|
||||||
*
|
*
|
||||||
|
@ -415,7 +396,7 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
*
|
*
|
||||||
* @return Unmodifiable list of all collections in this composite.
|
* @return Unmodifiable list of all collections in this composite.
|
||||||
*/
|
*/
|
||||||
public List<? extends Collection<E>> getCollections() {
|
public List<Collection<E>> getCollections() {
|
||||||
return UnmodifiableList.unmodifiableList(all);
|
return UnmodifiableList.unmodifiableList(all);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,7 +458,9 @@ public class CompositeCollection<E> implements Collection<E>, Serializable {
|
||||||
* @throws NullPointerException if the object cannot be removed because its null
|
* @throws NullPointerException if the object cannot be removed because its null
|
||||||
* @throws IllegalArgumentException if the object cannot be removed
|
* @throws IllegalArgumentException if the object cannot be removed
|
||||||
*/
|
*/
|
||||||
public boolean remove(CompositeCollection<E> composite, List<Collection<E>> collections, Object obj);
|
public boolean remove(CompositeCollection<E> composite,
|
||||||
|
List<Collection<E>> collections,
|
||||||
|
Object obj);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,20 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.commons.collections.set;
|
package org.apache.commons.collections.set;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.collections.collection.CompositeCollection;
|
import org.apache.commons.collections.iterators.EmptyIterator;
|
||||||
|
import org.apache.commons.collections.iterators.IteratorChain;
|
||||||
|
import org.apache.commons.collections.list.UnmodifiableList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decorates a set of other sets to provide a single unified view.
|
* Decorates a set of other sets to provide a single unified view.
|
||||||
|
@ -29,17 +37,28 @@ import org.apache.commons.collections.collection.CompositeCollection;
|
||||||
* Changes made to this set will actually be made on the decorated set.
|
* Changes made to this set will actually be made on the decorated set.
|
||||||
* Add operations require the use of a pluggable strategy.
|
* Add operations require the use of a pluggable strategy.
|
||||||
* If no strategy is provided then add is unsupported.
|
* If no strategy is provided then add is unsupported.
|
||||||
*
|
* <p>
|
||||||
|
* From version 4.0, this class does not extend {@link CompositeCollection}
|
||||||
|
* anymore due to its input restrictions (only accepts Sets).
|
||||||
|
* See <a href="https://issues.apache.org/jira/browse/COLLECTIONS-424">COLLECTIONS-424</a>
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class CompositeSet<E> extends CompositeCollection<E> implements Set<E> {
|
public class CompositeSet<E> implements Set<E>, Serializable {
|
||||||
|
|
||||||
/** Serialization version */
|
/** Serialization version */
|
||||||
private static final long serialVersionUID = 5185069727540378940L;
|
private static final long serialVersionUID = 5185069727540378940L;
|
||||||
|
|
||||||
|
/** SetMutator to handle changes to the collection */
|
||||||
|
protected SetMutator<E> mutator;
|
||||||
|
|
||||||
|
/** Sets in the composite */
|
||||||
|
protected List<Set<E>> all = new ArrayList<Set<E>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an empty CompositeSet
|
* Create an empty CompositeSet.
|
||||||
*/
|
*/
|
||||||
public CompositeSet() {
|
public CompositeSet() {
|
||||||
super();
|
super();
|
||||||
|
@ -51,7 +70,8 @@ public class CompositeSet<E> extends CompositeCollection<E> implements Set<E> {
|
||||||
* @param set the initial set in the composite
|
* @param set the initial set in the composite
|
||||||
*/
|
*/
|
||||||
public CompositeSet(final Set<E> set) {
|
public CompositeSet(final Set<E> set) {
|
||||||
super(set);
|
super();
|
||||||
|
addComposited(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,103 +80,143 @@ public class CompositeSet<E> extends CompositeCollection<E> implements Set<E> {
|
||||||
* @param sets the initial sets in the composite
|
* @param sets the initial sets in the composite
|
||||||
*/
|
*/
|
||||||
public CompositeSet(final Set<E>... sets) {
|
public CompositeSet(final Set<E>... sets) {
|
||||||
super(sets);
|
super();
|
||||||
|
addComposited(sets);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* Gets the size of this composite set.
|
||||||
|
* <p>
|
||||||
|
* This implementation calls <code>size()</code> on each set.
|
||||||
|
*
|
||||||
|
* @return total number of elements in all contained containers
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
int size = 0;
|
||||||
|
for (final Set<E> item : all) {
|
||||||
|
size += item.size();
|
||||||
|
}
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a Set to this composite
|
* Checks whether this composite set is empty.
|
||||||
|
* <p>
|
||||||
|
* This implementation calls <code>isEmpty()</code> on each set.
|
||||||
*
|
*
|
||||||
* @param c Must implement Set
|
* @return true if all of the contained sets are empty
|
||||||
* @throws IllegalArgumentException if c does not implement java.util.Set
|
|
||||||
* or if a SetMutator is set, but fails to resolve a collision
|
|
||||||
* @throws UnsupportedOperationException if there is no SetMutator set, or
|
|
||||||
* a CollectionMutator is set instead of a SetMutator
|
|
||||||
* @see org.apache.commons.collections.collection.CompositeCollection.CollectionMutator
|
|
||||||
* @see SetMutator
|
|
||||||
*/
|
*/
|
||||||
@Override
|
public boolean isEmpty() {
|
||||||
public synchronized void addComposited(final Collection<E> c) {
|
for (final Set<E> item : all) {
|
||||||
if (!(c instanceof Set)) {
|
if (item.isEmpty() == false) {
|
||||||
throw new IllegalArgumentException("Collections added must implement java.util.Set");
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
for (final Set<E> set : getCollections()) {
|
|
||||||
final Collection<E> intersects = CollectionUtils.intersection(set, c);
|
|
||||||
if (intersects.size() > 0) {
|
|
||||||
if (this.mutator == null) {
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Collision adding composited collection with no SetMutator set");
|
|
||||||
}
|
|
||||||
else if (!(this.mutator instanceof SetMutator)) {
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Collision adding composited collection to a CompositeSet with a CollectionMutator " +
|
|
||||||
"instead of a SetMutator");
|
|
||||||
}
|
|
||||||
getMutator().resolveCollision(this, set, (Set<E>) c, intersects);
|
|
||||||
if (CollectionUtils.intersection(set, c).size() > 0) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Attempt to add illegal entry unresolved by SetMutator.resolveCollision()");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.addComposited(c);
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public List<? extends Set<E>> getCollections() {
|
|
||||||
return (List<Set<E>>) super.getCollections();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add two sets to this composite.
|
* Checks whether this composite set contains the object.
|
||||||
|
* <p>
|
||||||
|
* This implementation calls <code>contains()</code> on each set.
|
||||||
*
|
*
|
||||||
* @param c the first {@link java.util.Set} to add to this composite
|
* @param obj the object to search for
|
||||||
* @param d the second {@link java.util.Set} to add to this composite
|
* @return true if obj is contained in any of the contained sets
|
||||||
* @throws IllegalArgumentException if c or d does not implement {@link java.util.Set}
|
*/
|
||||||
|
public boolean contains(final Object obj) {
|
||||||
|
for (final Set<E> item : all) {
|
||||||
|
if (item.contains(obj)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an iterator over all the sets in this composite.
|
||||||
|
* <p>
|
||||||
|
* This implementation uses an <code>IteratorChain</code>.
|
||||||
|
*
|
||||||
|
* @return an <code>IteratorChain</code> instance which supports
|
||||||
|
* <code>remove()</code>. Iteration occurs over contained collections in
|
||||||
|
* the order they were added, but this behavior should not be relied upon.
|
||||||
|
* @see IteratorChain
|
||||||
|
*/
|
||||||
|
public Iterator<E> iterator() {
|
||||||
|
if (all.isEmpty()) {
|
||||||
|
return EmptyIterator.<E>emptyIterator();
|
||||||
|
}
|
||||||
|
final IteratorChain<E> chain = new IteratorChain<E>();
|
||||||
|
for (final Set<E> item : all) {
|
||||||
|
chain.addIterator(item.iterator());
|
||||||
|
}
|
||||||
|
return chain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array containing all of the elements in this composite.
|
||||||
|
*
|
||||||
|
* @return an object array of all the elements in the collection
|
||||||
|
*/
|
||||||
|
public Object[] toArray() {
|
||||||
|
final Object[] result = new Object[size()];
|
||||||
|
int i = 0;
|
||||||
|
for (final Iterator<E> it = iterator(); it.hasNext(); i++) {
|
||||||
|
result[i] = it.next();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an object array, populating the supplied array if possible.
|
||||||
|
* See <code>Collection</code> interface for full details.
|
||||||
|
*
|
||||||
|
* @param <T> the type of the elements in the collection
|
||||||
|
* @param array the array to use, populating if possible
|
||||||
|
* @return an array of all the elements in the collection
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public synchronized void addComposited(final Collection<E> c, final Collection<E> d) {
|
public <T> T[] toArray(final T[] array) {
|
||||||
if (!(c instanceof Set)) {
|
final int size = size();
|
||||||
throw new IllegalArgumentException("Argument must implement java.util.Set");
|
Object[] result = null;
|
||||||
|
if (array.length >= size) {
|
||||||
|
result = array;
|
||||||
|
} else {
|
||||||
|
result = (Object[]) Array.newInstance(array.getClass().getComponentType(), size);
|
||||||
}
|
}
|
||||||
if (!(d instanceof Set)) {
|
|
||||||
throw new IllegalArgumentException("Argument must implement java.util.Set");
|
int offset = 0;
|
||||||
|
for (final Collection<E> item : all) {
|
||||||
|
for (final E e : item) {
|
||||||
|
result[offset++] = e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.addComposited(new Set[] { (Set<? extends E>) c, (Set<? extends E>) d });
|
if (result.length > size) {
|
||||||
|
result[size] = null;
|
||||||
|
}
|
||||||
|
return (T[]) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an array of sets to this composite
|
* Adds an object to the collection, throwing UnsupportedOperationException
|
||||||
* @param comps the {@link Collection} of {@link java.util.Set}s to add to this composite
|
* unless a SetMutator strategy is specified.
|
||||||
* @throws IllegalArgumentException if any of the collections in comps does not implement {@link java.util.Set}
|
*
|
||||||
|
* @param obj the object to add
|
||||||
|
* @return {@code true} if the collection was modified
|
||||||
|
* @throws UnsupportedOperationException if SetMutator hasn't been set or add is unsupported
|
||||||
|
* @throws ClassCastException if the object cannot be added due to its type
|
||||||
|
* @throws NullPointerException if the object cannot be added because its null
|
||||||
|
* @throws IllegalArgumentException if the object cannot be added
|
||||||
*/
|
*/
|
||||||
@Override
|
public boolean add(final E obj) {
|
||||||
public synchronized void addComposited(final Collection<E>[] comps) {
|
if (mutator == null) {
|
||||||
for (int i = comps.length - 1; i >= 0; --i) {
|
throw new UnsupportedOperationException(
|
||||||
this.addComposited(comps[i]);
|
"add() is not supported on CompositeSet without a SetMutator strategy");
|
||||||
}
|
}
|
||||||
|
return mutator.add(this, all, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This can receive either a
|
|
||||||
* {@link org.apache.commons.collections.collection.CompositeCollection.CollectionMutator CollectionMutator}
|
|
||||||
* or a {@link CompositeSet.SetMutator}.
|
|
||||||
* If a {@link org.apache.commons.collections.collection.CompositeCollection.CollectionMutator CollectionMutator}
|
|
||||||
* is used than conflicts when adding composited sets will throw IllegalArgumentException.
|
|
||||||
*
|
|
||||||
* @param mutator
|
|
||||||
* the {@link org.apache.commons.collections.collection.CompositeCollection.CollectionMutator CollectionMutator}
|
|
||||||
* to use for this composite
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setMutator(final CollectionMutator<E> mutator) {
|
|
||||||
super.setMutator(mutator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set operations */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If a <code>CollectionMutator</code> is defined for this CompositeSet then this
|
* If a <code>CollectionMutator</code> is defined for this CompositeSet then this
|
||||||
* method will be called anyway.
|
* method will be called anyway.
|
||||||
|
@ -164,9 +224,8 @@ public class CompositeSet<E> extends CompositeCollection<E> implements Set<E> {
|
||||||
* @param obj object to be removed
|
* @param obj object to be removed
|
||||||
* @return true if the object is removed, false otherwise
|
* @return true if the object is removed, false otherwise
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public boolean remove(final Object obj) {
|
public boolean remove(final Object obj) {
|
||||||
for (final Set<? extends E> set : getCollections()) {
|
for (final Set<E> set : getSets()) {
|
||||||
if (set.contains(obj)) {
|
if (set.contains(obj)) {
|
||||||
return set.remove(obj);
|
return set.remove(obj);
|
||||||
}
|
}
|
||||||
|
@ -174,6 +233,187 @@ public class CompositeSet<E> extends CompositeCollection<E> implements Set<E> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this composite contains all the elements in the specified collection.
|
||||||
|
* <p>
|
||||||
|
* This implementation calls <code>contains()</code> for each element in the
|
||||||
|
* specified collection.
|
||||||
|
*
|
||||||
|
* @param coll the collection to check for
|
||||||
|
* @return true if all elements contained
|
||||||
|
*/
|
||||||
|
public boolean containsAll(final Collection<?> coll) {
|
||||||
|
for (final Object item : coll) {
|
||||||
|
if (contains(item) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a collection of elements to this composite, throwing
|
||||||
|
* UnsupportedOperationException unless a SetMutator strategy is specified.
|
||||||
|
*
|
||||||
|
* @param coll the collection to add
|
||||||
|
* @return true if the composite was modified
|
||||||
|
* @throws UnsupportedOperationException if SetMutator hasn't been set or add is unsupported
|
||||||
|
* @throws ClassCastException if the object cannot be added due to its type
|
||||||
|
* @throws NullPointerException if the object cannot be added because its null
|
||||||
|
* @throws IllegalArgumentException if the object cannot be added
|
||||||
|
*/
|
||||||
|
public boolean addAll(final Collection<? extends E> coll) {
|
||||||
|
if (mutator == null) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"addAll() is not supported on CompositeSet without a SetMutator strategy");
|
||||||
|
}
|
||||||
|
return mutator.addAll(this, all, coll);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the elements in the specified collection from this composite set.
|
||||||
|
* <p>
|
||||||
|
* This implementation calls <code>removeAll</code> on each collection.
|
||||||
|
*
|
||||||
|
* @param coll the collection to remove
|
||||||
|
* @return true if the composite was modified
|
||||||
|
* @throws UnsupportedOperationException if removeAll is unsupported
|
||||||
|
*/
|
||||||
|
public boolean removeAll(final Collection<?> coll) {
|
||||||
|
if (coll.size() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean changed = false;
|
||||||
|
for (final Collection<E> item : all) {
|
||||||
|
changed |= item.removeAll(coll);
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retains all the elements in the specified collection in this composite set,
|
||||||
|
* removing all others.
|
||||||
|
* <p>
|
||||||
|
* This implementation calls <code>retainAll()</code> on each collection.
|
||||||
|
*
|
||||||
|
* @param coll the collection to remove
|
||||||
|
* @return true if the composite was modified
|
||||||
|
* @throws UnsupportedOperationException if retainAll is unsupported
|
||||||
|
*/
|
||||||
|
public boolean retainAll(final Collection<?> coll) {
|
||||||
|
boolean changed = false;
|
||||||
|
for (final Collection<E> item : all) {
|
||||||
|
changed |= item.retainAll(coll);
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all of the elements from this composite set.
|
||||||
|
* <p>
|
||||||
|
* This implementation calls <code>clear()</code> on each set.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException if clear is unsupported
|
||||||
|
*/
|
||||||
|
public void clear() {
|
||||||
|
for (final Collection<E> coll : all) {
|
||||||
|
coll.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* Specify a SetMutator strategy instance to handle changes.
|
||||||
|
*
|
||||||
|
* @param mutator the mutator to use
|
||||||
|
*/
|
||||||
|
public void setMutator(final SetMutator<E> mutator) {
|
||||||
|
this.mutator = mutator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a Set to this composite.
|
||||||
|
*
|
||||||
|
* @param set the set to add
|
||||||
|
* @throws IllegalArgumentException if a SetMutator is set, but fails to resolve a collision
|
||||||
|
* @throws UnsupportedOperationException if there is no SetMutator set
|
||||||
|
* @see SetMutator
|
||||||
|
*/
|
||||||
|
public synchronized void addComposited(final Set<E> set) {
|
||||||
|
for (final Set<E> existingSet : getSets()) {
|
||||||
|
final Collection<E> intersects = CollectionUtils.intersection(existingSet, set);
|
||||||
|
if (intersects.size() > 0) {
|
||||||
|
if (this.mutator == null) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Collision adding composited set with no SetMutator set");
|
||||||
|
}
|
||||||
|
getMutator().resolveCollision(this, existingSet, set, intersects);
|
||||||
|
if (CollectionUtils.intersection(existingSet, set).size() > 0) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Attempt to add illegal entry unresolved by SetMutator.resolveCollision()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
all.add(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add these Sets to the list of sets in this composite.
|
||||||
|
*
|
||||||
|
* @param set1 the first Set to be appended to the composite
|
||||||
|
* @param set2 the second Set to be appended to the composite
|
||||||
|
*/
|
||||||
|
public void addComposited(final Set<E> set1, final Set<E> set2) {
|
||||||
|
all.add(set1);
|
||||||
|
all.add(set2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add these Sets to the list of sets in this composite
|
||||||
|
*
|
||||||
|
* @param sets the Sets to be appended to the composite
|
||||||
|
*/
|
||||||
|
public void addComposited(final Set<E>[] sets) {
|
||||||
|
all.addAll(Arrays.asList(sets));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a set from those being decorated in this composite.
|
||||||
|
*
|
||||||
|
* @param set set to be removed
|
||||||
|
*/
|
||||||
|
public void removeComposited(final Set<E> set) {
|
||||||
|
all.remove(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* Returns a new Set containing all of the elements.
|
||||||
|
*
|
||||||
|
* @return A new HashSet containing all of the elements in this composite.
|
||||||
|
* The new collection is <i>not</i> backed by this composite.
|
||||||
|
*/
|
||||||
|
public Set<E> toSet() {
|
||||||
|
return new HashSet<E>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the sets being decorated.
|
||||||
|
*
|
||||||
|
* @return Unmodifiable list of all sets in this composite.
|
||||||
|
*/
|
||||||
|
public List<Set<E>> getSets() {
|
||||||
|
return UnmodifiableList.unmodifiableList(all);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the set mutator to be used for this CompositeSet.
|
||||||
|
* @return the set mutator
|
||||||
|
*/
|
||||||
|
protected SetMutator<E> getMutator() {
|
||||||
|
return mutator;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @see java.util.Set#equals
|
* @see java.util.Set#equals
|
||||||
|
@ -182,7 +422,7 @@ public class CompositeSet<E> extends CompositeCollection<E> implements Set<E> {
|
||||||
public boolean equals(final Object obj) {
|
public boolean equals(final Object obj) {
|
||||||
if (obj instanceof Set) {
|
if (obj instanceof Set) {
|
||||||
final Set<?> set = (Set<?>) obj;
|
final Set<?> set = (Set<?>) obj;
|
||||||
return set.containsAll(this) && set.size() == this.size();
|
return set.size() == this.size() && set.containsAll(this);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -200,18 +440,40 @@ public class CompositeSet<E> extends CompositeCollection<E> implements Set<E> {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected SetMutator<E> getMutator() {
|
|
||||||
return (SetMutator<E>) super.getMutator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define callbacks for mutation operations.
|
* Define callbacks for mutation operations.
|
||||||
* <p>
|
|
||||||
* Defining remove() on implementations of SetMutator is pointless
|
|
||||||
* as they are never called by CompositeSet.
|
|
||||||
*/
|
*/
|
||||||
public static interface SetMutator<E> extends CompositeCollection.CollectionMutator<E> {
|
public static interface SetMutator<E> extends Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an object is to be added to the composite.
|
||||||
|
*
|
||||||
|
* @param composite the CompositeSet being changed
|
||||||
|
* @param sets all of the Set instances in this CompositeSet
|
||||||
|
* @param obj the object being added
|
||||||
|
* @return true if the collection is changed
|
||||||
|
* @throws UnsupportedOperationException if add is unsupported
|
||||||
|
* @throws ClassCastException if the object cannot be added due to its type
|
||||||
|
* @throws NullPointerException if the object cannot be added because its null
|
||||||
|
* @throws IllegalArgumentException if the object cannot be added
|
||||||
|
*/
|
||||||
|
public boolean add(CompositeSet<E> composite, List<Set<E>> sets, E obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a collection is to be added to the composite.
|
||||||
|
*
|
||||||
|
* @param composite the CompositeSet being changed
|
||||||
|
* @param sets all of the Set instances in this CompositeSet
|
||||||
|
* @param coll the collection being added
|
||||||
|
* @return true if the collection is changed
|
||||||
|
* @throws UnsupportedOperationException if add is unsupported
|
||||||
|
* @throws ClassCastException if the object cannot be added due to its type
|
||||||
|
* @throws NullPointerException if the object cannot be added because its null
|
||||||
|
* @throws IllegalArgumentException if the object cannot be added
|
||||||
|
*/
|
||||||
|
public boolean addAll(CompositeSet<E> composite,
|
||||||
|
List<Set<E>> sets,
|
||||||
|
Collection<? extends E> coll);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a Set is added to the CompositeSet and there is a
|
* Called when a Set is added to the CompositeSet and there is a
|
||||||
|
@ -225,6 +487,9 @@ public class CompositeSet<E> extends CompositeCollection<E> implements Set<E> {
|
||||||
* @param added the Set being added to the composite
|
* @param added the Set being added to the composite
|
||||||
* @param intersects the intersection of the existing and added sets
|
* @param intersects the intersection of the existing and added sets
|
||||||
*/
|
*/
|
||||||
public void resolveCollision(CompositeSet<E> comp, Set<E> existing, Set<E> added, Collection<E> intersects);
|
public void resolveCollision(CompositeSet<E> comp,
|
||||||
|
Set<E> existing,
|
||||||
|
Set<E> added,
|
||||||
|
Collection<E> intersects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,10 +126,10 @@ public class CompositeCollectionTest<E> extends AbstractCollectionTest<E> {
|
||||||
protected void setUpMutatorTest() {
|
protected void setUpMutatorTest() {
|
||||||
setUpTest();
|
setUpTest();
|
||||||
c.setMutator(new CompositeCollection.CollectionMutator<E>() {
|
c.setMutator(new CompositeCollection.CollectionMutator<E>() {
|
||||||
public boolean add(final CompositeCollection<E> composite,
|
|
||||||
final List<Collection<E>> collections, final E obj) {
|
public boolean add(CompositeCollection<E> composite, List<Collection<E>> collections, E obj) {
|
||||||
for (final Collection<E> collection : collections) {
|
for (final Collection<E> coll : collections) {
|
||||||
collection.add(obj);
|
coll.add(obj);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.collections.collection.CompositeCollection;
|
import org.apache.commons.collections.set.CompositeSet.SetMutator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension of {@link AbstractSetTest} for exercising the
|
* Extension of {@link AbstractSetTest} for exercising the
|
||||||
|
@ -94,7 +94,7 @@ public class CompositeSetTest<E> extends AbstractSetTest<E> {
|
||||||
final Set<E> one = buildOne();
|
final Set<E> one = buildOne();
|
||||||
final Set<E> two = buildTwo();
|
final Set<E> two = buildTwo();
|
||||||
final CompositeSet<E> set = new CompositeSet<E>(new Set[] { one, two });
|
final CompositeSet<E> set = new CompositeSet<E>(new Set[] { one, two });
|
||||||
set.setMutator(new CompositeSet.SetMutator<E>() {
|
set.setMutator(new SetMutator<E>() {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public void resolveCollision(final CompositeSet<E> comp, final Set<E> existing,
|
public void resolveCollision(final CompositeSet<E> comp, final Set<E> existing,
|
||||||
|
@ -102,18 +102,13 @@ public class CompositeSetTest<E> extends AbstractSetTest<E> {
|
||||||
//noop
|
//noop
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean add(final CompositeCollection<E> composite,
|
public boolean add(final CompositeSet<E> composite,
|
||||||
final List<Collection<E>> collections, final E obj) {
|
final List<Set<E>> collections, final E obj) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addAll(final CompositeCollection<E> composite,
|
public boolean addAll(final CompositeSet<E> composite,
|
||||||
final List<Collection<E>> collections, final Collection<? extends E> coll) {
|
final List<Set<E>> collections, final Collection<? extends E> coll) {
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean remove(final CompositeCollection<E> composite,
|
|
||||||
final List<Collection<E>> collections, final Object obj) {
|
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,8 +20,6 @@ import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.collections.collection.CompositeCollection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is used in CompositeSetTest. When testing serialization,
|
* This class is used in CompositeSetTest. When testing serialization,
|
||||||
* the class has to be separate of CompositeSetTest, else the test
|
* the class has to be separate of CompositeSetTest, else the test
|
||||||
|
@ -42,15 +40,11 @@ class EmptySetMutator<E> implements CompositeSet.SetMutator<E> {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean add(final CompositeCollection<E> composite, final List<Collection<E>> collections, final E obj) {
|
public boolean add(final CompositeSet<E> composite, final List<Set<E>> collections, final E obj) {
|
||||||
return contained.add(obj);
|
return contained.add(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addAll(final CompositeCollection<E> composite, final List<Collection<E>> collections, final Collection<? extends E> coll) {
|
public boolean addAll(final CompositeSet<E> composite, final List<Set<E>> collections, final Collection<? extends E> coll) {
|
||||||
return contained.addAll(coll);
|
return contained.addAll(coll);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(final CompositeCollection<E> composite, final List<Collection<E>> collections, final Object obj) {
|
|
||||||
return contained.remove(obj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue