You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by br...@apache.org on 2011/05/25 20:04:29 UTC

svn commit: r1127604 - in /commons/proper/collections/trunk/src: java/org/apache/commons/collections/ java/org/apache/commons/collections/iterators/ test/org/apache/commons/collections/ test/org/apache/commons/collections/iterators/

Author: brentworden
Date: Wed May 25 18:04:29 2011
New Revision: 1127604

URL: http://svn.apache.org/viewvc?rev=1127604&view=rev
Log:
COLLECTIONS-213.  Added multiple use support to IteratorIterable.

Modified:
    commons/proper/collections/trunk/src/java/org/apache/commons/collections/IteratorUtils.java
    commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/IteratorIterable.java
    commons/proper/collections/trunk/src/test/org/apache/commons/collections/TestIteratorUtils.java
    commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestIteratorIterable.java

Modified: commons/proper/collections/trunk/src/java/org/apache/commons/collections/IteratorUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/java/org/apache/commons/collections/IteratorUtils.java?rev=1127604&r1=1127603&r2=1127604&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/java/org/apache/commons/collections/IteratorUtils.java (original)
+++ commons/proper/collections/trunk/src/java/org/apache/commons/collections/IteratorUtils.java Wed May 25 18:04:29 2011
@@ -759,7 +759,8 @@ public class IteratorUtils {
     }
 
     /**
-     * Gets an iterable that wraps an iterator.
+     * Gets an iterable that wraps an iterator.  The returned iterable can be
+     * used for a single iteration.
      *
      * @param iterator  the iterator to use, not null
      * @return a new, single use iterable
@@ -769,7 +770,22 @@ public class IteratorUtils {
         if (iterator == null) {
             throw new NullPointerException("Iterator must not be null");
         }
-        return new IteratorIterable<E>(iterator);
+        return new IteratorIterable<E>(iterator, false);
+    }
+
+    /**
+     * Gets an iterable that wraps an iterator.  The returned iterable can be
+     * used for multiple iterations.
+     *
+     * @param iterator  the iterator to use, not null
+     * @return a new, multiple use iterable
+     * @throws NullPointerException if iterator is null
+     */
+    public static <E> Iterable<E> asMultipleUseIterable(Iterator<? extends E> iterator) {
+        if (iterator == null) {
+            throw new NullPointerException("Iterator must not be null");
+        }
+        return new IteratorIterable<E>(iterator, true);
     }
 
     /**

Modified: commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/IteratorIterable.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/IteratorIterable.java?rev=1127604&r1=1127603&r2=1127604&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/IteratorIterable.java (original)
+++ commons/proper/collections/trunk/src/java/org/apache/commons/collections/iterators/IteratorIterable.java Wed May 25 18:04:29 2011
@@ -15,11 +15,47 @@ package org.apache.commons.collections.i
 
 import java.util.Iterator;
 
+import org.apache.commons.collections.ResettableIterator;
+
 /**
  * Adapter to make an {@link Iterator Iterator} instance appear to be an
- * {@link Iterable Iterable} instance. Unlike normal iterable instance, the
- * {@link #iterator()} method always returns the same iterator instance. This
- * prohibits this iterator to be only usable for one iterative operation.
+ * {@link Iterable Iterable} instance.  The iterable can be constructed in one
+ * of two variants:  single use, multiple use.
+ * 
+ * <p>
+ * In the single use iterable case, the iterable is only usable for one
+ * iterative operation over the source iterator.  Subsequent iterative
+ * operations use the same, exhausted source iterator.  To create a single use
+ * iterable, construct a new {@link IteratorIterable} using a {@link Iterator}
+ * that is NOT a {@link ResettableIterator} iterator:
+ * <pre>
+ *   Iterator<Integer> iterator = // some non-resettable iterator
+ *   Iterable<Integer> iterable = new IteratorIterable<Integer>(iterator);
+ * </pre>
+ * </p>
+ * 
+ * <p>
+ * In the multiple use iterable case, the iterable is usable for any number of
+ * iterative operations over the source iterator.  Of special note, even though
+ * the iterable supports multiple iterations, it does not support concurrent
+ * iterations. To implicitly create a multiple use iterable, construct a new
+ * {@link IteratorIterable} using a {@link ResettableIterator} iterator:
+ * <pre>
+ *   Integer[] array = {Integer.valueOf(1),Integer.valueOf(2),Integer.valueOf(3)};
+ *   Iterator<Integer> iterator = IteratorUtils.arrayIterator(array); // a resettable iterator
+ *   Iterable<Integer> iterable = new IteratorIterable<Integer>(iterator);
+ * </pre>
+ * </p>
+ * 
+ * <p>
+ * A multiple use iterable can also be explicitly constructed using any
+ * {@link Iterator} and specifying <code>true</code> for the
+ * <code>multipleUse</code> flag:
+ * <pre>
+ *   Iterator<Integer> iterator = // some non-resettable iterator
+ *   Iterable<Integer> iterable = new IteratorIterable<Integer>(iterator, true);
+ * </pre>
+ * </p>
  * 
  * @since Commons Collections 4.0
  * @version $Revision: $ $Date: $
@@ -47,9 +83,12 @@ public class IteratorIterable<E> impleme
         };
     }
 
-    /** the iterator being used. */
-    private final Iterator<E> iterator;
-
+    /** the iterator being adapted into an iterable. */
+    private final Iterator<? extends E> iterator;
+    
+    /** the iterator parameterized as the {@link #iterator()} return type. */ 
+    private final Iterator<E> typeSafeIterator;
+    
     /**
      * Constructs a new <code>IteratorIterable</code> that will use the given
      * iterator.
@@ -57,8 +96,24 @@ public class IteratorIterable<E> impleme
      * @param iterator the iterator to use.
      */
     public IteratorIterable(Iterator<? extends E> iterator) {
+        this(iterator, false);
+    }
+
+    /**
+     * Constructs a new <code>IteratorIterable</code> that will use the given
+     * iterator.
+     * 
+     * @param iterator the iterator to use.
+     * @param multipleUse <code>true</code> if the new iterable can be used in multiple iterations
+     */
+    public IteratorIterable(Iterator<? extends E> iterator, boolean multipleUse) {
         super();
-        this.iterator = createTypesafeIterator(iterator);
+        if (multipleUse && !(iterator instanceof ResettableIterator)) {
+            this.iterator = new ListIteratorWrapper<E>(iterator); 
+        } else {
+            this.iterator = iterator;
+        }
+        this.typeSafeIterator = createTypesafeIterator(this.iterator);
     }
 
     /**
@@ -67,6 +122,9 @@ public class IteratorIterable<E> impleme
      * @return the iterator
      */
     public Iterator<E> iterator() {
-        return iterator;
+        if (iterator instanceof ResettableIterator) {
+            ((ResettableIterator<? extends E>)iterator).reset();
+        }
+        return typeSafeIterator;
     }
 }

