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