001    /*
002     * Copyright (c) 2007-2014 Concurrent, Inc. All Rights Reserved.
003     *
004     * Project and contact information: http://www.cascading.org/
005     *
006     * This file is part of the Cascading project.
007     *
008     * Licensed under the Apache License, Version 2.0 (the "License");
009     * you may not use this file except in compliance with the License.
010     * You may obtain a copy of the License at
011     *
012     *     http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing, software
015     * distributed under the License is distributed on an "AS IS" BASIS,
016     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017     * See the License for the specific language governing permissions and
018     * limitations under the License.
019     */
020    
021    package cascading.tuple;
022    
023    import java.io.Closeable;
024    import java.io.IOException;
025    import java.util.Iterator;
026    
027    /**
028     * TupleEntryChainIterator chains the given Iterators into a single Iterator.
029     * <p/>
030     * As one iterator is completed, it will be closed and a new one will start.
031     */
032    public class TupleEntryIterableChainIterator extends TupleEntryIterator
033      {
034      Iterator<Iterator<Tuple>> iterators;
035      Iterator<Tuple> currentIterator = null;
036    
037      public TupleEntryIterableChainIterator( Fields fields )
038        {
039        super( fields );
040        }
041    
042      public TupleEntryIterableChainIterator( Fields fields, Iterable<Iterator<Tuple>> iterable )
043        {
044        super( fields );
045        this.iterators = iterable.iterator();
046        }
047    
048      /**
049       * Method hasNext returns true if there is a next TupleEntry
050       *
051       * @return boolean
052       */
053      public boolean hasNext()
054        {
055        if( currentIterator == null && !iterators.hasNext() )
056          return false;
057    
058        if( currentIterator != null && currentIterator.hasNext() )
059          return true;
060    
061        closeCurrent();
062    
063        currentIterator = null;
064    
065        if( iterators.hasNext() )
066          currentIterator = iterators.next();
067    
068        return hasNext();
069        }
070    
071      public void reset( Iterable<Iterator<Tuple>> iterable )
072        {
073        this.currentIterator = null;
074        this.iterators = iterable.iterator();
075        }
076    
077      /**
078       * Method next returns the next TupleEntry.
079       *
080       * @return TupleEntry
081       */
082      public TupleEntry next()
083        {
084        hasNext(); // force roll to next iterator
085    
086        entry.setTuple( currentIterator.next() );
087    
088        return entry;
089        }
090    
091      /** Method remove removes the current TupleEntry from the underlying collection. */
092      public void remove()
093        {
094        currentIterator.remove();
095        }
096    
097      /** Method close closes all underlying resources. */
098      public void close()
099        {
100        if( currentIterator != null )
101          closeCurrent();
102        }
103    
104      protected void closeCurrent()
105        {
106        close( currentIterator );
107        }
108    
109      private void close( Iterator iterator )
110        {
111        if( iterator instanceof Closeable )
112          {
113          try
114            {
115            ( (Closeable) iterator ).close();
116            }
117          catch( IOException exception )
118            {
119            // ignore
120            }
121          }
122        }
123      }