001    /*
002     * Copyright (c) 2007-2015 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 TupleEntryChainIterator extends TupleEntryIterator
033      {
034      /** Field iterator */
035      Iterator<Tuple>[] iterators;
036      int currentIterator = 0;
037    
038      public TupleEntryChainIterator( Fields fields, Iterator<Tuple>... iterators )
039        {
040        super( fields );
041        this.iterators = iterators;
042        }
043    
044      /**
045       * Method hasNext returns true if there is a next TupleEntry
046       *
047       * @return boolean
048       */
049      public boolean hasNext()
050        {
051        if( iterators.length < currentIterator + 1 ) // past the end
052          return false;
053    
054        if( iterators[ currentIterator ].hasNext() )
055          return true;
056    
057        closeCurrent();
058    
059        currentIterator++;
060    
061        return iterators.length != currentIterator && hasNext();
062        }
063    
064      public void reset( Iterator<Tuple>... iterators )
065        {
066        this.currentIterator = 0;
067        this.iterators = iterators;
068        }
069    
070      /**
071       * Method next returns the next TupleEntry.
072       *
073       * @return TupleEntry
074       */
075      public TupleEntry next()
076        {
077        hasNext(); // force roll to next iterator
078    
079        entry.setTuple( iterators[ currentIterator ].next() );
080    
081        return entry;
082        }
083    
084      /** Method remove removes the current TupleEntry from the underlying collection. */
085      public void remove()
086        {
087        iterators[ currentIterator ].remove();
088        }
089    
090      /** Method close closes all underlying resources. */
091      public void close()
092        {
093        if( iterators.length != currentIterator )
094          closeCurrent();
095        }
096    
097      protected void closeCurrent()
098        {
099        close( iterators[ currentIterator ] );
100        }
101    
102      private void close( Iterator iterator )
103        {
104        if( iterator instanceof Closeable )
105          {
106          try
107            {
108            ( (Closeable) iterator ).close();
109            }
110          catch( IOException exception )
111            {
112            // ignore
113            }
114          }
115        }
116      }