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