Modified: commons/proper/collections/trunk/src/test/org/apache/commons/collections/TestIteratorUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/org/apache/commons/collections/TestIteratorUtils.java?rev=1127604&r1=1127603&r2=1127604&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/test/org/apache/commons/collections/TestIteratorUtils.java (original)
+++ commons/proper/collections/trunk/src/test/org/apache/commons/collections/TestIteratorUtils.java Wed May 25 18:04:29 2011
@@ -61,6 +61,8 @@ public class TestIteratorUtils extends B
             assertEquals(expected, actual.intValue());
             ++expected;
         }
+        // insure iteration occurred
+        assertTrue(expected > 0);
 
         // single use iterator
         for(Integer actual : iterable) {
@@ -76,6 +78,41 @@ public class TestIteratorUtils extends B
             // success
         }
     }
+
+    public void testAsMultipleIterable() {
+        List<Integer> list = new ArrayList<Integer>();
+        list.add(Integer.valueOf(0));
+        list.add(Integer.valueOf(1));
+        list.add(Integer.valueOf(2));
+        Iterator<Integer> iterator = list.iterator();
+        
+        Iterable<Integer> iterable = IteratorUtils.asMultipleUseIterable(iterator);
+        int expected = 0;
+        for(Integer actual : iterable) {
+            assertEquals(expected, actual.intValue());
+            ++expected;
+        }
+        // insure iteration occurred
+        assertTrue(expected > 0);
+
+        // multiple use iterator
+        expected = 0;
+        for(Integer actual : iterable) {
+            assertEquals(expected, actual.intValue());
+            ++expected;
+        }
+        // insure iteration occurred
+        assertTrue(expected > 0);
+    }
+
+    public void testAsMultipleIterableNull() {
+        try {
+            IteratorUtils.asMultipleUseIterable(null);
+            fail("Expecting NullPointerException");
+        } catch (NullPointerException ex) {
+            // success
+        }
+    }
     
     public void testToList() {
         List<Object> list = new ArrayList<Object>();

Modified: commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestIteratorIterable.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestIteratorIterable.java?rev=1127604&r1=1127603&r2=1127604&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestIteratorIterable.java (original)
+++ commons/proper/collections/trunk/src/test/org/apache/commons/collections/iterators/TestIteratorIterable.java Wed May 25 18:04:29 2011
@@ -36,19 +36,47 @@ public class TestIteratorIterable extend
         super(name);
     }
 
-    public void testIterator() {
+    private Iterator<Integer> createIterator() {
         List<Integer> list = new ArrayList<Integer>();
         list.add(Integer.valueOf(0));
         list.add(Integer.valueOf(1));
         list.add(Integer.valueOf(2));
         Iterator<Integer> iter = list.iterator();
+        return iter;
+    }
 
+    public void testIterator() {
+        Iterator<Integer> iter = createIterator();
         Iterable<Number> iterable = new IteratorIterable<Number>(iter);
+        
+        // first use
+        verifyIteration(iterable);
+        
+        // second use
+        for (Number actual : iterable) {
+            fail("should not be able to iterate twice");
+        }
+    }
+
+    public void testMultipleUserIterator() {
+        Iterator<Integer> iter = createIterator();
+
+        Iterable<Number> iterable = new IteratorIterable<Number>(iter, true);
+        
+        // first use
+        verifyIteration(iterable);
+        
+        // second use
+        verifyIteration(iterable);
+    }
+
+    private void verifyIteration(Iterable<Number> iterable) {
         int expected = 0;
         for (Number actual : iterable) {
             assertEquals(expected, actual.intValue());
             ++expected;
         }
+        assertTrue(expected > 0);
     }
 }