    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements. See the NOTICE file distributed with this
    004 * work for additional information regarding copyright ownership. The ASF
    005 * licenses this file to You under the Apache License, Version 2.0 (the
    006 * "License"); you may not use this file except in compliance with the License.
    007 * You may obtain a copy of the License at
    008 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
    009 * or agreed to in writing, software distributed under the License is
    010 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    011 * KIND, either express or implied. See the License for the specific language
    012 * governing permissions and limitations under the License.
    013 */
    014package org.apache.commons.collections4.iterators;
    015
    016import java.util.Iterator;
    017
    018import org.apache.commons.collections4.ResettableIterator;
    019
    020/**
    021 * Adapter to make an {@link Iterator Iterator} instance appear to be an
    022 * {@link Iterable Iterable} instance.  The iterable can be constructed in one
    023 * of two variants:  single use, multiple use.
    024 *
    025 * <p>
    026 * In the single use iterable case, the iterable is only usable for one
    027 * iterative operation over the source iterator.  Subsequent iterative
    028 * operations use the same, exhausted source iterator.  To create a single use
    029 * iterable, construct a new {@link IteratorIterable} using a {@link Iterator}
    030 * that is NOT a {@link ResettableIterator} iterator:
    031 * </p>
    032 *
    033 * <pre>
    034 *   Iterator&lt;Integer&gt; iterator = // some non-resettable iterator
    035 *   Iterable&lt;Integer&gt; iterable = new IteratorIterable&lt;Integer&gt;(iterator);
    036 * </pre>
    037 *
    038 * <p>
    039 * In the multiple use iterable case, the iterable is usable for any number of
    040 * iterative operations over the source iterator.  Of special note, even though
    041 * the iterable supports multiple iterations, it does not support concurrent
    042 * iterations. To implicitly create a multiple use iterable, construct a new
    043 * {@link IteratorIterable} using a {@link ResettableIterator} iterator:
    044 * </p>
    045 *
    046 * <pre>
    047 *   Integer[] array = {Integer.valueOf(1),Integer.valueOf(2),Integer.valueOf(3)};
    048 *   Iterator&lt;Integer&gt; iterator = IteratorUtils.arrayIterator(array); // a resettable iterator
    049 *   Iterable&lt;Integer&gt; iterable = new IteratorIterable&lt;Integer&gt;(iterator);
    050 * </pre>
    051 *
    052 * <p>
    053 * A multiple use iterable can also be explicitly constructed using any
    054 * {@link Iterator} and specifying <code>true</code> for the
    055 * <code>multipleUse</code> flag:
    056 * </p>
    057 *
    058 * <pre>
    059 *   Iterator&lt;Integer&gt; iterator = // some non-resettable iterator
    060 *   Iterable&lt;Integer&gt; iterable = new IteratorIterable&lt;Integer&gt;(iterator, true);
    061 * </pre>
    062 *
    063 * @since 4.0
    064 */
    065public class IteratorIterable<E> implements Iterable<E> {
    066
    067    /**
    068     * Factory method to create an {@link Iterator Iterator} from another
    069     * iterator over objects of a different subtype.
    070     */
    071    private static <E> Iterator<E> createTypesafeIterator(final Iterator<? extends E> iterator) {
    072        return new Iterator<E>() {
    073            @Override
    074            public boolean hasNext() {
    075                return iterator.hasNext();
    076            }
    077
    078            @Override
    079            public E next() {
    080                return iterator.next();
    081            }
    082
    083            @Override
    084            public void remove() {
    085                iterator.remove();
    086            }
    087        };
    088    }
    089
    090    /** the iterator being adapted into an iterable. */
    091    private final Iterator<? extends E> iterator;
    092
    093    /** the iterator parameterized as the {@link #iterator()} return type. */
    094    private final Iterator<E> typeSafeIterator;
    095
    096    /**
    097     * Constructs a new <code>IteratorIterable</code> that will use the given
    098     * iterator.
    099     *
    100     * @param iterator the iterator to use.
    101     */
    102    public IteratorIterable(final Iterator<? extends E> iterator) {
    103        this(iterator, false);
    104    }
    105
    106    /**
    107     * Constructs a new <code>IteratorIterable</code> that will use the given
    108     * iterator.
    109     *
    110     * @param iterator the iterator to use.
    111     * @param multipleUse <code>true</code> if the new iterable can be used in multiple iterations
    112     */
    113    public IteratorIterable(final Iterator<? extends E> iterator, final boolean multipleUse) {
    114        super();
    115        if (multipleUse && !(iterator instanceof ResettableIterator)) {
    116            this.iterator = new ListIteratorWrapper<>(iterator);
    117        } else {
    118            this.iterator = iterator;
    119        }
    120        this.typeSafeIterator = createTypesafeIterator(this.iterator);
    121    }
    122
    123    /**
    124     * Gets the iterator wrapped by this iterable.
    125     *
    126     * @return the iterator
    127     */
    128    @Override
    129    public Iterator<E> iterator() {
    130        if (iterator instanceof ResettableIterator) {
    131            ((ResettableIterator<? extends E>)iterator).reset();
    132        }
    133        return typeSafeIterator;
    134    }
    135}