001 /* 002 // This software is subject to the terms of the Common Public License 003 // Agreement, available at the following URL: 004 // http://www.opensource.org/licenses/cpl.html. 005 // Copyright (C) 2008-2008 Julian Hyde 006 // All Rights Reserved. 007 // You must accept the terms of that agreement to use this software. 008 */ 009 package mondrian.util; 010 011 import mondrian.olap.Util; 012 013 import java.util.*; 014 015 /** 016 * Iterator over union of several {@link Iterable} collections. 017 * 018 * @see mondrian.olap.Util#union(Iterable[]) 019 * 020 * @author jhyde 021 * @version $Id: //open/mondrian/src/main/mondrian/util/UnionIterator.java#3 $ 022 * @since Apr 28, 2008 023 */ 024 public class UnionIterator<T> implements Iterator<T> { 025 private final Iterator<Iterable<? extends T>> iterableIterator; 026 private Iterator<? extends T> iterator; 027 028 /** 029 * Creates a UnionIterator. 030 * 031 * @param iterables Array of iterables 032 */ 033 public UnionIterator(Iterable<? extends T>... iterables) { 034 List<Iterable<? extends T>> list; 035 if (Util.Retrowoven) { 036 // Retroweaver has its own version of Iterable, but 037 // Collection doesn't implement it. Solve the problem by 038 // creating an explicit Iterable wrapper. 039 list = new ArrayList<Iterable<? extends T>>(iterables.length); 040 for (Iterable<? extends T> iterable : iterables) { 041 //noinspection unchecked 042 list.add(new MyIterable(iterable)); 043 } 044 } else { 045 list = Arrays.asList(iterables); 046 } 047 this.iterableIterator = list.iterator(); 048 moveToNext(); 049 } 050 051 public UnionIterator(Collection<? extends T>... iterables) { 052 List<Iterable<? extends T>> list = 053 new ArrayList<Iterable<? extends T>>(iterables.length); 054 for (Iterable<? extends T> iterable : iterables) { 055 //noinspection unchecked 056 list.add(new MyIterable(iterable)); 057 } 058 this.iterableIterator = list.iterator(); 059 moveToNext(); 060 } 061 062 public boolean hasNext() { 063 return iterator.hasNext(); 064 } 065 066 public T next() { 067 final T t = iterator.next(); 068 if (!iterator.hasNext()) { 069 moveToNext(); 070 } 071 return t; 072 } 073 074 /** 075 * Moves to the next iterator that has at least one element. 076 * Called after finishing an iterator, or at the start. 077 */ 078 private void moveToNext() { 079 do { 080 if (iterableIterator.hasNext()) { 081 iterator = iterableIterator.next().iterator(); 082 } else { 083 iterator = Collections.<T>emptyList().iterator(); 084 break; 085 } 086 } while (!iterator.hasNext()); 087 } 088 089 public void remove() { 090 iterator.remove(); 091 } 092 093 private static class MyIterable<T> implements Iterable { 094 private final Iterable<T> iterable; 095 096 /** 097 * Creates a MyIterable. 098 * 099 * @param iterable Iterable 100 */ 101 public MyIterable(Iterable<T> iterable) { 102 this.iterable = iterable; 103 } 104 105 public Iterator<T> iterator() { 106 return iterable.iterator(); 107 } 108 } 109 } 110 111 // End UnionIterator.java