You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sc...@apache.org on 2003/12/29 17:07:53 UTC

cvs commit: jakarta-commons/collections/src/java/org/apache/commons/collections/iterators IteratorChain.java

scolebourne    2003/12/29 08:07:53

  Modified:    collections/src/test/org/apache/commons/collections/iterators
                        TestIteratorChain.java
               collections/src/java/org/apache/commons/collections/iterators
                        IteratorChain.java
  Log:
  Enable zero iterators in the chain to function
  
  Revision  Changes    Path
  1.7       +16 -3     jakarta-commons/collections/src/test/org/apache/commons/collections/iterators/TestIteratorChain.java
  
  Index: TestIteratorChain.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/iterators/TestIteratorChain.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- TestIteratorChain.java	1 Oct 2003 21:54:55 -0000	1.6
  +++ TestIteratorChain.java	29 Dec 2003 16:07:53 -0000	1.7
  @@ -180,5 +180,18 @@
           assertEquals("C",chain.next());
           assertTrue("should not have next",!chain.hasNext());
       }
  +    
  +    public void testEmptyChain() {
  +        IteratorChain chain = new IteratorChain();
  +        assertEquals(false, chain.hasNext());
  +        try {
  +            chain.next();
  +            fail();
  +        } catch (NoSuchElementException ex) {}
  +        try {
  +            chain.remove();
  +            fail();
  +        } catch (IllegalStateException ex) {}
  +    }
  +        
   }
  -
  
  
  
  1.8       +70 -85    jakarta-commons/collections/src/java/org/apache/commons/collections/iterators/IteratorChain.java
  
  Index: IteratorChain.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/iterators/IteratorChain.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- IteratorChain.java	3 Dec 2003 11:37:44 -0000	1.7
  +++ IteratorChain.java	29 Dec 2003 16:07:53 -0000	1.8
  @@ -61,28 +61,28 @@
   import java.util.Collection;
   import java.util.Iterator;
   import java.util.List;
  -import java.util.NoSuchElementException;
   
  +import org.apache.commons.collections.IteratorUtils;
   import org.apache.commons.collections.list.UnmodifiableList;
   
   /**
  - * <p>An IteratorChain is an Iterator that wraps one or
  - * more Iterators.  When any method from the
  - * Iterator interface is called, the IteratorChain will
  - * proxy to a single underlying Iterator.  The 
  - * IteratorChain will invoke the Iterators in sequence until 
  - * all Iterators are exhausted completely.</p>
  - * 
  - * <p>Under many circumstances, linking Iterators together
  - * in this manner is more efficient (and convenient)
  - * than reading out the contents of each Iterator into a
  - * List and creating a new Iterator.</p>
  - * 
  - * <p>Calling a method that adds new Iterator<i>after
  - * a method in the Iterator interface
  - * has been called</i> will result in an
  - * UnsupportedOperationException.  Subclasses should <i>take care</i>
  - * to not alter the underlying List of Iterators.</p>
  + * An IteratorChain is an Iterator that wraps a number of Iterators.
  + * <p>
  + * This class makes mutiple iterators look like one to the caller
  + * When any method from the Iterator interface is called, the IteratorChain
  + * will delegate to a single underlying Iterator. The IteratorChain will
  + * invoke the Iterators in sequence until all Iterators are exhausted.
  + * <p>
  + * Under many circumstances, linking Iterators together in this manner is
  + * more efficient (and convenient) than reading out the contents of each
  + * Iterator into a List and creating a new Iterator.
  + * <p>
  + * Calling a method that adds new Iterator<i>after a method in the Iterator
  + * interface has been called</i> will result in an UnsupportedOperationException.
  + * Subclasses should <i>take care</i> to not alter the underlying List of Iterators.
  + * <p>
  + * NOTE: As from version 3.0, the IteratorChain may contain no
  + * iterators. In this case the class will function as an empty iterator.
    * 
    * @since Commons Collections 2.1
    * @version $Revision$ $Date$
  @@ -92,26 +92,30 @@
    */
   public class IteratorChain implements Iterator {
   
  +	/** The chain of iterators */
       protected final List iteratorChain = new ArrayList();
  +    /** The index of the current iterator */
       protected int currentIteratorIndex = 0;
  +    /** The current iterator */
       protected Iterator currentIterator = null;
  -    // the "last used" Iterator is the Iterator upon which
  -    // next() or hasNext() was most recently called
  -    // used for the remove() operation only
  +    /**
  +     * The "last used" Iterator is the Iterator upon which
  +     * next() or hasNext() was most recently called
  +     * used for the remove() operation only
  +     */
       protected Iterator lastUsedIterator = null;
  -
  -    // ComparatorChain is "locked" after the first time
  -    // compare(Object,Object) is called
  +    /**
  +     * ComparatorChain is "locked" after the first time
  +     * compare(Object,Object) is called
  +     */
       protected boolean isLocked = false;
   
  -    // Constructors
  -    // -------------------------------------------------------------------
  -    
  +    //-----------------------------------------------------------------------
       /**
        * Construct an IteratorChain with no Iterators.
  -     * You must add at least Iterator before calling
  -     * any method from the Iterator interface, or an 
  -     * UnsupportedOperationException is thrown
  +     * <p>
  +     * You will normally use {@link #addIterator(Iterator)} to add
  +     * some iterators after using this constructor.
        */
       public IteratorChain() {
           super();
  @@ -172,9 +176,7 @@
           }
       }
       
  -    // Public Methods
  -    // -------------------------------------------------------------------
  -
  +    //-----------------------------------------------------------------------
       /**
        * Add an Iterator to the end of the chain 
        * 
  @@ -226,74 +228,64 @@
       }
   
       /**
  -     * Determine if modifications can still be made to the
  -     * IteratorChain.  IteratorChains cannot be modified
  -     * once they have executed a method from the Iterator
  -     * interface.
  +     * Determine if modifications can still be made to the IteratorChain.
  +     * IteratorChains cannot be modified once they have executed a method
  +     * from the Iterator interface.
        * 
  -     * @return true = IteratorChain cannot be modified; false = 
  -     *         IteratorChain can still be modified.
  +     * @return true if IteratorChain cannot be modified, false if it can 
        */
       public boolean isLocked() {
           return isLocked;
       }
   
  -    // throw an exception if the IteratorChain is locked
  +    /**
  +     * Checks whether the iterator chain is now locked and in use.
  +     */
       private void checkLocked() {
           if (isLocked == true) {
               throw new UnsupportedOperationException("IteratorChain cannot be changed after the first use of a method from the Iterator interface");
           }
       }
   
  -    private void checkChainIntegrity() {
  -        if (iteratorChain.size() == 0) {
  -            throw new UnsupportedOperationException("IteratorChains must contain at least one Iterator");
  -        }
  -    }
  -
  -    // you MUST call this method whenever you call a method in the Iterator interface, because
  -    // this method also assigns the initial value of the currentIterator variable
  +    /**
  +     * Lock the chain so no more iterators can be added.
  +     * This must be called from all Iterator interface methods.
  +     */
       private void lockChain() {
           if (isLocked == false) {
  -            checkChainIntegrity();
               isLocked = true;
           }
       }
   
  -    // call this before any Iterator method to make sure that the current Iterator
  -    // is not exhausted
  +    /**
  +     * Updates the current iterator field to ensure that the current Iterator
  +     * is not exhausted
  +     */
       protected void updateCurrentIterator() {
           if (currentIterator == null) {
  -            currentIterator = (Iterator) iteratorChain.get(0);
  +            if (iteratorChain.isEmpty()) {
  +                currentIterator = IteratorUtils.EMPTY_ITERATOR;
  +            } else {
  +                currentIterator = (Iterator) iteratorChain.get(0);
  +            }
               // set last used iterator here, in case the user calls remove
               // before calling hasNext() or next() (although they shouldn't)
               lastUsedIterator = currentIterator;
           }
   
  -        if (currentIteratorIndex == (iteratorChain.size() - 1)) {
  -            return;
  -        }
  -
  -        while (currentIterator.hasNext() == false) {
  -            ++currentIteratorIndex;
  +        while (currentIterator.hasNext() == false && currentIteratorIndex < iteratorChain.size() - 1) {
  +            currentIteratorIndex++;
               currentIterator = (Iterator) iteratorChain.get(currentIteratorIndex);
  -
  -            if (currentIteratorIndex == (iteratorChain.size() - 1)) {
  -                return;
  -            }
           }
       }
   
  +    //-----------------------------------------------------------------------
       /**
  -     * Return true if any Iterator in the IteratorChain has a remaining
  -     * element.
  +     * Return true if any Iterator in the IteratorChain has a remaining element.
        * 
        * @return true if elements remain
  -     * @exception UnsupportedOperationException
  -     *                   if the IteratorChain does not contain at least one
  -     *                   Iterator
        */
  -    public boolean hasNext() throws UnsupportedOperationException {
  +    public boolean hasNext() {
           lockChain();
           updateCurrentIterator();
           lastUsedIterator = currentIterator;
  @@ -305,13 +297,9 @@
        * Returns the next Object of the current Iterator
        * 
        * @return Object from the current Iterator
  -     * @exception NoSuchElementException
  -     *                   if all the Iterators are exhausted
  -     * @exception UnsupportedOperationException
  -     *                   if the IteratorChain does not contain at least one
  -     *                   Iterator
  +     * @throws NoSuchElementException if all the Iterators are exhausted
        */
  -    public Object next() throws NoSuchElementException, UnsupportedOperationException {
  +    public Object next() {
           lockChain();
           updateCurrentIterator();
           lastUsedIterator = currentIterator;
  @@ -327,20 +315,17 @@
        * UnsupportedOperationException if the underlying
        * Iterator does not support this method. 
        * 
  -     * @exception UnsupportedOperationException
  -     *                   if the remove operator is not supported by the underlying
  -     *                   Iterator or if there are no Iterators in the IteratorChain
  -     * @exception IllegalStateException
  -     *                   if the next method has not yet been called, or the
  -     *                   remove method has already been called after the last
  -     *                   call to the next method.
  +     * @throws UnsupportedOperationException
  +     *   if the remove operator is not supported by the underlying Iterator
  +     * @throws IllegalStateException
  +     *   if the next method has not yet been called, or the remove method has
  +     *   already been called after the last call to the next method.
        */
  -    public void remove() throws UnsupportedOperationException, IllegalStateException  {
  +    public void remove() {
           lockChain();
           updateCurrentIterator();
   
           lastUsedIterator.remove();
       }
  -
   
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org