001: /*
002: * Janino - An embedded Java[TM] compiler
003: *
004: * Copyright (c) 2006, Arno Unkrig
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * 2. Redistributions in binary form must reproduce the above
014: * copyright notice, this list of conditions and the following
015: * disclaimer in the documentation and/or other materials
016: * provided with the distribution.
017: * 3. The name of the author may not be used to endorse or promote
018: * products derived from this software without specific prior
019: * written permission.
020: *
021: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
022: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
023: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
024: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
025: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
026: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
027: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
028: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
029: * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
030: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
031: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
032: */
033:
034: package org.codehaus.janino.util.iterator;
035:
036: import java.util.*;
037:
038: /**
039: * An {@link java.util.Iterator} that iterates over a delegate, which produces
040: * arrays, {@link java.util.Collection}s, {@link java.util.Enumeration}s or
041: * {@link java.util.Iterator}s. This {@link java.util.Iterator} returns the
042: * elements of these objects.
043: * <p>
044: * The count of dimensions is declared at construction. Count "1" produces an
045: * {@link java.util.Iterator} that adds no functionality to its delegate, count
046: * "2" produces an {@link Iterator} that behaves as explained above, and so
047: * forth.
048: */
049: public class MultiDimensionalIterator implements Iterator {
050: private final Iterator[] nest;
051: private static final Iterator EMPTY_ITERATOR = new Iterator() {
052: public boolean hasNext() {
053: return false;
054: }
055:
056: public Object next() {
057: throw new NoSuchElementException();
058: }
059:
060: public void remove() {
061: throw new UnsupportedOperationException("remove");
062: }
063: };
064:
065: public MultiDimensionalIterator(Iterator delegate,
066: int dimensionCount) {
067: this .nest = new Iterator[dimensionCount];
068: this .nest[0] = delegate;
069: for (int i = 1; i < dimensionCount; ++i)
070: this .nest[i] = MultiDimensionalIterator.EMPTY_ITERATOR;
071: }
072:
073: /**
074: * @throws UniterableElementException
075: */
076: public boolean hasNext() {
077:
078: // Unroll this check because it is so performance critical:
079: if (this .nest[this .nest.length - 1].hasNext())
080: return true;
081:
082: int i = this .nest.length - 2;
083: if (i < 0)
084: return false;
085:
086: for (;;) {
087: if (!this .nest[i].hasNext()) {
088: if (i == 0)
089: return false;
090: --i;
091: } else {
092: if (i == this .nest.length - 1)
093: return true;
094: Object o = this .nest[i].next();
095: if (o instanceof Iterator) {
096: this .nest[++i] = (Iterator) o;
097: } else if (o instanceof Object[]) {
098: this .nest[++i] = Arrays.asList((Object[]) o)
099: .iterator();
100: } else if (o instanceof Collection) {
101: this .nest[++i] = ((Collection) o).iterator();
102: } else if (o instanceof Enumeration) {
103: this .nest[++i] = new EnumerationIterator(
104: (Enumeration) o);
105: } else {
106: throw new UniterableElementException();
107: }
108: }
109: }
110: }
111:
112: public Object next() {
113: if (!this .hasNext())
114: throw new NoSuchElementException();
115: return this .nest[this .nest.length - 1].next();
116: }
117:
118: public void remove() {
119: throw new UnsupportedOperationException("remove");
120: }
121: }
|