001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2005-2005 Julian Hyde
008// Copyright (C) 2005-2012 Pentaho
009// All Rights Reserved.
010*/
011package mondrian.util;
012
013import java.util.*;
014
015/**
016 * Iterable over an iterator.
017 *
018 * <p>It can be restarted. As you iterate, it stores elements in a backing
019 * array. If you call {@link #iterator()} again, it will first replay elements
020 * from that array.</p>
021 */
022public class IteratorIterable<E> implements Iterable<E> {
023    private final List<E> list = new ArrayList<E>();
024    private final Iterator<E> recordingIterator;
025
026    /** Creates an IteratorIterable. */
027    public IteratorIterable(final Iterator<E> iterator) {
028        this.recordingIterator =
029            new Iterator<E>() {
030                public boolean hasNext() {
031                    return iterator.hasNext();
032                }
033
034                public E next() {
035                    final E e = iterator.next();
036                    list.add(e);
037                    return e;
038                }
039
040                public void remove() {
041                    throw new UnsupportedOperationException();
042                }
043            };
044    }
045
046    public Iterator<E> iterator() {
047        // Return an iterator over the union of (1) the list, (2) the rest
048        // of the iterator. The second part writes elements to the list as
049        // it returns them.
050        //noinspection unchecked
051        return Composite.of(
052            // Can't use ArrayList.iterator(). It throws
053            // ConcurrentModificationException, because the list is growing
054            // under its feet.
055            new Iterator<E>() {
056                int i = 0;
057
058                public boolean hasNext() {
059                    return i < list.size();
060                }
061
062                public E next() {
063                    return list.get(i++);
064                }
065
066                public void remove() {
067                    throw new UnsupportedOperationException();
068                }
069            },
070            recordingIterator);
071    }
072}
073
074// End IteratorIterable.java