001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.modeshape.common.collection; 018 019import java.util.Iterator; 020import java.util.NoSuchElementException; 021import org.modeshape.common.annotation.NotThreadSafe; 022 023/** 024 * An iterator implementation that wraps multiple other iterators. 025 * 026 * @author Randall Hauch (rhauch@redhat.com) 027 * @param <E> the value type 028 */ 029@NotThreadSafe 030public final class MultiIterator<E> implements Iterator<E> { 031 032 public static <E> MultiIterator<E> fromIterators( Iterable<Iterator<E>> iterators ) { 033 return new MultiIterator<>(iterators); 034 } 035 036 public static <E> MultiIterator<E> fromIterables( final Iterable<? extends Iterable<E>> iterables ) { 037 final Iterator<? extends Iterable<E>> iterator = iterables.iterator(); 038 Iterable<Iterator<E>> iterators = new Iterable<Iterator<E>>() { 039 @Override 040 public Iterator<Iterator<E>> iterator() { 041 return new Iterator<Iterator<E>>() { 042 @Override 043 public boolean hasNext() { 044 return iterator.hasNext(); 045 } 046 047 @Override 048 public Iterator<E> next() { 049 return iterator.next().iterator(); 050 } 051 052 @Override 053 public void remove() { 054 iterator.remove(); 055 } 056 }; 057 } 058 }; 059 return new MultiIterator<>(iterators); 060 } 061 062 private final Iterator<Iterator<E>> iterators; 063 private Iterator<E> current; 064 065 protected MultiIterator( Iterable<Iterator<E>> iterators ) { 066 this.iterators = iterators.iterator(); 067 } 068 069 @Override 070 public boolean hasNext() { 071 if (nextIterator()) return current.hasNext(); 072 return false; 073 } 074 075 @Override 076 public E next() { 077 if (nextIterator()) return current.next(); 078 throw new NoSuchElementException(); 079 } 080 081 protected boolean nextIterator() { 082 while (current == null || !current.hasNext()) { 083 // Find the next iterator ... 084 if (!iterators.hasNext()) return false; 085 current = iterators.next(); 086 } 087 return true; 088 } 089 090 @Override 091 public void remove() { 092 throw new UnsupportedOperationException(); 093 } 094 095}