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