All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.protempa.backend.dsb.file.CloseableIteratorChain Maven / Gradle / Ivy

The newest version!
package org.protempa.backend.dsb.file;

/*
 * #%L
 * Protempa File Data Source Backend
 * %%
 * Copyright (C) 2012 - 2015 Emory University
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import org.protempa.DataSourceReadException;
import org.protempa.DataStreamingEvent;
import org.protempa.DataStreamingEventIterator;

/**
 *
 * @author Andrew Post
 */
class CloseableIteratorChain implements DataStreamingEventIterator {
    /** The chain of iterators */
    private final Queue> iteratorChain = new LinkedList>();

    /** The current iterator */
    private DataStreamingEventIterator currentIterator = null;

    /**
     * The "last used" Iterator is the Iterator upon which next() or hasNext()
     * was most recently called used for the remove() operation only
     */
    private DataStreamingEventIterator lastUsedIterator = null;

    /**
     * ComparatorChain is "locked" after the first time compare(Object,Object)
     * is called
     */
    private boolean isLocked = false;

    //-----------------------------------------------------------------------
    /**
     * Construct an IteratorChain with no Iterators.
     * 

* You will normally use {@link #addIterator(Iterator)} to add some * iterators after using this constructor. */ CloseableIteratorChain() { super(); } /** * Construct an IteratorChain with a single Iterator. *

* This method takes one iterator. The newly constructed iterator will * iterate through that iterator. Thus calling this constructor on its own * will have no effect other than decorating the input iterator. *

* You will normally use {@link #addIterator(Iterator)} to add some more * iterators after using this constructor. * * @param iterator the first child iterator in the IteratorChain, not null * @throws NullPointerException if the iterator is null */ CloseableIteratorChain(final DataStreamingEventIterator iterator) { super(); addIterator(iterator); } /** * Constructs a new IteratorChain over the two given iterators. *

* This method takes two iterators. The newly constructed iterator will * iterate through each one of the input iterators in turn. * * @param first the first child iterator in the IteratorChain, not null * @param second the second child iterator in the IteratorChain, not null * @throws NullPointerException if either iterator is null */ CloseableIteratorChain(final DataStreamingEventIterator first, final DataStreamingEventIterator second) { super(); addIterator(first); addIterator(second); } /** * Constructs a new IteratorChain over the array of iterators. *

* This method takes an array of iterators. The newly constructed iterator * will iterate through each one of the input iterators in turn. * * @param iteratorChain the array of iterators, not null * @throws NullPointerException if iterators array is or contains null */ CloseableIteratorChain(final DataStreamingEventIterator... iteratorChain) { super(); for (final DataStreamingEventIterator element : iteratorChain) { addIterator(element); } } /** * Constructs a new IteratorChain over the collection of * iterators. *

* This method takes a collection of iterators. The newly constructed * iterator will iterate through each one of the input iterators in turn. * * @param iteratorChain the collection of iterators, not null * @throws NullPointerException if iterators collection is or contains null * @throws ClassCastException if iterators collection doesn't contain an * iterator */ CloseableIteratorChain(final Collection> iteratorChain) { super(); for (final DataStreamingEventIterator iterator : iteratorChain) { addIterator(iterator); } } //----------------------------------------------------------------------- /** * Add an Iterator to the end of the chain * * @param iterator Iterator to add * @throws IllegalStateException if I've already started iterating * @throws NullPointerException if the iterator is null */ void addIterator(final DataStreamingEventIterator iterator) { checkLocked(); if (iterator == null) { throw new NullPointerException("Iterator must not be null"); } iteratorChain.add(iterator); } /** * Returns the remaining number of Iterators in the current IteratorChain. * * @return Iterator count */ int size() { return iteratorChain.size(); } /** * Determine if modifications can still be made to the IteratorChain. * IteratorChains cannot be modified once they have executed a method from * the Iterator interface. * * @return true if IteratorChain cannot be modified, false if it can */ boolean isLocked() { return isLocked; } /** * Checks whether the iterator chain is now locked and in use. */ private void checkLocked() { if (isLocked == true) { throw new UnsupportedOperationException( "IteratorChain cannot be changed after the first use of a method from the Iterator interface"); } } /** * Lock the chain so no more iterators can be added. This must be called * from all Iterator interface methods. */ private void lockChain() { if (isLocked == false) { isLocked = true; } } /** * Updates the current iterator field to ensure that the current Iterator is * not exhausted */ protected void updateCurrentIterator() throws DataSourceReadException { if (currentIterator == null) { if (iteratorChain.isEmpty()) { currentIterator = new EmptyDataStreamingEventIterator(); } else { currentIterator = iteratorChain.remove(); } // set last used iterator here, in case the user calls remove // before calling hasNext() or next() (although they shouldn't) lastUsedIterator = currentIterator; } while (currentIterator.hasNext() == false && !iteratorChain.isEmpty()) { currentIterator.close(); currentIterator = iteratorChain.remove(); } } //----------------------------------------------------------------------- /** * Return true if any Iterator in the IteratorChain has a remaining element. * * @return true if elements remain */ @Override public boolean hasNext() throws DataSourceReadException { lockChain(); updateCurrentIterator(); lastUsedIterator = currentIterator; return currentIterator.hasNext(); } /** * Returns the next Object of the current Iterator * * @return Object from the current Iterator * @throws java.util.NoSuchElementException if all the Iterators are * exhausted */ @Override public DataStreamingEvent next() throws DataSourceReadException { lockChain(); updateCurrentIterator(); lastUsedIterator = currentIterator; return currentIterator.next(); } @Override public void close() throws DataSourceReadException { for (Iterator> itr = this.iteratorChain.iterator(); itr.hasNext();) { DataStreamingEventIterator next = itr.next(); next.close(); itr.remove(); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy