Clover coverage report - Drools - 2.0-rc2
Coverage timestamp: Wed May 11 2005 07:12:26 BST
file stats: LOC: 340   Methods: 16
NCLOC: 135   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
IteratorChain.java 0% 0% 0% 0%
coverage
 1    /*
 2    * Copyright 1999-2004 The Apache Software Foundation
 3    *
 4    * Licensed under the Apache License, Version 2.0 (the "License");
 5    * you may not use this file except in compliance with the License.
 6    * You may obtain a copy of the License at
 7    *
 8    * http://www.apache.org/licenses/LICENSE-2.0
 9    *
 10    * Unless required by applicable law or agreed to in writing, software
 11    * distributed under the License is distributed on an "AS IS" BASIS,
 12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13    * See the License for the specific language governing permissions and
 14    * limitations under the License.
 15    */
 16    package org.drools.util;
 17   
 18    import java.util.ArrayList;
 19    import java.util.Collection;
 20    import java.util.Collections;
 21    import java.util.Iterator;
 22    import java.util.List;
 23   
 24    /**
 25    * An IteratorChain is an Iterator that wraps a number of Iterators.
 26    * <p>
 27    * This class makes multiple iterators look like one to the caller When any
 28    * method from the Iterator interface is called, the IteratorChain will delegate
 29    * to a single underlying Iterator. The IteratorChain will invoke the Iterators
 30    * in sequence until all Iterators are exhausted.
 31    * <p>
 32    * Under many circumstances, linking Iterators together in this manner is more
 33    * efficient (and convenient) than reading out the contents of each Iterator
 34    * into a List and creating a new Iterator.
 35    * <p>
 36    * Calling a method that adds new Iterator <i>after a method in the Iterator
 37    * interface has been called </i> will result in an
 38    * UnsupportedOperationException. Subclasses should <i>take care </i> to not
 39    * alter the underlying List of Iterators.
 40    * <p>
 41    * NOTE: As from version 3.0, the IteratorChain may contain no iterators. In
 42    * this case the class will function as an empty iterator.
 43    *
 44    * @since Commons Collections 2.1
 45    * @version $Revision: 1.4 $ $Date: 2004/12/06 01:30:38 $
 46    *
 47    * @author Morgan Delagrange
 48    * @author Stephen Colebourne
 49    */
 50    public class IteratorChain
 51    implements
 52    Iterator
 53    {
 54   
 55    /** The chain of iterators */
 56    protected final List iteratorChain = new ArrayList( );
 57    /** The index of the current iterator */
 58    protected int currentIteratorIndex = 0;
 59    /** The current iterator */
 60    protected Iterator currentIterator = null;
 61    /**
 62    * The "last used" Iterator is the Iterator upon which next() or hasNext()
 63    * was most recently called used for the remove() operation only
 64    */
 65    protected Iterator lastUsedIterator = null;
 66    /**
 67    * ComparatorChain is "locked" after the first time compare(Object,Object)
 68    * is called
 69    */
 70    protected boolean isLocked = false;
 71   
 72    // -----------------------------------------------------------------------
 73    /**
 74    * Construct an IteratorChain with no Iterators.
 75    * <p>
 76    * You will normally use {@link #addIterator(Iterator)}to add some
 77    * iterators after using this constructor.
 78    */
 79  0 public IteratorChain()
 80    {
 81  0 super( );
 82    }
 83   
 84    /**
 85    * Construct an IteratorChain with a single Iterator.
 86    *
 87    * @param iterator
 88    * first Iterator in the IteratorChain
 89    * @throws NullPointerException
 90    * if the iterator is null
 91    */
 92  0 public IteratorChain(Iterator iterator)
 93    {
 94  0 super( );
 95  0 addIterator( iterator );
 96    }
 97   
 98    /**
 99    * Constructs a new <code>IteratorChain</code> over the two given
 100    * iterators.
 101    *
 102    * @param a
 103    * the first child iterator
 104    * @param b
 105    * the second child iterator
 106    * @throws NullPointerException
 107    * if either iterator is null
 108    */
 109  0 public IteratorChain(Iterator a,
 110    Iterator b)
 111    {
 112  0 super( );
 113  0 addIterator( a );
 114  0 addIterator( b );
 115    }
 116   
 117    /**
 118    * Constructs a new <code>IteratorChain</code> over the array of
 119    * iterators.
 120    *
 121    * @param iterators
 122    * the array of iterators
 123    * @throws NullPointerException
 124    * if iterators array is or contains null
 125    */
 126  0 public IteratorChain(Iterator[] iterators)
 127    {
 128  0 super( );
 129  0 for ( int i = 0; i < iterators.length; i++ )
 130    {
 131  0 addIterator( iterators[i] );
 132    }
 133    }
 134   
 135    /**
 136    * Constructs a new <code>IteratorChain</code> over the collection of
 137    * iterators.
 138    *
 139    * @param iterators
 140    * the collection of iterators
 141    * @throws NullPointerException
 142    * if iterators collection is or contains null
 143    * @throws ClassCastException
 144    * if iterators collection doesn't contain an iterator
 145    */
 146  0 public IteratorChain(Collection iterators)
 147    {
 148  0 super( );
 149  0 for ( Iterator it = iterators.iterator( ); it.hasNext( ); )
 150    {
 151  0 Iterator item = (Iterator) it.next( );
 152  0 addIterator( item );
 153    }
 154    }
 155   
 156    // -----------------------------------------------------------------------
 157    /**
 158    * Add an Iterator to the end of the chain
 159    *
 160    * @param iterator
 161    * Iterator to add
 162    * @throws IllegalStateException
 163    * if I've already started iterating
 164    * @throws NullPointerException
 165    * if the iterator is null
 166    */
 167  0 public void addIterator(Iterator iterator)
 168    {
 169  0 checkLocked( );
 170  0 if ( iterator == null )
 171    {
 172  0 throw new NullPointerException( "Iterator must not be null" );
 173    }
 174  0 iteratorChain.add( iterator );
 175    }
 176   
 177    /**
 178    * Set the Iterator at the given index
 179    *
 180    * @param index
 181    * index of the Iterator to replace
 182    * @param iterator
 183    * Iterator to place at the given index
 184    * @throws IndexOutOfBoundsException
 185    * if index &lt; 0 or index &gt; size()
 186    * @throws IllegalStateException
 187    * if I've already started iterating
 188    * @throws NullPointerException
 189    * if the iterator is null
 190    */
 191  0 public void setIterator(int index,
 192    Iterator iterator) throws IndexOutOfBoundsException
 193    {
 194  0 checkLocked( );
 195  0 if ( iterator == null )
 196    {
 197  0 throw new NullPointerException( "Iterator must not be null" );
 198    }
 199  0 iteratorChain.set( index,
 200    iterator );
 201    }
 202   
 203    /**
 204    * Get the list of Iterators (unmodifiable)
 205    *
 206    * @return the unmodifiable list of iterators added
 207    */
 208  0 public List getIterators()
 209    {
 210  0 return Collections.unmodifiableList( iteratorChain );
 211    }
 212   
 213    /**
 214    * Number of Iterators in the current IteratorChain.
 215    *
 216    * @return Iterator count
 217    */
 218  0 public int size()
 219    {
 220  0 return iteratorChain.size( );
 221    }
 222   
 223    /**
 224    * Determine if modifications can still be made to the IteratorChain.
 225    * IteratorChains cannot be modified once they have executed a method from
 226    * the Iterator interface.
 227    *
 228    * @return true if IteratorChain cannot be modified, false if it can
 229    */
 230  0 public boolean isLocked()
 231    {
 232  0 return isLocked;
 233    }
 234   
 235    /**
 236    * Checks whether the iterator chain is now locked and in use.
 237    */
 238  0 private void checkLocked()
 239    {
 240  0 if ( isLocked == true )
 241    {
 242  0 throw new UnsupportedOperationException( "IteratorChain cannot be changed after the first use of a method from the Iterator interface" );
 243    }
 244    }
 245   
 246    /**
 247    * Lock the chain so no more iterators can be added. This must be called
 248    * from all Iterator interface methods.
 249    */
 250  0 private void lockChain()
 251    {
 252  0 if ( isLocked == false )
 253    {
 254  0 isLocked = true;
 255    }
 256    }
 257   
 258    /**
 259    * Updates the current iterator field to ensure that the current Iterator is
 260    * not exhausted
 261    */
 262  0 protected void updateCurrentIterator()
 263    {
 264  0 if ( currentIterator == null )
 265    {
 266  0 if ( iteratorChain.isEmpty( ) )
 267    {
 268  0 currentIterator = Collections.EMPTY_LIST.iterator( );
 269    }
 270    else
 271    {
 272  0 currentIterator = (Iterator) iteratorChain.get( 0 );
 273    }
 274    // set last used iterator here, in case the user calls remove
 275    // before calling hasNext() or next() (although they shouldn't)
 276  0 lastUsedIterator = currentIterator;
 277    }
 278   
 279  0 while ( currentIterator.hasNext( ) == false && currentIteratorIndex < iteratorChain.size( ) - 1 )
 280    {
 281  0 currentIteratorIndex++;
 282  0 currentIterator = (Iterator) iteratorChain.get( currentIteratorIndex );
 283    }
 284    }
 285   
 286    // -----------------------------------------------------------------------
 287    /**
 288    * Return true if any Iterator in the IteratorChain has a remaining element.
 289    *
 290    * @return true if elements remain
 291    */
 292  0 public boolean hasNext()
 293    {
 294  0 lockChain( );
 295  0 updateCurrentIterator( );
 296  0 lastUsedIterator = currentIterator;
 297   
 298  0 return currentIterator.hasNext( );
 299    }
 300   
 301    /**
 302    * Returns the next Object of the current Iterator
 303    *
 304    * @return Object from the current Iterator
 305    * @throws java.util.NoSuchElementException
 306    * if all the Iterators are exhausted
 307    */
 308  0 public Object next()
 309    {
 310  0 lockChain( );
 311  0 updateCurrentIterator( );
 312  0 lastUsedIterator = currentIterator;
 313   
 314  0 return currentIterator.next( );
 315    }
 316   
 317    /**
 318    * Removes from the underlying collection the last element returned by the
 319    * Iterator. As with next() and hasNext(), this method calls remove() on the
 320    * underlying Iterator. Therefore, this method may throw an
 321    * UnsupportedOperationException if the underlying Iterator does not support
 322    * this method.
 323    *
 324    * @throws UnsupportedOperationException
 325    * if the remove operator is not supported by the underlying
 326    * Iterator
 327    * @throws IllegalStateException
 328    * if the next method has not yet been called, or the remove
 329    * method has already been called after the last call to the
 330    * next method.
 331    */
 332  0 public void remove()
 333    {
 334  0 lockChain( );
 335  0 updateCurrentIterator( );
 336   
 337  0 lastUsedIterator.remove( );
 338    }
 339   
 340    }