commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From skes...@apache.org
Subject svn commit: r593144 [1/2] - in /commons/proper/collections/branches/collections_jdk5_branch: ./ src/java/org/apache/commons/collections/ src/test/org/apache/commons/collections/
Date Thu, 08 Nov 2007 12:21:56 GMT
Author: skestle
Date: Thu Nov  8 04:21:55 2007
New Revision: 593144

URL: http://svn.apache.org/viewvc?rev=593144&view=rev
Log:
Updated CollectionUtils and test.  Probably 80-90% complete for generics.  Very open to review / patches.

Jira: COLLECTIONS-245

Added:
    commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/MockTestCase.java
Modified:
    commons/proper/collections/branches/collections_jdk5_branch/build.xml
    commons/proper/collections/branches/collections_jdk5_branch/project.xml
    commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/CollectionUtils.java
    commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestCollectionUtils.java

Modified: commons/proper/collections/branches/collections_jdk5_branch/build.xml
URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/build.xml?rev=593144&r1=593143&r2=593144&view=diff
==============================================================================
--- commons/proper/collections/branches/collections_jdk5_branch/build.xml (original)
+++ commons/proper/collections/branches/collections_jdk5_branch/build.xml Thu Nov  8 04:21:55 2007
@@ -86,10 +86,17 @@
   <property name="build.src.tar.name"   value="${build.dist}/${component.name}-${component.version}-src.tar"/>
   <property name="build.src.gz.name"    value="${build.dist}/${component.name}-${component.version}-src.tar.gz"/>
   <property name="build.src.zip.name"   value="${build.dist}/${component.name}-${component.version}-src.zip"/>
-  <property name="dist.home"            value="dist"/> <!-- for nightly builds -->
+  <property name="dist.home"            value="dist"/>
+  <!-- for nightly builds -->
 
+  <!-- Path variables -->
+  <path id="test.support.path">
+    <!--Combines all jar references needed for running and compiling tests-->
+    <pathelement location="${junit.jar}" />
+    <pathelement location="${easymock.jar}" />
+  </path>
 
-<!-- ========== Settings ================================================== -->
+  <!-- ========== Settings ================================================== -->
 
   <!-- Javac -->
   <property name="compile.debug"           value="true"/>
@@ -107,30 +114,30 @@
   <property name="maven.repo"  value="${user.home}/.maven/repository" />
 
 
-<!-- ====================================================================== -->
-<!-- ========== Executable Targets ======================================== -->
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
+  <!-- ========== Executable Targets ======================================== -->
+  <!-- ====================================================================== -->
 
   <target name="clean"
           description="Clean build and distribution directories">
     <delete dir="${build.home}"/>
   </target>
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
 
   <target name="init"
           description="Initialize and evaluate conditionals">
     <echo message="-------- ${component.name} ${component.version} --------"/>
   </target>
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
 
   <target name="prepare" depends="init"
           description="Prepare build directory">
     <mkdir dir="${build.home}"/>
   </target>
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
 
   <target name="compile" depends="prepare"
           description="Compile main code">
@@ -143,7 +150,7 @@
     </javac>
   </target>
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
 
   <target name="jar" depends="compile"
           description="Create jar">
@@ -152,7 +159,7 @@
              tofile="${build.classes}/META-INF/LICENSE.txt"/>
     <copy      file="NOTICE.txt"
              tofile="${build.classes}/META-INF/NOTICE.txt"/>
-             
+
     <tstamp/>
     <mkdir      dir="${build.conf}"/>
     <copy     todir="${build.conf}" filtering="on">
@@ -164,14 +171,14 @@
       </filterset>
       <fileset dir="${source.conf}" includes="*.MF"/>
     </copy>
-             
+
     <!-- NOTE: A jar built using JDK1.4 is incompatible with JDK1.2 -->
     <jar    jarfile="${build.jar.name}"
             basedir="${build.classes}"
            manifest="${build.conf}/MANIFEST.MF"/>
   </target>
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
   <!-- Targets you might use to get smaller jar files - not recommended -->
 
   <target name="splitjar" depends="jar"
@@ -273,7 +280,7 @@
 
   </target>
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
 
   <target name="compile.tests" depends="compile"
           description="Compile unit test cases">
@@ -285,12 +292,12 @@
           optimize="false">
       <classpath>
         <pathelement location="${build.classes}"/>
-        <pathelement location="${junit.jar}"/>
+        <path refid="test.support.path"/>
       </classpath>
     </javac>
   </target>
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
 
   <!-- Tests collections, either running all or one test -->
   <target name="test" depends="-test-all,-test-single"
@@ -320,8 +327,8 @@
         <pathelement location="${build.instrumented}"/>
         <pathelement location="${build.classes}"/>
         <pathelement location="${build.tests}"/>
-        <pathelement location="${junit.jar}"/>
-        <path refid="emma.lib"/>
+        <path refid="test.support.path"/>
+      	<path refid="emma.lib"/>
       </classpath>
       <jvmarg value="-Demma.coverage.out.file=${build.reports.coverage}/coverage.ec" />
       <jvmarg value="-Demma.coverage.out.merge=true" />
@@ -379,7 +386,7 @@
 	</target>
 
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
 
   <target name="testjar"  depends="compile.tests,jar"
           description="Run all unit test cases">
@@ -400,11 +407,13 @@
     </junit>
   </target>
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
 
   <target name="javadoc" depends="prepare"
           description="Create component Javadoc documentation">
-    <tstamp><format property="year" pattern="yyyy"/></tstamp>
+    <tstamp>
+      <format property="year" pattern="yyyy"/>
+    </tstamp>
     <delete     dir="${build.docs}"/>
     <mkdir      dir="${build.docs}"/>
     <javadoc sourcepath="${source.java}"
@@ -422,10 +431,10 @@
     </javadoc>
   </target>
 
-<!-- ====================================================================== -->
-<!-- ========== Test framework ============================================ -->
-<!-- ====================================================================== -->
-   
+  <!-- ====================================================================== -->
+  <!-- ========== Test framework ============================================ -->
+  <!-- ====================================================================== -->
+
   <property name="tf.name"                 value="commons-collections-testframework"/>
   <property name="tf.package"              value="org.apache.commons.collections"/>
   <property name="tf.title"                value="Commons Collections Test Framework"/>
@@ -435,12 +444,12 @@
   <property name="tf.build.conf"           value="${build.home}/tfconf"/>
   <property name="tf.build.tf"             value="${build.home}/testframework"/>
   <property name="tf.build.docs"           value="${build.home}/docs/testframework"/>
-  
+
   <property name="tf.jar.name" value="${tf.name}-${tf.version}.jar"/>
   <property name="tf.build.jar.name" value="${build.home}/${tf.jar.name}"/>
 
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
 
   <!-- patternset describing test framework source not dependent on collections jar -->
   <patternset id="tf.patternset.validate">
