diff --git a/src/java/org/apache/commons/collections/AbstractBag.java b/src/java/org/apache/commons/collections/AbstractBag.java
new file mode 100644
index 000000000..86e798979
--- /dev/null
+++ b/src/java/org/apache/commons/collections/AbstractBag.java
@@ -0,0 +1,335 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Attic/AbstractBag.java,v 1.1 2001/08/29 15:28:07 jstrachan Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/08/29 15:28:07 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * true
if the bag contains all elements in
+ * the given collection, respecting cardinality.
+ * @see #containsAll(Collection)
+ **/
+ public boolean containsAll(Bag other) {
+ boolean result = true;
+ Iterator i = other.uniqueSet().iterator();
+ while (i.hasNext()) {
+ Object current = i.next();
+ boolean contains =
+ getCount(current) >= ((Bag)other).getCount(current);
+ result = result && contains;
+ }
+ return result;
+ }
+
+ public boolean equals(Object o) {
+ boolean result = false;
+ if (o instanceof AbstractBag) {
+ result = _map.equals(((AbstractBag)o).getMap());
+ } else if (o instanceof Map) {
+ result = _map.equals((Map)o);
+ }
+ return result;
+ }
+
+ public int hashCode() {
+ return _map.hashCode();
+ }
+
+ public boolean isEmpty() {
+ return _map.isEmpty();
+ }
+
+ public Iterator iterator() {
+ return new BagIterator(this, extractList().iterator());
+ }
+
+ private class BagIterator implements Iterator {
+ private AbstractBag _parent = null;
+ private Iterator _support = null;
+ private Object _current = null;
+ private int _mods = 0;
+
+ public BagIterator(AbstractBag parent, Iterator support) {
+ _parent = parent;
+ _support = support;
+ _current = null;
+ _mods = parent.modCount();
+ }
+
+ public boolean hasNext() {
+ return _support.hasNext();
+ }
+
+ public Object next() {
+ if (_parent.modCount() != _mods) {
+ throw new ConcurrentModificationException();
+ }
+ _current = _support.next();
+ return _current;
+ }
+
+ public void remove() {
+ if (_parent.modCount() != _mods) {
+ throw new ConcurrentModificationException();
+ }
+ _support.remove();
+ _parent.remove(_current, 1);
+ _mods++;
+ }
+ }
+
+ public boolean remove (Object o) {
+ return remove(o, getCount(o));
+ }
+
+ public boolean remove (Object o, int i) {
+ _mods++;
+ boolean result = false;
+ int count = getCount(o);
+ if (count > i) {
+ _map.put(o, new Integer(count - i));
+ result = true;
+ _total -= i;
+ } else {
+ result = uniqueSet().remove(o);
+ _total -= count;
+ }
+ return result;
+ }
+
+ public boolean removeAll(Collection c) {
+ boolean result = false;
+ if (c != null) {
+ Iterator i = c.iterator();
+ while (i.hasNext()) {
+ boolean changed = remove(i.next(), 1);
+ result = result || changed;
+ }
+ }
+ return result;
+ }
+
+ public boolean retainAll(Collection c) {
+ return retainAll(new HashBag(c));
+ }
+
+ /**
+ * Remove any members of the bag that are not in the given
+ * bag, respecting cardinality.
+ * @see #retainAll(Collection)
+ * @return true
if this call changed the collection
+ **/
+ public boolean retainAll(Bag other) {
+ boolean result = false;
+ Bag excess = new HashBag();
+ Iterator i = uniqueSet().iterator();
+ while (i.hasNext()) {
+ Object current = i.next();
+ int myCount = getCount(current);
+ int otherCount = other.getCount(current);
+ if (1 <= otherCount && otherCount <= myCount) {
+ excess.add(current, myCount - otherCount);
+ } else {
+ excess.add(current, myCount);
+ }
+ }
+ if (!excess.isEmpty()) {
+ result = removeAll(excess);
+ }
+ return result;
+ }
+
+ public Object[] toArray() {
+ return extractList().toArray();
+ }
+
+ public Object[] toArray(Object[] a) {
+ return extractList().toArray(a);
+ }
+
+ public int getCount(Object o) {
+ int result = 0;
+ Integer count = MapUtils.getInteger(_map, o);
+ if (count != null) {
+ result = count.intValue();
+ }
+ return result;
+ }
+
+ public Set uniqueSet() {
+ return _map.keySet();
+ }
+
+ public int size() {
+ return _total;
+ }
+
+ /**
+ * Actually walks the bag to make sure the count is correct and
+ * resets the running total
+ **/
+ protected int calcTotalSize() {
+ _total = extractList().size();
+ return _total;
+ }
+
+ /**
+ * Utility method for implementations to set the map that backs
+ * this bag. Not intended for interactive use outside of
+ * subclasses.
+ **/
+ protected void setMap(Map m) {
+ _map = m;
+ }
+
+ /**
+ * Utility method for implementations to access the map that backs
+ * this bag. Not intended for interactive use outside of
+ * subclasses.
+ **/
+ protected Map getMap() {
+ return _map;
+ }
+
+ /**
+ * Create a list for use in iteration, etc.
+ **/
+ private List extractList() {
+ List result = new ArrayList();
+ Iterator i = uniqueSet().iterator();
+ while (i.hasNext()) {
+ Object current = i.next();
+ for (int index = 0; index < getCount(current); index++) {
+ result.add(current);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Return number of modifications for iterator
+ **/
+ private int modCount() {
+ return _mods;
+ }
+}
+
+
+
diff --git a/src/java/org/apache/commons/collections/Bag.java b/src/java/org/apache/commons/collections/Bag.java
new file mode 100644
index 000000000..e1a0bae5e
--- /dev/null
+++ b/src/java/org/apache/commons/collections/Bag.java
@@ -0,0 +1,181 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Bag.java,v 1.1 2001/08/29 15:28:07 jstrachan Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/08/29 15:28:07 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * hashCode
to check for equality. Suppose
+ * you have a Bag that contains {a, a, b, c}
. Calling
+ * {@link #getCount} on a
would return 2, while calling
+ * {@link #uniqueSet} would return {a, b, c}
.
+ *
+ * @author Chuck Burdick
+ **/
+public interface Bag extends Collection {
+ /**
+ * Return the number of occurrences (cardinality) of the given
+ * object currently in the bag. If the object does not exist in the
+ * bag, return 0.
+ **/
+ public int getCount(Object o);
+
+ /**
+ * Add the given object to the bag and keep a count. If the object
+ * is already in the {@link #uniqueSet} then increment its count as
+ * reported by {@link #getCount}. Otherwise add it to the {@link
+ * #uniqueSet} and report its count as 1.
+ * @return true
if the object was not already in the
+ * uniqueSet
+ * @see #getCount
+ **/
+ public boolean add(Object o);
+
+ /**
+ * Add i
copies of the given object to the bag and
+ * keep a count.
+ * @return true
if the object was not already in the
+ * uniqueSet
+ * @see #add(Object)
+ * @see #getCount
+ **/
+ public boolean add(Object o, int i);
+
+ /**
+ * Remove all occurrences of the given object from the bag, and do
+ * not represent the object in the {@link #uniqueSet}.
+ * @see #remove(Object, int)
+ * @return true
if this call changed the collection
+ **/
+ public boolean remove(Object o);
+
+ /**
+ * Remove the given number of occurrences from the bag. If the bag
+ * contains less than i
occurrences, the item will be
+ * removed from the {@link #uniqueSet}.
+ * @see #getCount
+ * @see #remove(Object)
+ * @return true
if this call changed the collection
+ **/
+ public boolean remove(Object o, int i);
+
+ /**
+ * The {@link Set} of unique members that represent all members in
+ * the bag. Uniqueness constraints are the same as those in {@link
+ * Set}.
+ **/
+ public Set uniqueSet();
+
+ /**
+ * Returns the total number of items in the bag across all types.
+ * @see #size
+ **/
+ public int size();
+
+ /**
+ * Returns true
if the bag contains all elements in
+ * the given collection, respecting cardinality. That is, if the
+ * given collection C
contains n
copies
+ * of a given object, calling {@link #getCount} on that object must
+ * be >= n
for all n
in C
.
+ **/
+ public boolean containsAll(Collection c);
+
+ /**
+ * Remove all elements represented in the given collection,
+ * respecting cardinality. That is, if the given collection
+ * C
contains n
copies of a given object,
+ * the bag will have n
fewer copies, assuming the bag
+ * had at least n
copies to begin with.
+ * @return true
if this call changed the collection
+ **/
+ public boolean removeAll(Collection c);
+
+ /**
+ * Remove any members of the bag that are not in the given
+ * collection, respecting cardinality. That is, if the given
+ * collection C
contains n
copies of a
+ * given object and the bag has m > n
copies, then
+ * delete m - n
copies from the bag. In addition, if
+ * e
is an object in the bag but
+ * !C.contains(e)
, then remove e
and any
+ * of its copies.
+ *
+ * @return true
if this call changed the collection
+ **/
+ public boolean retainAll(Collection c);
+
+ /**
+ * Returns an {@link Iterator} over the entire set of members,
+ * including copies due to cardinality. This iterator is fail-fast
+ * and will not tolerate concurrent modifications.
+ **/
+ public Iterator iterator();
+}
+
+
+
+
+
diff --git a/src/java/org/apache/commons/collections/HashBag.java b/src/java/org/apache/commons/collections/HashBag.java
new file mode 100644
index 000000000..038c620c7
--- /dev/null
+++ b/src/java/org/apache/commons/collections/HashBag.java
@@ -0,0 +1,89 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/HashBag.java,v 1.1 2001/08/29 15:28:07 jstrachan Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/08/29 15:28:07 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ *
- Java Collections Framework extensions. -
-- See also the java.util package. -
-Category | Classes | Comments | -
---|---|---|
List Implementations | -
- {@link org.apache.commons.collections.CursorableLinkedList} - {@link org.apache.commons.collections.FastArrayList} - |
- - Special-purpose implementations of the {@link - java.util.List} interface. - | -
Map Implementations | -
- {@link org.apache.commons.collections.BeanMap} - {@link org.apache.commons.collections.DefaultMapEntry} - {@link org.apache.commons.collections.ExtendedProperties} - {@link org.apache.commons.collections.FastHashMap} - {@link org.apache.commons.collections.FastTreeMap} - {@link org.apache.commons.collections.LRUMap} - {@link org.apache.commons.collections.SoftRefHashMap} - |
- - Special-purpose implementations of the {@link - java.util.Map} interface. - | -
Stack and Queue Implementations | -
- {@link org.apache.commons.collections.ArrayStack} - {@link org.apache.commons.collections.BinaryHeap} - {@link org.apache.commons.collections.PriorityQueue} - {@link org.apache.commons.collections.SynchronizedPriorityQueue} - |
- - Special-purpose implementations of the {@link - java.util.Stack} interface, as well as similar {@link - org.apache.commons.collections.PriorityQueue} - interface. - | -
Adapters | -
- {@link org.apache.commons.collections.ArrayEnumeration} - {@link org.apache.commons.collections.ArrayIterator} - {@link org.apache.commons.collections.EnumerationIterator} - {@link org.apache.commons.collections.IteratorEnumeration} - |
- - Access Java1-style containers as though they were - Java2-style Collections and vice-versa. - | -
Utilities | -
- {@link org.apache.commons.collections.Closure} - {@link org.apache.commons.collections.CollectionUtils} - {@link org.apache.commons.collections.MapUtils} - |
- - Manipulate collection objects, determine set theoretic - properties, ensure type-safety, etc. - | -
Transformation Tools | -
- {@link org.apache.commons.collections.FilterIterator} - {@link org.apache.commons.collections.Predicate} - {@link org.apache.commons.collections.ProxyIterator} - {@link org.apache.commons.collections.Transformer} - {@link org.apache.commons.collections.TransformIterator} - |
- - Create views or functors on a collection. If your collection - represents X, these allow you to define and look at - f(X). - | -
+ Java Collections Framework extensions. +
++ See also the java.util package. +
+Category | Classes | Comments | +
---|---|---|
List Implementations | +
+ {@link org.apache.commons.collections.CursorableLinkedList} + {@link org.apache.commons.collections.FastArrayList} + |
+ + Special-purpose implementations of the {@link + java.util.List} interface. + | +
Map Implementations | +
+ {@link org.apache.commons.collections.BeanMap} + {@link org.apache.commons.collections.DefaultMapEntry} + {@link org.apache.commons.collections.ExtendedProperties} + {@link org.apache.commons.collections.FastHashMap} + {@link org.apache.commons.collections.FastTreeMap} + {@link org.apache.commons.collections.LRUMap} + {@link org.apache.commons.collections.SoftRefHashMap} + |
+ + Special-purpose implementations of the {@link + java.util.Map} interface. + | +
Stack and Queue Implementations | +
+ {@link org.apache.commons.collections.ArrayStack} + {@link org.apache.commons.collections.BinaryHeap} + {@link org.apache.commons.collections.PriorityQueue} + {@link org.apache.commons.collections.SynchronizedPriorityQueue} + |
+ + Special-purpose implementations of the {@link + java.util.Stack} interface, as well as similar {@link + org.apache.commons.collections.PriorityQueue} + interface. + | +Bag Interface and Implementations | +
+ {@link org.apache.commons.collections.Bag} + {@link org.apache.commons.collections.HashBag} + {@link org.apache.commons.collections.SortedBag} + {@link org.apache.commons.collections.TreeBag} + |
+ + New collections interface that keeps a count of its members. + | + +
Adapters | +
+ {@link org.apache.commons.collections.ArrayEnumeration} + {@link org.apache.commons.collections.ArrayIterator} + {@link org.apache.commons.collections.EnumerationIterator} + {@link org.apache.commons.collections.IteratorEnumeration} + |
+ + Access Java1-style containers as though they were + Java2-style Collections and vice-versa. + | +
Utilities | +
+ {@link org.apache.commons.collections.Closure} + {@link org.apache.commons.collections.CollectionUtils} + {@link org.apache.commons.collections.MapUtils} + |
+ + Manipulate collection objects, determine set theoretic + properties, ensure type-safety, etc. + | +
Transformation Tools | +
+ {@link org.apache.commons.collections.FilterIterator} + {@link org.apache.commons.collections.Predicate} + {@link org.apache.commons.collections.ProxyIterator} + {@link org.apache.commons.collections.Transformer} + {@link org.apache.commons.collections.TransformIterator} + |
+ + Create views or functors on a collection. If your collection + represents X, these allow you to define and look at + f(X). + | +
+ * To use, simply extend this class, and implement + * the {@link #makeBag} method. + *
+ * If your {@link Bag} fails one of these tests by design,
+ * you may still use this base set of cases. Simply override the
+ * test case (method) your {@link Bag} fails.
+ *
+ * @author Chuck Burdick
+ * @version $Id: TestBag.java,v 1.1 2001/08/29 15:28:07 jstrachan Exp $
+ */
+public abstract class TestBag extends TestCollection {
+ public TestBag(String testName) {
+ super(testName);
+ }
+
+ /**
+ * Return a new, empty {@link Bag} to used for testing.
+ */
+ public abstract Bag makeBag();
+
+ public Collection makeCollection() {
+ return makeBag();
+ }
+
+ public void testBagAdd() {
+ Bag bag = makeBag();
+ bag.add("A");
+ assertTrue("Should contain 'A'", bag.contains("A"));
+ assertEquals("Should have count of 1",
+ 1, bag.getCount("A"));
+ bag.add("A");
+ assertTrue("Should contain 'A'", bag.contains("A"));
+ assertEquals("Should have count of 2",
+ 2, bag.getCount("A"));
+ bag.add("B");
+ assertTrue(bag.contains("A"));
+ assertTrue(bag.contains("B"));
+ }
+
+ public void testBagEqualsSelf() {
+ Bag bag = makeBag();
+ assertTrue(bag.equals(bag));
+ bag.add("elt");
+ assertTrue(bag.equals(bag));
+ bag.add("elt"); // again
+ assertTrue(bag.equals(bag));
+ bag.add("elt2");
+ assertTrue(bag.equals(bag));
+ }
+
+ public void testRemove() {
+ Bag bag = makeBag();
+ bag.add("A");
+ assertEquals("Should have count of 1", 1, bag.getCount("A"));
+ bag.remove("A");
+ assertEquals("Should have count of 0", 0, bag.getCount("A"));
+ bag.add("A");
+ bag.add("A");
+ bag.add("A");
+ bag.add("A");
+ assertEquals("Should have count of 4", 4, bag.getCount("A"));
+ bag.remove("A", 0);
+ assertEquals("Should have count of 4", 4, bag.getCount("A"));
+ bag.remove("A", 2);
+ assertEquals("Should have count of 2", 2, bag.getCount("A"));
+ bag.remove("A");
+ assertEquals("Should have count of 0", 0, bag.getCount("A"));
+ }
+
+ public void testRemoveAll() {
+ Bag bag = makeBag();
+ bag.add("A", 2);
+ assertEquals("Should have count of 2", 2, bag.getCount("A"));
+ bag.add("B");
+ bag.add("C");
+ assertEquals("Should have count of 4", 4, bag.size());
+ List delete = new ArrayList();
+ delete.add("A");
+ delete.add("B");
+ bag.removeAll(delete);
+ assertEquals("Should have count of 1", 1, bag.getCount("A"));
+ assertEquals("Should have count of 0", 0, bag.getCount("B"));
+ assertEquals("Should have count of 1", 1, bag.getCount("C"));
+ assertEquals("Should have count of 2", 2, bag.size());
+ }
+
+ public void testContains() {
+ Bag bag = makeBag();
+ bag.add("A");
+ bag.add("A");
+ bag.add("A");
+ bag.add("B");
+ bag.add("B");
+ List compare = new ArrayList();
+ compare.add("A");
+ compare.add("B");
+ assertEquals("Other list has 1 'B'", 1,
+ (new HashBag(compare)).getCount("B"));
+ assertTrue("Bag has at least 1 'B'", 1 <= bag.getCount("B"));
+ assertTrue("Bag contains items in the list", bag.containsAll(compare));
+ compare.add("A");
+ compare.add("B");
+ assertEquals("Other list has 2 'B'", 2,
+ (new HashBag(compare)).getCount("B"));
+ assertTrue("Bag has at least 2 'B'", 2 <= bag.getCount("B"));
+ assertTrue("Bag contains items in the list", bag.containsAll(compare));
+ compare.add("A");
+ compare.add("B");
+ assertEquals("Other list has 3 'B'", 3,
+ (new HashBag(compare)).getCount("B"));
+ assertTrue("Bag does not have 3 'B'", 3 > bag.getCount("B"));
+ assertTrue("Bag contains items in the list", !bag.containsAll(compare));
+ }
+
+ public void testSize() {
+ Bag bag = makeBag();
+ bag.add("A");
+ bag.add("A");
+ bag.add("A");
+ bag.add("B");
+ bag.add("B");
+ assertEquals("Should have 5 total items", 5, bag.size());
+ bag.remove("A", 2);
+ assertEquals("Should have 1 'A'", 1, bag.getCount("A"));
+ assertEquals("Should have 3 total items", 3, bag.size());
+ bag.remove("B");
+ assertEquals("Should have 1 total item", 1, bag.size());
+ }
+
+ public void testRetainAll() {
+ Bag bag = makeBag();
+ bag.add("A");
+ bag.add("A");
+ bag.add("A");
+ bag.add("B");
+ bag.add("B");
+ bag.add("C");
+ List retains = new ArrayList();
+ retains.add("B");
+ retains.add("C");
+ bag.retainAll(retains);
+ assertEquals("Should have 2 total items", 2, bag.size());
+ }
+
+ public void testIterator() {
+ Bag bag = makeBag();
+ bag.add("A");
+ bag.add("A");
+ bag.add("B");
+ assertEquals("Bag should have 3 items", 3, bag.size());
+ Iterator i = bag.iterator();
+ assertEquals("First should be 'A'", "A", i.next());
+ assertEquals("Second should be 'A'", "A", i.next());
+ i.remove();
+ assertEquals("Third should be 'B'", "B", i.next());
+ assertTrue("Should have no more", !i.hasNext());
+ assertEquals("Bag should have 2 items", 2, bag.size());
+ assertEquals("Bag should have 1 'A'", 1, bag.getCount("A"));
+ }
+
+ public void testIteratorFail() {
+ Bag bag = makeBag();
+ bag.add("A");
+ bag.add("A");
+ bag.add("B");
+ Iterator i = bag.iterator();
+ assertEquals("First should be 'A'", "A", i.next());
+ bag.remove("A");
+ try {
+ i.next();
+ fail("Should throw ConcurrentModificationException");
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+}
+
+
diff --git a/src/test/org/apache/commons/collections/TestHashBag.java b/src/test/org/apache/commons/collections/TestHashBag.java
new file mode 100644
index 000000000..403d1a77e
--- /dev/null
+++ b/src/test/org/apache/commons/collections/TestHashBag.java
@@ -0,0 +1,90 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/TestHashBag.java,v 1.1 2001/08/29 15:28:07 jstrachan Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/08/29 15:28:07 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ *