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) 2011-2011 Pentaho
008// All Rights Reserved.
009*/
010package mondrian.util;
011
012import java.util.*;
013
014/**
015 * Composite collections.
016 *
017 * @author jhyde
018 */
019public abstract class Composite {
020
021    /**
022     * Creates a composite list, inferring the element type from the arguments.
023     *
024     * @param lists One or more lists
025     * @param <T> element type
026     * @return composite list
027     */
028    public static <T> List<T> of(
029        List<? extends T>... lists)
030    {
031        return CompositeList.<T>of(lists);
032    }
033
034    /**
035     * Creates a composite iterable, inferring the element type from the
036     * arguments.
037     *
038     * @param iterables One or more iterables
039     * @param <T> element type
040     * @return composite iterable
041     */
042    public static <T> Iterable<T> of(
043        Iterable<? extends T>... iterables)
044    {
045        return new CompositeIterable<T>(iterables);
046    }
047
048    /**
049     * Creates a composite list, inferring the element type from the arguments.
050     *
051     * @param iterators One or more iterators
052     * @param <T> element type
053     * @return composite list
054     */
055    public static <T> Iterator<T> of(
056        Iterator<? extends T>... iterators)
057    {
058        final Iterator[] iterators1 = (Iterator[]) iterators;
059        return new CompositeIterator<T>(iterators1);
060    }
061
062    private static class CompositeIterable<T> implements Iterable<T> {
063        private final Iterable<? extends T>[] iterables;
064
065        public CompositeIterable(Iterable<? extends T>[] iterables) {
066            this.iterables = iterables;
067        }
068
069        public Iterator<T> iterator() {
070            return new CompositeIterator(iterables);
071        }
072    }
073
074    private static class CompositeIterator<T> implements Iterator<T> {
075        private final Iterator<Iterator<T>> iteratorIterator;
076        private boolean hasNext;
077        private T next;
078        private Iterator<T> iterator;
079
080        public CompositeIterator(Iterator<T>[] iterables) {
081            this.iteratorIterator = Arrays.asList(iterables).iterator();
082            this.iterator = Collections.<T>emptyList().iterator();
083            this.hasNext = true;
084            advance();
085        }
086
087        public CompositeIterator(final Iterable<T>[] iterables) {
088            this.iteratorIterator =
089                new IterableIterator<T>(iterables);
090                Arrays.asList(iterables).iterator();
091            this.iterator = Collections.<T>emptyList().iterator();
092            this.hasNext = true;
093            advance();
094        }
095
096        private void advance() {
097            for (;;) {
098                if (iterator.hasNext()) {
099                    next = iterator.next();
100                    return;
101                }
102                if (!iteratorIterator.hasNext()) {
103                    hasNext = false;
104                    break;
105                }
106                iterator = iteratorIterator.next();
107            }
108        }
109
110        public boolean hasNext() {
111            return hasNext;
112        }
113
114        public T next() {
115            final T next1 = next;
116            advance();
117            return next1;
118        }
119
120        public void remove() {
121            throw new UnsupportedOperationException();
122        }
123    }
124
125    private static class IterableIterator<T>
126        implements Iterator<Iterator<T>>
127    {
128        private int i;
129        private final Iterable<T>[] iterables;
130
131        public IterableIterator(Iterable<T>[] iterables) {
132            this.iterables = iterables;
133            i = 0;
134        }
135
136        public boolean hasNext() {
137            return i < iterables.length;
138        }
139
140        public Iterator<T> next() {
141            return iterables[i++].iterator();
142        }
143
144        public void remove() {
145            throw new UnsupportedOperationException();
146        }
147    }
148}
149
150// End Composite.java