@@ -457,7 +466,7 @@
     <include name="**/AbstractTestMapEntry.java"/>
     <include name="**/BulkTest.java"/>
   </patternset>
-  
+
   <target name="tf.validate" depends="prepare"
           description="Testframework - Validate testframework independence">
     <delete    dir="${tf.build.tf}"/>
@@ -475,7 +484,7 @@
     <delete dir="${tf.build.tf}"/>
   </target>
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
 
   <target name="tf.jar" depends="compile.tests"
           description="Testframework - Create jar">
@@ -486,13 +495,13 @@
         <include name="**/BulkTest*.class"/>
       </fileset>
     </copy>
-    
+
     <mkdir      dir="${tf.build.tf}/META-INF"/>
     <copy      file="LICENSE.txt"
              tofile="${tf.build.tf}/META-INF/LICENSE.txt"/>
     <copy      file="NOTICE.txt"
              tofile="${tf.build.tf}/META-INF/NOTICE.txt"/>
-             
+
     <tstamp/>
     <mkdir      dir="${tf.build.conf}"/>
     <copy     todir="${tf.build.conf}" filtering="on">
@@ -504,18 +513,20 @@
       </filterset>
       <fileset dir="${source.conf}" includes="*.MF"/>
     </copy>
-             
+
     <!-- NOTE: A jar built using JDK1.4 is incompatible with JDK1.2 -->
     <jar    jarfile="${tf.build.jar.name}"
             basedir="${tf.build.tf}"
            manifest="${tf.build.conf}/MANIFEST.MF"/>
   </target>
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
 
   <target name="tf.javadoc" depends="prepare"
           description="Testframework - Create Javadoc documentation">
-    <tstamp><format property="year" pattern="yyyy"/></tstamp>
+    <tstamp>
+      <format property="year" pattern="yyyy"/>
+    </tstamp>
     <delete     dir="${tf.build.docs}"/>
     <mkdir      dir="${tf.build.docs}"/>
     <javadoc    destdir="${tf.build.docs}"
@@ -535,11 +546,11 @@
   </target>
 
 
-<!-- ====================================================================== -->
-<!-- ========== Distributions ============================================= -->
-<!-- ====================================================================== -->
-   
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
+  <!-- ========== Distributions ============================================= -->
+  <!-- ====================================================================== -->
+
+  <!-- ====================================================================== -->
 
   <!-- Target needed for nightly builds -->
   <target name="dist" depends="javadoc,dist.create"
@@ -548,7 +559,7 @@
     <mkdir dir="${dist.home}" />
     <copy todir="${dist.home}">
       <fileset dir="${build.dist.bin}" />
-	</copy>
+    </copy>
   </target>
 
   <target name="dist.create" depends="jar,testjar,tf.validate,tf.jar,dist.bin,dist.src">
@@ -565,7 +576,7 @@
     <antcall target="internal-md5">
       <param name="path" value="${build.home}/${final.name}.jar"/>
     </antcall>
-  	
+
     <mkdir      dir="${build.dist.bin.work}"/>
     <copy     todir="${build.dist.bin.work}">
       <fileset dir=".">
@@ -582,7 +593,7 @@
       </fileset>
     </copy>
   </target>
-  
+
   <target name="dist.src">
     <mkdir      dir="${build.dist.src.work}"/>
     <copy     todir="${build.dist.src.work}">
@@ -614,12 +625,12 @@
     </copy>
   </target>
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
 
   <target name="release" depends="dist.create,zip"
           description="Create release">
-  	<!-- POM -->
-  	<copy file="project.xml" tofile="${build.home}/${final.name}.pom" />
+    <!-- POM -->
+    <copy file="project.xml" tofile="${build.home}/${final.name}.pom" />
     <antcall target="internal-md5">
       <param name="path" value="${build.home}/${final.name}.pom"/>
     </antcall>
@@ -627,10 +638,10 @@
 
   <target name="zip" depends="zip.bin,zip.src">
   </target>
-  
+
   <target name="zip.bin">
     <mkdir dir="${build.dist}"/>
-  	<fixcrlf srcdir="${build.dist.bin.work}" eol="lf" includes="*.txt" />
+    <fixcrlf srcdir="${build.dist.bin.work}" eol="lf" includes="*.txt" />
     <tar longfile="gnu" tarfile="${build.bin.tar.name}">
       <tarfileset dir="${build.dist.bin}"/>
     </tar>
@@ -639,8 +650,8 @@
     <antcall target="internal-md5">
       <param name="path" value="${build.bin.gz.name}"/>
     </antcall>
-    
-  	<fixcrlf srcdir="${build.dist.bin.work}" eol="crlf" includes="*.txt" />
+
+    <fixcrlf srcdir="${build.dist.bin.work}" eol="crlf" includes="*.txt" />
     <zip zipfile="${build.bin.zip.name}" >
       <zipfileset dir="${build.dist.bin}"/>
     </zip>
@@ -651,7 +662,7 @@
 
   <target name="zip.src">
     <mkdir dir="${build.dist}"/>
-  	<fixcrlf srcdir="${build.dist.src.work}" eol="lf" includes="*.txt,*.properties" />
+    <fixcrlf srcdir="${build.dist.src.work}" eol="lf" includes="*.txt,*.properties" />
     <tar longfile="gnu" tarfile="${build.src.tar.name}">
       <tarfileset dir="${build.dist.src}"/>
     </tar>
@@ -660,8 +671,8 @@
     <antcall target="internal-md5">
       <param name="path" value="${build.src.gz.name}"/>
     </antcall>
-    
-  	<fixcrlf srcdir="${build.dist.src.work}" eol="crlf" includes="*.txt,*.properties" />
+
+    <fixcrlf srcdir="${build.dist.src.work}" eol="crlf" includes="*.txt,*.properties" />
     <zip zipfile="${build.src.zip.name}" >
       <zipfileset dir="${build.dist.src}"/>
     </zip>
@@ -673,10 +684,10 @@
   <target name="internal-md5">
     <basename property="_base" file="${path}"/>
     <checksum file="${path}" property="md5"/>
-   	<echo message="${md5} *${_base}" file="${path}.md5"/>
+    <echo message="${md5} *${_base}" file="${path}.md5"/>
   </target>
 
-<!-- ====================================================================== -->
+  <!-- ====================================================================== -->
   <target name="clirr">
     <taskdef resource="clirrtask.properties">
       <classpath path="${maven.repo}/clirr/jars/clirr-core-0.6-uber.jar;" />

Modified: commons/proper/collections/branches/collections_jdk5_branch/project.xml
URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/project.xml?rev=593144&r1=593143&r2=593144&view=diff
==============================================================================
--- commons/proper/collections/branches/collections_jdk5_branch/project.xml (original)
+++ commons/proper/collections/branches/collections_jdk5_branch/project.xml Thu Nov  8 04:21:55 2007
@@ -172,6 +172,10 @@
       <name>Robert Burrell Donkin</name>
       <id>rdonkin</id>
     </developer>
