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