+    <developer>
+       <name>Stephen Kestle</name>
+       <id>skestle</id>
+    </developer>
   </developers>
   
   <contributors>

Modified: commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/CollectionUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/CollectionUtils.java?rev=593144&r1=593143&r2=593144&view=diff
==============================================================================
--- commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/CollectionUtils.java (original)
+++ commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/CollectionUtils.java Thu Nov  8 04:21:55 2007
@@ -36,7 +36,8 @@
 
 /**
  * Provides utility methods and decorators for {@link Collection} instances.
- *
+ * Method parameters will take {@link Iterable} objects when possible.
+ * 
  * @since Commons Collections 1.0
  * @version $Revision$ $Date$
  * 
@@ -55,14 +56,16 @@
  * @author Stephen Smith
  * @author Stephen Kestle
  */
+//TODO - note generic types for review in wiki - especially <?> ones
+//TODO - doc Cardinality Helpers
 public class CollectionUtils {
 
-    private static class CardinalityHelper {
-        final Map<?, Integer> cardinalityA, cardinalityB;
+    private static class CardinalityHelper<O> {
+        final Map<O, Integer> cardinalityA, cardinalityB;
         
-        public CardinalityHelper(Collection a, Collection b) {
-            cardinalityA = getCardinalityMap(a);
-            cardinalityB = getCardinalityMap(b);
+        public <I1 extends O, I2 extends O> CardinalityHelper(Iterable<I1> a, Iterable<I2> b) {
+            cardinalityA = CollectionUtils.<O, I1>getCardinalityMap(a);
+            cardinalityB = CollectionUtils.<O, I2>getCardinalityMap(b);
         }
         
         public final int max(Object obj) {
@@ -90,28 +93,29 @@
         }
     }
     
-    private static class SetOperationCardinalityHelper extends CardinalityHelper implements Iterable {
-        private final Set elements;
-        private final List newList;
+    private static class SetOperationCardinalityHelper<O> extends CardinalityHelper<O> implements Iterable<O> {
+        private final Set<O> elements;
+        private final List<O> newList;
 
-        public SetOperationCardinalityHelper(Collection a, Collection b) {
+        public SetOperationCardinalityHelper(Iterable<? extends O> a, Iterable<? extends O> b) {
             super(a, b);
-            elements = new HashSet(a);
-            elements.addAll(b);
-            newList = new ArrayList();
+            elements = new HashSet<O>();
+            addAll(elements, a);
+            addAll(elements, b);
+            newList = new ArrayList<O>();
         }
 
-        public Iterator iterator() {
+        public Iterator<O> iterator() {
             return elements.iterator();
         }
 
-        public void setCardinality(Object obj, int count) {
+        public void setCardinality(O obj, int count) {
             for (int i = 0; i < count; i++) {
                 newList.add(obj);
             }
         }
 
-        public Collection list() {
+        public Collection<O> list() {
             return newList;
         }
 
@@ -127,7 +131,7 @@
      * this purpose. However they could be cast to Set or List which might be
      * undesirable. This implementation only implements Collection.
      */
-    public static final Collection EMPTY_COLLECTION = UnmodifiableCollection.decorate(new ArrayList());
+    public static final Collection EMPTY_COLLECTION = UnmodifiableCollection.decorate(new ArrayList<Object>());
 
     /**
      * <code>CollectionUtils</code> should not normally be instantiated.
@@ -136,43 +140,62 @@
     }
 
     /**
-     * Returns a {@link Collection} containing the union
-     * of the given {@link Collection}s.
+     * Returns the immutable EMPTY_COLLECTION with generic type safety.
+     * 
+     * @see #EMPTY_COLLECTION
+     * @since 4.0
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Collection<T> emptyCollection() {
+        return EMPTY_COLLECTION;
+    }
+
+    /**
+     * Returns a {@link Collection} containing the union of the given
+     * {@link Collection}s.
      * <p>
-     * The cardinality of each element in the returned {@link Collection}
-     * will be equal to the maximum of the cardinality of that element
-     * in the two given {@link Collection}s.
-     *
-     * @param a  the first collection, must not be null
-     * @param b  the second collection, must not be null
-     * @return  the union of the two collections
+     * The cardinality of each element in the returned {@link Collection} will
+     * be equal to the maximum of the cardinality of that element in the two
+     * given {@link Collection}s.
+     * 
+     * @param a the first collection, must not be null
+     * @param b the second collection, must not be null
+     * @param <O> the generic type that is able to represent the types contained
+     *        in both input collections.
+     * @param <I1> the generic type of the first input {@link Iterable}.
+     * @param <I2> the generic type of the second input {@link Iterable}.
+     * @return the union of the two collections
      * @see Collection#addAll
      */
-    public static Collection union(final Collection a, final Collection b) {
-        SetOperationCardinalityHelper helper = new SetOperationCardinalityHelper(a, b);
-        for (Object obj : helper) {
+    public static <O> Collection<O> union(final Iterable<? extends O> a, final Iterable<? extends O> b) {
+        SetOperationCardinalityHelper<O> helper = new SetOperationCardinalityHelper<O>(a, b);
+        for (O obj : helper) {
             helper.setCardinality(obj, helper.max(obj));
         }
         return helper.list();
     }
 
     /**
-     * Returns a {@link Collection} containing the intersection
-     * of the given {@link Collection}s.
+     * Returns a {@link Collection} containing the intersection of the given
+     * {@link Collection}s.
      * <p>
-     * The cardinality of each element in the returned {@link Collection}
-     * will be equal to the minimum of the cardinality of that element
-     * in the two given {@link Collection}s.
-     *
-     * @param a  the first collection, must not be null
-     * @param b  the second collection, must not be null
+     * The cardinality of each element in the returned {@link Collection} will
+     * be equal to the minimum of the cardinality of that element in the two
+     * given {@link Collection}s.
+     * 
+     * @param a the first collection, must not be null
+     * @param b the second collection, must not be null
+     * @param <O> the generic type that is able to represent the types contained
+     *        in both input collections.
+     * @param <I1> the generic type of the first input {@link Iterable}.
+     * @param <I2> the generic type of the second input {@link Iterable}.
      * @return the intersection of the two collections
      * @see Collection#retainAll
      * @see #containsAny
      */
-    public static Collection intersection(final Collection a, final Collection b) {
-        SetOperationCardinalityHelper helper = new SetOperationCardinalityHelper(a, b);
-        for (Object obj : helper) {
+    public static <O> Collection<O> intersection(final Iterable<? extends O> a, final Iterable<? extends O> b) {
+        SetOperationCardinalityHelper<O> helper = new SetOperationCardinalityHelper<O>(a, b);
+        for (O obj : helper) {
             helper.setCardinality(obj, helper.min(obj));
         }
         return helper.list();
@@ -182,22 +205,26 @@
      * Returns a {@link Collection} containing the exclusive disjunction
      * (symmetric difference) of the given {@link Collection}s.
      * <p>
-     * The cardinality of each element <i>e</i> in the returned {@link Collection}
-     * will be equal to
+     * The cardinality of each element <i>e</i> in the returned
+     * {@link Collection} will be equal to
      * <tt>max(cardinality(<i>e</i>,<i>a</i>),cardinality(<i>e</i>,<i>b</i>)) - min(cardinality(<i>e</i>,<i>a</i>),cardinality(<i>e</i>,<i>b</i>))</tt>.
      * <p>
      * This is equivalent to
      * <tt>{@link #subtract subtract}({@link #union union(a,b)},{@link #intersection intersection(a,b)})</tt>
      * or
      * <tt>{@link #union union}({@link #subtract subtract(a,b)},{@link #subtract subtract(b,a)})</tt>.
-     *
-     * @param a  the first collection, must not be null
-     * @param b  the second collection, must not be null
+     
+     * @param a the first collection, must not be null
+     * @param b the second collection, must not be null
+     * @param <O> the generic type that is able to represent the types contained
+     *        in both input collections.
+     * @param <I1> the generic type of the first input {@link Iterable}.
+     * @param <I2> the generic type of the second input {@link Iterable}.
      * @return the symmetric difference of the two collections
      */
-    public static Collection disjunction(final Collection a, final Collection b) {
-        SetOperationCardinalityHelper helper = new SetOperationCardinalityHelper(a, b);
-        for (Object obj : helper) {
+    public static <O> Collection<O> disjunction(final Iterable<? extends O> a, final Iterable<? extends O> b) {
+        SetOperationCardinalityHelper<O> helper = new SetOperationCardinalityHelper<O>(a, b);
+        for (O obj : helper) {
             helper.setCardinality(obj, helper.max(obj) - helper.min(obj));
         }
         return helper.list();
@@ -211,13 +238,18 @@
      *
      * @param a  the collection to subtract from, must not be null
      * @param b  the collection to subtract, must not be null
+     * @param <O> the generic type that is able to represent the types contained
+     *        in both input collections.
+     * @param <I1> the generic type of the first input {@link Iterable}.
+     * @param <I2> the generic type of the second input {@link Iterable}.
      * @return a new collection with the results
      * @see Collection#removeAll
      */
-    public static Collection subtract(final Collection a, final Collection b) {
-        ArrayList list = new ArrayList( a );
-        for (Iterator it = b.iterator(); it.hasNext();) {
-            list.remove(it.next());
+    public static <O> Collection<O> subtract(final Iterable<? extends O> a, final Iterable<? extends O> b) {
+        ArrayList<O> list = new ArrayList<O>();
+        addAll(list, a);
+        for (O element : b) {
+            list.remove(element);
         }
         return list;
     }
@@ -259,18 +291,24 @@
      * Only those elements present in the collection will appear as
      * keys in the map.
      * 
-     * @param coll  the collection to get the cardinality map for, must not be null
+     * @param coll
+     *            the collection to get the cardinality map for, must not be
+     *            null
+     * @param <I>
+     *            the type of object in the input {@link Collection}
+     * @param <O>
+     *            the type of object in the returned {@link Map}. This is a
+     *            super type of <I>.
      * @return the populated cardinality map
      */
-    public static Map getCardinalityMap(final Collection coll) {
-        Map count = new HashMap();
-        for (Iterator it = coll.iterator(); it.hasNext();) {
-            Object obj = it.next();
-            Integer c = (Integer) (count.get(obj));
+    public static <O, I extends O> Map<O, Integer> getCardinalityMap(final Iterable<I> coll) {
+        Map<O, Integer> count = new HashMap<O, Integer>();
+        for (I obj : coll) {
+            Integer c = count.get(obj);
             if (c == null) {
-                count.put(obj,INTEGER_ONE);
+                count.put(obj, INTEGER_ONE);
             } else {
-                count.put(obj,new Integer(c.intValue() + 1));
+                count.put(obj, c + 1);
             }
         }
         return count;
@@ -278,18 +316,18 @@
 
     /**
      * Returns <tt>true</tt> iff <i>a</i> is a sub-collection of <i>b</i>,
-     * that is, iff the cardinality of <i>e</i> in <i>a</i> is less
-     * than or equal to the cardinality of <i>e</i> in <i>b</i>,
-     * for each element <i>e</i> in <i>a</i>.
-     *
-     * @param a  the first (sub?) collection, must not be null
-     * @param b  the second (super?) collection, must not be null
+     * that is, iff the cardinality of <i>e</i> in <i>a</i> is less than or
+     * equal to the cardinality of <i>e</i> in <i>b</i>, for each element <i>e</i>
+     * in <i>a</i>.
+     * 
+     * @param a the first (sub?) collection, must not be null
+     * @param b the second (super?) collection, must not be null
      * @return <code>true</code> iff <i>a</i> is a sub-collection of <i>b</i>
      * @see #isProperSubCollection
      * @see Collection#containsAll
      */
-    public static boolean isSubCollection(final Collection a, final Collection b) {
-        CardinalityHelper helper = new CardinalityHelper(a, b);
+    public static boolean isSubCollection(final Collection<?> a, final Collection<?> b) {
+        CardinalityHelper<Object> helper = new CardinalityHelper<Object>(a, b);
         for (Object obj : a) {
             if (helper.freqA(obj) > helper.freqB(obj)) {
                 return false;
@@ -319,8 +357,8 @@
      * @see #isSubCollection
      * @see Collection#containsAll
      */
-    public static boolean isProperSubCollection(final Collection a, final Collection b) {
-        return (a.size() < b.size()) && CollectionUtils.isSubCollection(a,b);
+    public static boolean isProperSubCollection(final Collection<?> a, final Collection<?> b) {
+        return (a.size() < b.size()) && CollectionUtils.isSubCollection(a, b);
     }
 
     /**
@@ -335,11 +373,11 @@
      * @param b  the second collection, must not be null
      * @return <code>true</code> iff the collections contain the same elements with the same cardinalities.
      */
-    public static boolean isEqualCollection(final Collection a, final Collection b) {
+    public static boolean isEqualCollection(final Collection<?> a, final Collection<?> b) {
         if(a.size() != b.size()) {
             return false;
         }
-        final CardinalityHelper helper = new CardinalityHelper(a, b);
+        final CardinalityHelper<Object> helper = new CardinalityHelper<Object>(a, b);
         if(helper.cardinalityA.size() != helper.cardinalityB.size()) {
             return false;
         }
@@ -353,28 +391,29 @@
 
     /**
      * Returns the number of occurrences of <i>obj</i> in <i>coll</i>.
-     *
-     * @param obj  the object to find the cardinality of
-     * @param coll  the collection to search
+     * 
+     * @param obj the object to find the cardinality of
+     * @param coll the {@link Iterable} to search
+     * @param <O> the type of object that the {@link Iterable} may contain.
      * @return the the number of occurrences of obj in coll
      */
-    public static int cardinality(Object obj, final Collection coll) {
+    public static <O> int cardinality(O obj, final Iterable<? super O> coll) {
         if (coll instanceof Set) {
-            return (coll.contains(obj) ? 1 : 0);
+            return (((Set<? super O>) coll).contains(obj) ? 1 : 0);
         }
         if (coll instanceof Bag) {
-            return ((Bag) coll).getCount(obj);
+            return ((Bag<? super O>) coll).getCount(obj);
         }
         int count = 0;
         if (obj == null) {
-            for (Iterator it = coll.iterator();it.hasNext();) {
-                if (it.next() == null) {
+            for (Object element : coll) {
+                if (element == null) {
                     count++;
                 }
             }
         } else {
-            for (Iterator it = coll.iterator();it.hasNext();) {
-                if (obj.equals(it.next())) {
+            for (Object element : coll) {
+                if (obj.equals(element)) {
                     count++;
                 }
             }
@@ -392,10 +431,9 @@
      * @param predicate  the predicate to use, may be null
      * @return the first element of the collection which matches the predicate or null if none could be found
      */
-    public static Object find(Collection collection, Predicate predicate) {
+    public static <T> T find(Collection<T> collection, Predicate<? super T> predicate) {
         if (collection != null && predicate != null) {
-            for (Iterator iter = collection.iterator(); iter.hasNext();) {
-                Object item = iter.next();
+            for (T item : collection) {
                 if (predicate.evaluate(item)) {
                     return item;
                 }
@@ -403,35 +441,39 @@
         }
         return null;
     }
-    
-    /** 
+
+    /**
      * Executes the given closure on each element in the collection.
      * <p>
      * If the input collection or closure is null, there is no change made.
      * 
-     * @param collection  the collection to get the input from, may be null
-     * @param closure  the closure to perform, may be null
+     * @param collection
+     *            the collection to get the input from, may be null
+     * @param closure
+     *            the closure to perform, may be null
      */
-    public static void forAllDo(Collection collection, Closure closure) {
+    public static <T> void forAllDo(Collection<T> collection, Closure<? super T> closure) {
         if (collection != null && closure != null) {
-            for (Iterator it = collection.iterator(); it.hasNext();) {
-                closure.execute(it.next());
+            for (T element : collection) {
+                closure.execute(element);
             }
         }
     }
 
-    /** 
+    /**
      * Filter the collection by applying a Predicate to each element. If the
      * predicate returns false, remove the element.
      * <p>
      * If the input collection or predicate is null, there is no change made.
      * 
-     * @param collection  the collection to get the input from, may be null
-     * @param predicate  the predicate to use as a filter, may be null
+     * @param collection
+     *            the collection to get the input from, may be null
+     * @param predicate
+     *            the predicate to use as a filter, may be null
      */
-    public static void filter(Collection collection, Predicate predicate) {
+    public static <T> void filter(Iterable<T> collection, Predicate<? super T> predicate) {
         if (collection != null && predicate != null) {
-            for (Iterator it = collection.iterator(); it.hasNext();) {
+            for (Iterator<T> it = collection.iterator(); it.hasNext();) {
                 if (predicate.evaluate(it.next()) == false) {
                     it.remove();
                 }
@@ -439,51 +481,56 @@
         }
     }
 
-    /** 
+    /**
      * Transform the collection by applying a Transformer to each element.
      * <p>
      * If the input collection or transformer is null, there is no change made.
      * <p>
-     * This routine is best for Lists, for which set() is used to do the 
-     * transformations "in place."  For other Collections, clear() and addAll()
-     * are used to replace elements.  
+     * This routine is best for Lists, for which set() is used to do the
+     * transformations "in place." For other Collections, clear() and addAll()
+     * are used to replace elements.
      * <p>
      * If the input collection controls its input, such as a Set, and the
-     * Transformer creates duplicates (or are otherwise invalid), the 
-     * collection may reduce in size due to calling this method.
+     * Transformer creates duplicates (or are otherwise invalid), the collection
+     * may reduce in size due to calling this method.
      * 
-     * @param collection  the collection to get the input from, may be null
-     * @param transformer  the transformer to perform, may be null
+     * @param collection
+     *            the {@link Iterable} to get the input from, may be null
+     * @param transformer
+     *            the transformer to perform, may be null
      */
-    public static void transform(Collection collection, Transformer transformer) {
+    public static <C> void transform(Collection<C> collection, Transformer<? super C, ? extends C> transformer) {
         if (collection != null && transformer != null) {
             if (collection instanceof List) {
-                List list = (List) collection;
-                for (ListIterator it = list.listIterator(); it.hasNext();) {
+                List<C> list = (List<C>) collection;
+                for (ListIterator<C> it = list.listIterator(); it.hasNext();) {
                     it.set(transformer.transform(it.next()));
                 }
             } else {
-                Collection resultCollection = collect(collection, transformer);
+                Collection<C> resultCollection = collect(collection, transformer);
                 collection.clear();
                 collection.addAll(resultCollection);
             }
         }
     }
 
-    /** 
-     * Counts the number of elements in the input collection that match the predicate.
+    /**
+     * Counts the number of elements in the input collection that match the
+     * predicate.
      * <p>
      * A <code>null</code> collection or predicate matches no elements.
      * 
-     * @param inputCollection  the collection to get the input from, may be null
-     * @param predicate  the predicate to use, may be null
+     * @param input
+     *            the {@link Iterable} to get the input from, may be null
+     * @param predicate
+     *            the predicate to use, may be null
      * @return the number of matches for the predicate in the collection
      */
-    public static int countMatches(Collection inputCollection, Predicate predicate) {
+    public static <C> int countMatches(Iterable<C> input, Predicate<? super C> predicate) {
         int count = 0;
-        if (inputCollection != null && predicate != null) {
-            for (Iterator it = inputCollection.iterator(); it.hasNext();) {
-                if (predicate.evaluate(it.next())) {
+        if (input != null && predicate != null) {
+            for (C o : input) {
+                if (predicate.evaluate(o)) {
                     count++;
                 }
             }
@@ -491,19 +538,23 @@
         return count;
     }
 
-    /** 
-     * Answers true if a predicate is true for at least one element of a collection.
+    /**
+     * Answers true if a predicate is true for at least one element of a
+     * collection.
      * <p>
      * A <code>null</code> collection or predicate returns false.
      * 
-     * @param collection the collection to get the input from, may be null
-     * @param predicate the predicate to use, may be null
-     * @return true if at least one element of the collection matches the predicate
-     */
-    public static boolean exists(Collection collection, Predicate predicate) {
-        if (collection != null && predicate != null) {
-            for (Iterator it = collection.iterator(); it.hasNext();) {
-                if (predicate.evaluate(it.next())) {
+     * @param input
+     *            the {@link Iterable} to get the input from, may be null
+     * @param predicate
+     *            the predicate to use, may be null
+     * @return true if at least one element of the collection matches the
+     *         predicate
+     */
+    public static <C> boolean exists(Iterable<C> input, Predicate<? super C> predicate) {
+        if (input != null && predicate != null) {
+            for (C o : input) {
+                if (predicate.evaluate(o)) {
                     return true;
                 }
             }
@@ -511,112 +562,134 @@
         return false;
     }
 
-    /** 
-     * Selects all elements from input collection which match the given predicate
-     * into an output collection.
+    /**
+     * Selects all elements from input collection which match the given
+     * predicate into an output collection.
      * <p>
      * A <code>null</code> predicate matches no elements.
      * 
-     * @param inputCollection  the collection to get the input from, may not be null
-     * @param predicate  the predicate to use, may be null
+     * @param inputCollection
+     *            the collection to get the input from, may not be null
+     * @param predicate
+     *            the predicate to use, may be null
      * @return the elements matching the predicate (new list)
-     * @throws NullPointerException if the input collection is null
+     * @throws NullPointerException
+     *             if the input collection is null
      */
-    public static Collection select(Collection inputCollection, Predicate predicate) {
-        ArrayList answer = new ArrayList(inputCollection.size());
-        select(inputCollection, predicate, answer);
-        return answer;
+    public static <O, I extends O> Collection<O> select(Collection<I> inputCollection, Predicate<? super I> predicate) {
+        return select(inputCollection, predicate, new ArrayList<O>(inputCollection.size()));
     }
 
-    /** 
-     * Selects all elements from input collection which match the given predicate
-     * and adds them to outputCollection.
+    /**
+     * Selects all elements from input collection which match the given
+     * predicate and adds them to outputCollection.
      * <p>
-     * If the input collection or predicate is null, there is no change to the 
+     * If the input collection or predicate is null, there is no change to the
      * output collection.
      * 
-     * @param inputCollection  the collection to get the input from, may be null
-     * @param predicate  the predicate to use, may be null
-     * @param outputCollection  the collection to output into, may not be null
+     * @param inputCollection
+     *            the collection to get the input from, may be null
+     * @param predicate
+     *            the predicate to use, may be null
+     * @param outputCollection
+     *            the collection to output into, may not be null
      */
-    public static void select(Collection inputCollection, Predicate predicate, Collection outputCollection) {
+    public static <O, I extends O> Collection<O> select(Collection<I> inputCollection, Predicate<? super I> predicate, Collection<O> outputCollection) {
         if (inputCollection != null && predicate != null) {
-            for (Iterator iter = inputCollection.iterator(); iter.hasNext();) {
-                Object item = iter.next();
+            for (I item : inputCollection) {
                 if (predicate.evaluate(item)) {
                     outputCollection.add(item);
                 }
             }
         }
+        return outputCollection;
     }
-    
+
     /**
-     * Selects all elements from inputCollection which don't match the given predicate
-     * into an output collection.
+     * Selects all elements from inputCollection which don't match the given
+     * predicate into an output collection.
      * <p>
-     * If the input predicate is <code>null</code>, the result is an empty list.
+     * If the input predicate is <code>null</code>, the result is an empty
+     * list.
      * 
-     * @param inputCollection  the collection to get the input from, may not be null
-     * @param predicate  the predicate to use, may be null
+     * @param inputCollection
+     *            the collection to get the input from, may not be null
+     * @param predicate
+     *            the predicate to use, may be null
      * @return the elements <b>not</b> matching the predicate (new list)
-     * @throws NullPointerException if the input collection is null
+     * @throws NullPointerException
+     *             if the input collection is null
      */
-    public static Collection selectRejected(Collection inputCollection, Predicate predicate) {
-        ArrayList answer = new ArrayList(inputCollection.size());
-        selectRejected(inputCollection, predicate, answer);
-        return answer;
+    public static <O, I extends O> Collection<O> selectRejected(Collection<I> inputCollection, Predicate<? super I> predicate) {
+        return selectRejected(inputCollection, predicate, new ArrayList<O>(inputCollection.size()));
     }
-    
-    /** 
-     * Selects all elements from inputCollection which don't match the given predicate
-     * and adds them to outputCollection.
+
+    /**
+     * Selects all elements from inputCollection which don't match the given
+     * predicate and adds them to outputCollection.
      * <p>
-     * If the input predicate is <code>null</code>, no elements are added to <code>outputCollection</code>.
+     * If the input predicate is <code>null</code>, no elements are added to
+     * <code>outputCollection</code>.
      * 
-     * @param inputCollection  the collection to get the input from, may be null
-     * @param predicate  the predicate to use, may be null
-     * @param outputCollection  the collection to output into, may not be null
+     * @param inputCollection
+     *            the collection to get the input from, may be null
+     * @param predicate
+     *            the predicate to use, may be null
+     * @param outputCollection
+     *            the collection to output into, may not be null
      */
-    public static void selectRejected(Collection inputCollection, Predicate predicate, Collection outputCollection) {
+    public static <O, I extends O> Collection<O> selectRejected(Collection<I> inputCollection, Predicate<? super I> predicate, Collection<O> outputCollection) {
         if (inputCollection != null && predicate != null) {
-            for (Iterator iter = inputCollection.iterator(); iter.hasNext();) {
-                Object item = iter.next();
+            for (I item : inputCollection) {
                 if (predicate.evaluate(item) == false) {
                     outputCollection.add(item);
                 }
             }
         }
+        return outputCollection;
     }
-    
-    /** 
-     * Returns a new Collection consisting of the elements of inputCollection transformed
-     * by the given transformer.
+
+    /**
+     * Returns a new Collection consisting of the elements of inputCollection
+     * transformed by the given transformer.
      * <p>
      * If the input transformer is null, the result is an empty list.
      * 
-     * @param inputCollection  the collection to get the input from, may not be null
-     * @param transformer  the transformer to use, may be null
+     * @param inputCollection
+     *            the collection to get the input from, may not be null
+     * @param transformer
+     *            the transformer to use, may be null
+     * @param <I> the type of object in the input collection
+     * @param <O> the type of object in the output collection
+     * @param <T> the output type of the transformer - this extends O.
      * @return the transformed result (new list)
-     * @throws NullPointerException if the input collection is null
+     * @throws NullPointerException
+     *             if the input collection is null
      */
-    public static Collection collect(Collection inputCollection, Transformer transformer) {
-        ArrayList answer = new ArrayList(inputCollection.size());
+    public static <I,O> Collection<O> collect(Iterable<I> inputCollection, Transformer<? super I, ? extends O> transformer) {
+        ArrayList<O> answer = new ArrayList<O>();
         collect(inputCollection, transformer, answer);
         return answer;
     }
-    
-    /** 
-     * Transforms all elements from the inputIterator with the given transformer 
+
+    /**
+     * Transforms all elements from the inputIterator with the given transformer
      * and adds them to the outputCollection.
      * <p>
-     * If the input iterator or transformer is null, the result is an empty list.
+     * If the input iterator or transformer is null, the result is an empty
+     * list.
      * 
-     * @param inputIterator  the iterator to get the input from, may be null
-     * @param transformer  the transformer to use, may be null
+     * @param inputIterator
+     *            the iterator to get the input from, may be null
+     * @param transformer
+     *            the transformer to use, may be null
+     * @param <I> the type of object in the input collection
+     * @param <O> the type of object in the output collection
+     * @param <T> the output type of the transformer - this extends O.
      * @return the transformed result (new list)
      */
-    public static Collection collect(Iterator inputIterator, Transformer transformer) {
-        ArrayList answer = new ArrayList();
+    public static <I,O> Collection<O> collect(Iterator<I> inputIterator, Transformer<? super I, ? extends O> transformer) {
+        ArrayList<O> answer = new ArrayList<O>();
         collect(inputIterator, transformer, answer);
         return answer;
     }
@@ -631,10 +704,13 @@
      * @param inputCollection  the collection to get the input from, may be null
      * @param transformer  the transformer to use, may be null
      * @param outputCollection  the collection to output into, may not be null
+     * @param <I> the type of object in the input collection
+     * @param <O> the type of object in the output collection
+     * @param <T> the output type of the transformer - this extends O.
      * @return the outputCollection with the transformed input added
      * @throws NullPointerException if the output collection is null
      */
-    public static Collection collect(Collection inputCollection, final Transformer transformer, final Collection outputCollection) {
+    public static <I,O,T extends O> Collection<O> collect(Iterable<I> inputCollection, final Transformer<? super I,T> transformer, final Collection<O> outputCollection) {
         if (inputCollection != null) {
             return collect(inputCollection.iterator(), transformer, outputCollection);
         }
@@ -651,14 +727,18 @@
      * @param inputIterator  the iterator to get the input from, may be null
      * @param transformer  the transformer to use, may be null
      * @param outputCollection  the collection to output into, may not be null
+     * @param <I> the type of object in the input collection
+     * @param <O> the type of object in the output collection
+     * @param <T> the output type of the transformer - this extends O.
      * @return the outputCollection with the transformed input added
      * @throws NullPointerException if the output collection is null
      */
-    public static Collection collect(Iterator inputIterator, final Transformer transformer, final Collection outputCollection) {
+    //TODO - deprecate and replace with IteratorIterable
+    public static <I,O,T extends O> Collection<O> collect(Iterator<I> inputIterator, final Transformer<? super I,T> transformer, final Collection<O> outputCollection) {
         if (inputIterator != null && transformer != null) {
             while (inputIterator.hasNext()) {
-                Object item = inputIterator.next();
-                Object value = transformer.transform(item);
+                I item = inputIterator.next();
+                T value = transformer.transform(item);
                 outputCollection.add(value);
             }
         }
@@ -675,23 +755,49 @@
      * @throws NullPointerException if the collection is null
      * @since Commons Collections 3.2
      */
-    public static boolean addIgnoreNull(Collection collection, Object object) {
+    public static <T> boolean addIgnoreNull(Collection<T> collection, T object) {
         return (object == null ? false : collection.add(object));
     }
-    
+
+    /**
+     * Adds all elements in the {@link Iterable} to the given collection. If the
+     * {@link Iterable} is a {@link Collection} then it is cast and will be
+     * added using {@link Collection#addAll(Collection)} instead of iterating.
+     * 
+     * @param collection
+     *            the collection to add to, must not be null
+     * @param iterable
+     *            the iterable of elements to add, must not be null
+     * @return a boolean indicating whether the collection has changed or not.
+     * @throws NullPointerException
+     *             if the collection or iterator is null
+     */
+    public static <T> boolean addAll(Collection<? super T> collection, Iterable<T> iterable) {
+        if (iterable instanceof Collection) {
+            return collection.addAll((Collection<T>) iterable);
+        }
+        return addAll(collection, iterable.iterator());
+    }
+
     /**
      * Adds all elements in the iteration to the given collection.
      * 
-     * @param collection  the collection to add to, must not be null
-     * @param iterator  the iterator of elements to add, must not be null
-     * @throws NullPointerException if the collection or iterator is null
+     * @param collection
+     *            the collection to add to, must not be null
+     * @param iterator
+     *            the iterator of elements to add, must not be null
+     * @return a boolean indicating whether the collection has changed or not.
+     * @throws NullPointerException
+     *             if the collection or iterator is null
      */
-    public static void addAll(Collection collection, Iterator iterator) {
+    public static <C> boolean addAll(Collection<C> collection, Iterator<? extends C> iterator) {
+        boolean changed = false;
         while (iterator.hasNext()) {
-            collection.add(iterator.next());
+            changed |= collection.add(iterator.next());
         }
+        return changed;
     }
-    
+
     /**
      * Adds all elements in the enumeration to the given collection.
      * 
@@ -699,26 +805,87 @@
      * @param enumeration  the enumeration of elements to add, must not be null
      * @throws NullPointerException if the collection or enumeration is null
      */
-    public static void addAll(Collection collection, Enumeration enumeration) {
+     //TODO return boolean or collection - check other add() methods too.
+    public static <C> void addAll(Collection<C> collection, Enumeration<? extends C> enumeration) {
         while (enumeration.hasMoreElements()) {
             collection.add(enumeration.nextElement());
         }
-    }    
-    
-    /** 
+    }
+
+    /**
      * Adds all elements in the array to the given collection.
      * 
-     * @param collection  the collection to add to, must not be null
-     * @param elements  the array of elements to add, must not be null
-     * @throws NullPointerException if the collection or array is null
+     * @param collection
+     *            the collection to add to, must not be null
+     * @param elements
+     *            the array of elements to add, must not be null
+     * @throws NullPointerException
+     *             if the collection or array is null
      */
-    public static void addAll(Collection collection, Object[] elements) {
+    public static <C, T extends C> void addAll(Collection<C> collection, T[] elements) {
         for (int i = 0, size = elements.length; i < size; i++) {
             collection.add(elements[i]);
         }
-    }    
+    }
+
+    /**
+     * Returns the <code>index</code>-th value in {@link Iterator}, throwing
+     * <code>IndexOutOfBoundsException</code> if there is no such element.
+     * The Iterator is advanced to 
+     *      <code>index</code> (or to the end, if <code>index</code> exceeds the 
+     *      number of entries) as a side effect of this method.</li>
+     * 
+     * @param iterator  the iterator to get a value from
+     * @param index  the index to get
+     * @param <T> the type of object in the {@link Iterator}
+     * @return the object at the specified index
+     * @throws IndexOutOfBoundsException if the index is invalid
+     * @throws IllegalArgumentException if the object type is invalid
+     */
+    public static <T> T get(Iterator<T> iterator, int index) {
+        checkIndexBounds(index);
+            while (iterator.hasNext()) {
+                index--;
+                if (index == -1) {
+                    return iterator.next();
+                }
+                iterator.next();
+            }
+            throw new IndexOutOfBoundsException("Entry does not exist: " + index);
+    }
 
     /**
+     * Ensures an index is not negative.
+     * @param index the index to check.
+     * @throws IndexOutOfBoundsException if the index is negative.
+     */
+    private static void checkIndexBounds(int index) {
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Index cannot be negative: " + index);
+        }
+    }
+    
+    /**
+     * Returns the <code>index</code>-th value in the <code>iterable</code>'s {@link Iterator}, throwing
+     * <code>IndexOutOfBoundsException</code> if there is no such element.
+     * <p>
+     * If the {@link Iterable} is a {@link List}, then it will use {@link List#get(int)}.
+     * 
+     * @param iterable  the {@link Iterable} to get a value from
+     * @param index  the index to get
+     * @param <T> the type of object in the {@link Iterable}.
+     * @return the object at the specified index
+     * @throws IndexOutOfBoundsException if the index is invalid
+     */
+    public static <T> T get(Iterable<T> iterable, int index) {
+        checkIndexBounds(index);
+        if (iterable instanceof List) {
+            return ((List<T>) iterable).get(index);
+        }
+        return get(iterable.iterator(), index);
+    }
+    
+    /**
      * Returns the <code>index</code>-th value in <code>object</code>, throwing
      * <code>IndexOutOfBoundsException</code> if there is no such element or 
      * <code>IllegalArgumentException</code> if <code>object</code> is not an 
@@ -756,8 +923,6 @@
             Map map = (Map) object;
             Iterator iterator = map.entrySet().iterator();
             return get(iterator, index);
-        } else if (object instanceof List) {
-            return ((List) object).get(index);
         } else if (object instanceof Object[]) {
             return ((Object[]) object)[index];
         } else if (object instanceof Iterator) {
@@ -795,6 +960,20 @@
             }
         }
     }
+
+    /**
+     * Returns the <code>index</code>-th <code>Map.Entry</code> in the <code>map</code>'s <code>entrySet</code>, throwing
+     * <code>IndexOutOfBoundsException</code> if there is no such element.
+     * 
+     * @param map  the object to get a value from
+     * @param index  the index to get
+     * @return the object at the specified index
+     * @throws IndexOutOfBoundsException if the index is invalid
+     */
+    public static <K,V> Map.Entry<K, V> get(Map<K,V> map, int index) {
+        checkIndexBounds(index);
+        return get(map.entrySet(), index);
+    }
     
     /** 
      * Gets the size of the collection/iterator specified.
@@ -844,7 +1023,7 @@
         }
         return total;
     }
-    
+
     /**
      * Checks if the specified collection/array/iterator is empty.
      * <p>
@@ -911,7 +1090,7 @@
      * @since Commons Collections 3.2
      */
     public static boolean isNotEmpty(Collection coll) {
-        return !CollectionUtils.isEmpty(coll);
+        return !isEmpty(coll);
     }
 
     //-----------------------------------------------------------------------
@@ -934,6 +1113,14 @@
         }
     }
 
+    private static final <T> int getFreq(final T obj, final Map<T, Integer> freqMap) {
+        Integer count = freqMap.get(obj);
+        if (count != null) {
+            return count.intValue();
+        }
+        return 0;
+    }
+
     /**
      * Returns true if no more elements can be added to the Collection.
      * <p>
@@ -959,7 +1146,7 @@
         try {
             BoundedCollection bcoll = UnmodifiableBoundedCollection.decorateUsing(coll);
             return bcoll.isFull();
-            
+
         } catch (IllegalArgumentException ex) {
             return false;
         }
@@ -990,7 +1177,7 @@
         try {
             BoundedCollection bcoll = UnmodifiableBoundedCollection.decorateUsing(coll);
             return bcoll.maxSize();
-            
+
         } catch (IllegalArgumentException ex) {
             return -1;
         }
@@ -1012,7 +1199,7 @@
      * @throws NullPointerException if either parameter is null
      * @since Commons Collections 3.2
      */
-    public static Collection retainAll(Collection collection, Collection retain) {
+    public static <C> Collection<C> retainAll(Collection<C> collection, Collection<?> retain) {
         return ListUtils.retainAll(collection, retain);
     }
 
@@ -1086,10 +1273,11 @@
      *
      * @param collection  the collection to predicate, must not be null
      * @param predicate  the predicate for the collection, must not be null
+     * @param <C> the type of objects in the Collection.
      * @return a predicated collection backed by the given collection
      * @throws IllegalArgumentException  if the Collection is null
      */
-    public static Collection predicatedCollection(Collection collection, Predicate predicate) {
+    public static <C> Collection<C> predicatedCollection(Collection<C> collection, Predicate<? super C> predicate) {
         return PredicatedCollection.decorate(collection, predicate);
     }
 

Added: commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/MockTestCase.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/MockTestCase.java?rev=593144&view=auto
==============================================================================
--- commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/MockTestCase.java (added)
+++ commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/MockTestCase.java Thu Nov  8 04:21:55 2007
@@ -0,0 +1,68 @@
+/*
+ * 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.collections;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.easymock.EasyMock;
+import org.easymock.IExpectationSetters;
+
+/**
+ * Provides utilities for making mock-based tests.  Most notable is the generic "type-safe"
+ * {@link #createMock(Class)} method, and {@link #replay()} and {@link #verify()} methods
+ * that call the respective methods on all created mock objects.
+ * 
+ * @author Stephen Kestle
+ */
+public abstract class MockTestCase {
+	private List<Object> mockObjects = new ArrayList<Object>();
+
+	@SuppressWarnings("unchecked")
+	protected <T> T createMock(Class name) {
+		T mock = (T) EasyMock.createMock(name);
+		return registerMock(mock);
+	}
+
+	private <T> T registerMock(T mock) {
+		mockObjects.add(mock);
+		return mock;
+	}
+
+	protected <T> IExpectationSetters<T> expect(T t) {
+		return EasyMock.expect(t);
+	}
+
+	protected final void replay() {
+		for (Iterator i = mockObjects.iterator(); i.hasNext();) {
+			EasyMock.replay(i.next());
+		}
+	}
+
+	protected final void verify() {
+		for (ListIterator i = mockObjects.listIterator(); i.hasNext();) {
+			try {
+				EasyMock.verify(i.next());
+			} catch (AssertionError e) {
+				throw new AssertionError((i.previousIndex() + 1) + ""
+						+ e.getMessage());
+			}
+		}
+	}
+}



Mime
View raw message