001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.collections4;
018
019import java.lang.reflect.Array;
020import java.lang.reflect.InvocationTargetException;
021import java.lang.reflect.Method;
022import java.util.ArrayList;
023import java.util.Collection;
024import java.util.Comparator;
025import java.util.Dictionary;
026import java.util.Enumeration;
027import java.util.Iterator;
028import java.util.List;
029import java.util.ListIterator;
030import java.util.Map;
031
032import org.apache.commons.collections4.functors.EqualPredicate;
033import org.apache.commons.collections4.iterators.ArrayIterator;
034import org.apache.commons.collections4.iterators.ArrayListIterator;
035import org.apache.commons.collections4.iterators.BoundedIterator;
036import org.apache.commons.collections4.iterators.CollatingIterator;
037import org.apache.commons.collections4.iterators.EmptyIterator;
038import org.apache.commons.collections4.iterators.EmptyListIterator;
039import org.apache.commons.collections4.iterators.EmptyMapIterator;
040import org.apache.commons.collections4.iterators.EmptyOrderedIterator;
041import org.apache.commons.collections4.iterators.EmptyOrderedMapIterator;
042import org.apache.commons.collections4.iterators.EnumerationIterator;
043import org.apache.commons.collections4.iterators.FilterIterator;
044import org.apache.commons.collections4.iterators.FilterListIterator;
045import org.apache.commons.collections4.iterators.IteratorChain;
046import org.apache.commons.collections4.iterators.IteratorEnumeration;
047import org.apache.commons.collections4.iterators.IteratorIterable;
048import org.apache.commons.collections4.iterators.ListIteratorWrapper;
049import org.apache.commons.collections4.iterators.LoopingIterator;
050import org.apache.commons.collections4.iterators.LoopingListIterator;
051import org.apache.commons.collections4.iterators.NodeListIterator;
052import org.apache.commons.collections4.iterators.ObjectArrayIterator;
053import org.apache.commons.collections4.iterators.ObjectArrayListIterator;
054import org.apache.commons.collections4.iterators.ObjectGraphIterator;
055import org.apache.commons.collections4.iterators.PeekingIterator;
056import org.apache.commons.collections4.iterators.PushbackIterator;
057import org.apache.commons.collections4.iterators.SingletonIterator;
058import org.apache.commons.collections4.iterators.SingletonListIterator;
059import org.apache.commons.collections4.iterators.SkippingIterator;
060import org.apache.commons.collections4.iterators.TransformIterator;
061import org.apache.commons.collections4.iterators.UnmodifiableIterator;
062import org.apache.commons.collections4.iterators.UnmodifiableListIterator;
063import org.apache.commons.collections4.iterators.UnmodifiableMapIterator;
064import org.apache.commons.collections4.iterators.ZippingIterator;
065import org.w3c.dom.Node;
066import org.w3c.dom.NodeList;
067
068/**
069 * Provides static utility methods and decorators for {@link Iterator}
070 * instances. The implementations are provided in the iterators subpackage.
071 *
072 * @since 2.1
073 */
074public class IteratorUtils {
075    // validation is done in this class in certain cases because the
076    // public classes allow invalid states
077
078    /**
079     * An iterator over no elements.
080     */
081    @SuppressWarnings("rawtypes")
082    public static final ResettableIterator EMPTY_ITERATOR = EmptyIterator.RESETTABLE_INSTANCE;
083
084    /**
085     * A list iterator over no elements.
086     */
087    @SuppressWarnings("rawtypes")
088    public static final ResettableListIterator EMPTY_LIST_ITERATOR = EmptyListIterator.RESETTABLE_INSTANCE;
089
090    /**
091     * An ordered iterator over no elements.
092     */
093    @SuppressWarnings("rawtypes")
094    public static final OrderedIterator EMPTY_ORDERED_ITERATOR = EmptyOrderedIterator.INSTANCE;
095
096    /**
097     * A map iterator over no elements.
098     */
099    @SuppressWarnings("rawtypes")
100    public static final MapIterator EMPTY_MAP_ITERATOR = EmptyMapIterator.INSTANCE;
101
102    /**
103     * An ordered map iterator over no elements.
104     */
105    @SuppressWarnings("rawtypes")
106    public static final OrderedMapIterator EMPTY_ORDERED_MAP_ITERATOR = EmptyOrderedMapIterator.INSTANCE;
107
108    /**
109     * Default prefix used while converting an Iterator to its String representation.
110     */
111    private static final String DEFAULT_TOSTRING_PREFIX = "[";
112
113    /**
114     * Default suffix used while converting an Iterator to its String representation.
115     */
116    private static final String DEFAULT_TOSTRING_SUFFIX = "]";
117
118    /**
119     * Default delimiter used to delimit elements while converting an Iterator
120     * to its String representation.
121     */
122    private static final String DEFAULT_TOSTRING_DELIMITER = ", ";
123
124    /**
125     * IteratorUtils is not normally instantiated.
126     */
127    private IteratorUtils() {}
128
129    // Empty
130    //-----------------------------------------------------------------------
131    /**
132     * Gets an empty iterator.
133     * <p>
134     * This iterator is a valid iterator object that will iterate over nothing.
135     *
136     * @param <E> the element type
137     * @return an iterator over nothing
138     */
139    public static <E> ResettableIterator<E> emptyIterator() {
140        return EmptyIterator.<E>resettableEmptyIterator();
141    }
142
143    /**
144     * Gets an empty list iterator.
145     * <p>
146     * This iterator is a valid list iterator object that will iterate
147     * over nothing.
148     *
149     * @param <E> the element type
150     * @return a list iterator over nothing
151     */
152    public static <E> ResettableListIterator<E> emptyListIterator() {
153        return EmptyListIterator.<E>resettableEmptyListIterator();
154    }
155
156    /**
157     * Gets an empty ordered iterator.
158     * <p>
159     * This iterator is a valid iterator object that will iterate
160     * over nothing.
161     *
162     * @param <E> the element type
163     * @return an ordered iterator over nothing
164     */
165    public static <E> OrderedIterator<E> emptyOrderedIterator() {
166        return EmptyOrderedIterator.<E>emptyOrderedIterator();
167    }
168
169    /**
170     * Gets an empty map iterator.
171     * <p>
172     * This iterator is a valid map iterator object that will iterate
173     * over nothing.
174     *
175     * @param <K> the key type
176     * @param <V> the value type
177     * @return a map iterator over nothing
178     */
179    public static <K, V> MapIterator<K, V> emptyMapIterator() {
180        return EmptyMapIterator.<K, V>emptyMapIterator();
181    }
182
183    /**
184     * Gets an empty ordered map iterator.
185     * <p>
186     * This iterator is a valid map iterator object that will iterate
187     * over nothing.
188     *
189     * @param <K> the key type
190     * @param <V> the value type
191     * @return a map iterator over nothing
192     */
193    public static <K, V> OrderedMapIterator<K, V> emptyOrderedMapIterator() {
194        return EmptyOrderedMapIterator.<K, V>emptyOrderedMapIterator();
195    }
196
197    // Singleton
198    //-----------------------------------------------------------------------
199    /**
200     * Gets a singleton iterator.
201     * <p>
202     * This iterator is a valid iterator object that will iterate over
203     * the specified object.
204     *
205     * @param <E> the element type
206     * @param object  the single object over which to iterate
207     * @return a singleton iterator over the object
208     */
209    public static <E> ResettableIterator<E> singletonIterator(final E object) {
210        return new SingletonIterator<>(object);
211    }
212
213    /**
214     * Gets a singleton list iterator.
215     * <p>
216     * This iterator is a valid list iterator object that will iterate over
217     * the specified object.
218     *
219     * @param <E> the element type
220     * @param object  the single object over which to iterate
221     * @return a singleton list iterator over the object
222     */
223    public static <E> ListIterator<E> singletonListIterator(final E object) {
224        return new SingletonListIterator<>(object);
225    }
226
227    // Arrays
228    //-----------------------------------------------------------------------
229    /**
230     * Gets an iterator over an object array.
231     *
232     * @param <E> the element type
233     * @param array  the array over which to iterate
234     * @return an iterator over the array
235     * @throws NullPointerException if array is null
236     */
237    public static <E> ResettableIterator<E> arrayIterator(final E... array) {
238        return new ObjectArrayIterator<>(array);
239    }
240
241    /**
242     * Gets an iterator over an object or primitive array.
243     * <p>
244     * This method will handle primitive arrays as well as object arrays.
245     * The primitives will be wrapped in the appropriate wrapper class.
246     *
247     * @param <E> the element type
248     * @param array  the array over which to iterate
249     * @return an iterator over the array
250     * @throws IllegalArgumentException if the array is not an array
251     * @throws NullPointerException if array is null
252     */
253    public static <E> ResettableIterator<E> arrayIterator(final Object array) {
254        return new ArrayIterator<>(array);
255    }
256
257    /**
258     * Gets an iterator over the end part of an object array.
259     *
260     * @param <E> the element type
261     * @param array  the array over which to iterate
262     * @param start  the index to start iterating at
263     * @return an iterator over part of the array
264     * @throws IndexOutOfBoundsException if start is less than zero or greater
265     *   than the length of the array
266     * @throws NullPointerException if array is null
267     */
268    public static <E> ResettableIterator<E> arrayIterator(final E[] array, final int start) {
269        return new ObjectArrayIterator<>(array, start);
270    }
271
272    /**
273     * Gets an iterator over the end part of an object or primitive array.
274     * <p>
275     * This method will handle primitive arrays as well as object arrays.
276     * The primitives will be wrapped in the appropriate wrapper class.
277     *
278     * @param <E> the element type
279     * @param array  the array over which to iterate
280     * @param start  the index to start iterating at
281     * @return an iterator over part of the array
282     * @throws IllegalArgumentException if the array is not an array
283     * @throws IndexOutOfBoundsException if start is less than zero or greater
284     *   than the length of the array
285     * @throws NullPointerException if array is null
286     */
287    public static <E> ResettableIterator<E> arrayIterator(final Object array, final int start) {
288        return new ArrayIterator<>(array, start);
289    }
290
291    /**
292     * Gets an iterator over part of an object array.
293     *
294     * @param <E> the element type
295     * @param array  the array over which to iterate
296     * @param start  the index to start iterating at
297     * @param end  the index to finish iterating at
298     * @return an iterator over part of the array
299     * @throws IndexOutOfBoundsException if array bounds are invalid
300     * @throws IllegalArgumentException if end is before start
301     * @throws NullPointerException if array is null
302     */
303    public static <E> ResettableIterator<E> arrayIterator(final E[] array, final int start, final int end) {
304        return new ObjectArrayIterator<>(array, start, end);
305    }
306
307    /**
308     * Gets an iterator over part of an object or primitive array.
309     * <p>
310     * This method will handle primitive arrays as well as object arrays.
311     * The primitives will be wrapped in the appropriate wrapper class.
312     *
313     * @param <E> the element type
314     * @param array  the array over which to iterate
315     * @param start  the index to start iterating at
316     * @param end  the index to finish iterating at
317     * @return an iterator over part of the array
318     * @throws IllegalArgumentException if the array is not an array or end is before start
319     * @throws IndexOutOfBoundsException if array bounds are invalid
320     * @throws NullPointerException if array is null
321     */
322    public static <E> ResettableIterator<E> arrayIterator(final Object array, final int start, final int end) {
323        return new ArrayIterator<>(array, start, end);
324    }
325
326    //-----------------------------------------------------------------------
327    /**
328     * Gets a list iterator over an object array.
329     *
330     * @param <E> the element type
331     * @param array  the array over which to iterate
332     * @return a list iterator over the array
333     * @throws NullPointerException if array is null
334     */
335    public static <E> ResettableListIterator<E> arrayListIterator(final E... array) {
336        return new ObjectArrayListIterator<>(array);
337    }
338
339    /**
340     * Gets a list iterator over an object or primitive array.
341     * <p>
342     * This method will handle primitive arrays as well as object arrays.
343     * The primitives will be wrapped in the appropriate wrapper class.
344     *
345     * @param <E> the element type
346     * @param array  the array over which to iterate
347     * @return a list iterator over the array
348     * @throws IllegalArgumentException if the array is not an array
349     * @throws NullPointerException if array is null
350     */
351    public static <E> ResettableListIterator<E> arrayListIterator(final Object array) {
352        return new ArrayListIterator<>(array);
353    }
354
355    /**
356     * Gets a list iterator over the end part of an object array.
357     *
358     * @param <E> the element type
359     * @param array  the array over which to iterate
360     * @param start  the index to start iterating at
361     * @return a list iterator over part of the array
362     * @throws IndexOutOfBoundsException if start is less than zero
363     * @throws NullPointerException if array is null
364     */
365    public static <E> ResettableListIterator<E> arrayListIterator(final E[] array, final int start) {
366        return new ObjectArrayListIterator<>(array, start);
367    }
368
369    /**
370     * Gets a list iterator over the end part of an object or primitive array.
371     * <p>
372     * This method will handle primitive arrays as well as object arrays.
373     * The primitives will be wrapped in the appropriate wrapper class.
374     *
375     * @param <E> the element type
376     * @param array  the array over which to iterate
377     * @param start  the index to start iterating at
378     * @return a list iterator over part of the array
379     * @throws IllegalArgumentException if the array is not an array
380     * @throws IndexOutOfBoundsException if start is less than zero
381     * @throws NullPointerException if array is null
382     */
383    public static <E> ResettableListIterator<E> arrayListIterator(final Object array, final int start) {
384        return new ArrayListIterator<>(array, start);
385    }
386
387    /**
388     * Gets a list iterator over part of an object array.
389     *
390     * @param <E> the element type
391     * @param array  the array over which to iterate
392     * @param start  the index to start iterating at
393     * @param end  the index to finish iterating at
394     * @return a list iterator over part of the array
395     * @throws IndexOutOfBoundsException if array bounds are invalid
396     * @throws IllegalArgumentException if end is before start
397     * @throws NullPointerException if array is null
398     */
399    public static <E> ResettableListIterator<E> arrayListIterator(final E[] array, final int start, final int end) {
400        return new ObjectArrayListIterator<>(array, start, end);
401    }
402
403    /**
404     * Gets a list iterator over part of an object or primitive array.
405     * <p>
406     * This method will handle primitive arrays as well as object arrays.
407     * The primitives will be wrapped in the appropriate wrapper class.
408     *
409     * @param <E> the element type
410     * @param array  the array over which to iterate
411     * @param start  the index to start iterating at
412     * @param end  the index to finish iterating at
413     * @return a list iterator over part of the array
414     * @throws IllegalArgumentException if the array is not an array or end is before start
415     * @throws IndexOutOfBoundsException if array bounds are invalid
416     * @throws NullPointerException if array is null
417     */
418    public static <E> ResettableListIterator<E> arrayListIterator(final Object array, final int start, final int end) {
419        return new ArrayListIterator<>(array, start, end);
420    }
421
422    // Bounded
423    //-----------------------------------------------------------------------
424    /**
425     * Decorates the specified iterator to return at most the given number
426     * of elements.
427     *
428     * @param <E> the element type
429     * @param iterator  the iterator to decorate
430     * @param max  the maximum number of elements returned by this iterator
431     * @return a new bounded iterator
432     * @throws NullPointerException if the iterator is null
433     * @throws IllegalArgumentException if max is negative
434     * @since 4.1
435     */
436    public static <E> BoundedIterator<E> boundedIterator(final Iterator<? extends E> iterator, final long max) {
437        return boundedIterator(iterator, 0, max);
438    }
439
440    /**
441     * Decorates the specified iterator to return at most the given number
442     * of elements, skipping all elements until the iterator reaches the
443     * position at {@code offset}.
444     * <p>
445     * The iterator is immediately advanced until it reaches the position at
446     * {@code offset}, incurring O(n) time.
447     *
448     * @param <E> the element type
449     * @param iterator  the iterator to decorate
450     * @param offset  the index of the first element of the decorated iterator to return
451     * @param max  the maximum number of elements returned by this iterator
452     * @return a new bounded iterator
453     * @throws NullPointerException if the iterator is null
454     * @throws IllegalArgumentException if either offset or max is negative
455     * @since 4.1
456     */
457    public static <E> BoundedIterator<E> boundedIterator(final Iterator<? extends E> iterator,
458                                                         final long offset, final long max) {
459        return new BoundedIterator<>(iterator, offset, max);
460    }
461
462    // Unmodifiable
463    //-----------------------------------------------------------------------
464    /**
465     * Gets an immutable version of an {@link Iterator}. The returned object
466     * will always throw an {@link UnsupportedOperationException} for
467     * the {@link Iterator#remove} method.
468     *
469     * @param <E> the element type
470     * @param iterator  the iterator to make immutable
471     * @return an immutable version of the iterator
472     */
473    public static <E> Iterator<E> unmodifiableIterator(final Iterator<E> iterator) {
474        return UnmodifiableIterator.unmodifiableIterator(iterator);
475    }
476
477    /**
478     * Gets an immutable version of a {@link ListIterator}. The returned object
479     * will always throw an {@link UnsupportedOperationException} for
480     * the {@link Iterator#remove}, {@link ListIterator#add} and
481     * {@link ListIterator#set} methods.
482     *
483     * @param <E> the element type
484     * @param listIterator  the iterator to make immutable
485     * @return an immutable version of the iterator
486     */
487    public static <E> ListIterator<E> unmodifiableListIterator(final ListIterator<E> listIterator) {
488        return UnmodifiableListIterator.umodifiableListIterator(listIterator);
489    }
490
491    /**
492     * Gets an immutable version of a {@link MapIterator}. The returned object
493     * will always throw an {@link UnsupportedOperationException} for
494     * the {@link Iterator#remove}, {@link MapIterator#setValue(Object)} methods.
495     *
496     * @param <K> the key type
497     * @param <V> the value type
498     * @param mapIterator  the iterator to make immutable
499     * @return an immutable version of the iterator
500     */
501    public static <K, V> MapIterator<K, V> unmodifiableMapIterator(final MapIterator<K, V> mapIterator) {
502        return UnmodifiableMapIterator.unmodifiableMapIterator(mapIterator);
503    }
504
505    // Chained
506    //-----------------------------------------------------------------------
507
508    /**
509     * Gets an iterator that iterates through two {@link Iterator}s
510     * one after another.
511     *
512     * @param <E> the element type
513     * @param iterator1  the first iterator to use, not null
514     * @param iterator2  the second iterator to use, not null
515     * @return a combination iterator over the iterators
516     * @throws NullPointerException if either iterator is null
517     */
518    public static <E> Iterator<E> chainedIterator(final Iterator<? extends E> iterator1,
519                                                  final Iterator<? extends E> iterator2) {
520        // keep a version with two iterators to avoid the following warning in client code (Java 5 & 6)
521        // "A generic array of E is created for a varargs parameter"
522        return new IteratorChain<>(iterator1, iterator2);
523    }
524
525    /**
526     * Gets an iterator that iterates through an array of {@link Iterator}s
527     * one after another.
528     *
529     * @param <E> the element type
530     * @param iterators  the iterators to use, not null or empty or contain nulls
531     * @return a combination iterator over the iterators
532     * @throws NullPointerException if iterators array is null or contains a null
533     */
534    public static <E> Iterator<E> chainedIterator(final Iterator<? extends E>... iterators) {
535        return new IteratorChain<>(iterators);
536    }
537
538    /**
539     * Gets an iterator that iterates through a collections of {@link Iterator}s
540     * one after another.
541     *
542     * @param <E> the element type
543     * @param iterators  the iterators to use, not null or empty or contain nulls
544     * @return a combination iterator over the iterators
545     * @throws NullPointerException if iterators collection is null or contains a null
546     * @throws ClassCastException if the iterators collection contains the wrong object type
547     */
548    public static <E> Iterator<E> chainedIterator(final Collection<Iterator<? extends E>> iterators) {
549        return new IteratorChain<>(iterators);
550    }
551
552    // Collated
553    //-----------------------------------------------------------------------
554    /**
555     * Gets an iterator that provides an ordered iteration over the elements
556     * contained in a collection of ordered {@link Iterator}s.
557     * <p>
558     * Given two ordered {@link Iterator}s <code>A</code> and <code>B</code>,
559     * the {@link Iterator#next()} method will return the lesser of
560     * <code>A.next()</code> and <code>B.next()</code>.
561     * <p>
562     * The comparator is optional. If null is specified then natural order is used.
563     *
564     * @param <E> the element type
565     * @param comparator  the comparator to use, may be null for natural order
566     * @param iterator1  the first iterators to use, not null
567     * @param iterator2  the first iterators to use, not null
568     * @return a combination iterator over the iterators
569     * @throws NullPointerException if either iterator is null
570     */
571    public static <E> Iterator<E> collatedIterator(final Comparator<? super E> comparator,
572                                                   final Iterator<? extends E> iterator1,
573                                                   final Iterator<? extends E> iterator2) {
574        @SuppressWarnings("unchecked")
575        final Comparator<E> comp =
576            comparator == null ? ComparatorUtils.NATURAL_COMPARATOR : (Comparator<E>) comparator;
577        return new CollatingIterator<>(comp, iterator1, iterator2);
578    }
579
580    /**
581     * Gets an iterator that provides an ordered iteration over the elements
582     * contained in an array of {@link Iterator}s.
583     * <p>
584     * Given two ordered {@link Iterator}s <code>A</code> and <code>B</code>,
585     * the {@link Iterator#next()} method will return the lesser of
586     * <code>A.next()</code> and <code>B.next()</code> and so on.
587     * <p>
588     * The comparator is optional. If null is specified then natural order is used.
589     *
590     * @param <E> the element type
591     * @param comparator  the comparator to use, may be null for natural order
592     * @param iterators  the iterators to use, not null or empty or contain nulls
593     * @return a combination iterator over the iterators
594     * @throws NullPointerException if iterators array is null or contains a null value
595     */
596    public static <E> Iterator<E> collatedIterator(final Comparator<? super E> comparator,
597                                                   final Iterator<? extends E>... iterators) {
598        @SuppressWarnings("unchecked")
599        final Comparator<E> comp =
600            comparator == null ? ComparatorUtils.NATURAL_COMPARATOR : (Comparator<E>) comparator;
601        return new CollatingIterator<>(comp, iterators);
602    }
603
604    /**
605     * Gets an iterator that provides an ordered iteration over the elements
606     * contained in a collection of {@link Iterator}s.
607     * <p>
608     * Given two ordered {@link Iterator}s <code>A</code> and <code>B</code>,
609     * the {@link Iterator#next()} method will return the lesser of
610     * <code>A.next()</code> and <code>B.next()</code> and so on.
611     * <p>
612     * The comparator is optional. If null is specified then natural order is used.
613     *
614     * @param <E> the element type
615     * @param comparator  the comparator to use, may be null for natural order
616     * @param iterators  the iterators to use, not null or empty or contain nulls
617     * @return a combination iterator over the iterators
618     * @throws NullPointerException if iterators collection is null or contains a null
619     * @throws ClassCastException if the iterators collection contains the wrong object type
620     */
621    public static <E> Iterator<E> collatedIterator(final Comparator<? super E> comparator,
622                                                   final Collection<Iterator<? extends E>> iterators) {
623        @SuppressWarnings("unchecked")
624        final Comparator<E> comp =
625            comparator == null ? ComparatorUtils.NATURAL_COMPARATOR : (Comparator<E>) comparator;
626        return new CollatingIterator<>(comp, iterators);
627    }
628
629    // Object Graph
630    //-----------------------------------------------------------------------
631    /**
632     * Gets an iterator that operates over an object graph.
633     * <p>
634     * This iterator can extract multiple objects from a complex tree-like object graph.
635     * The iteration starts from a single root object.
636     * It uses a <code>Transformer</code> to extract the iterators and elements.
637     * Its main benefit is that no intermediate <code>List</code> is created.
638     * <p>
639     * For example, consider an object graph:
640     * <pre>
641     *                 |- Branch -- Leaf
642     *                 |         \- Leaf
643     *         |- Tree |         /- Leaf
644     *         |       |- Branch -- Leaf
645     *  Forest |                 \- Leaf
646     *         |       |- Branch -- Leaf
647     *         |       |         \- Leaf
648     *         |- Tree |         /- Leaf
649     *                 |- Branch -- Leaf
650     *                 |- Branch -- Leaf</pre>
651     * The following <code>Transformer</code>, used in this class, will extract all
652     * the Leaf objects without creating a combined intermediate list:
653     * <pre>
654     * public Object transform(Object input) {
655     *   if (input instanceof Forest) {
656     *     return ((Forest) input).treeIterator();
657     *   }
658     *   if (input instanceof Tree) {
659     *     return ((Tree) input).branchIterator();
660     *   }
661     *   if (input instanceof Branch) {
662     *     return ((Branch) input).leafIterator();
663     *   }
664     *   if (input instanceof Leaf) {
665     *     return input;
666     *   }
667     *   throw new ClassCastException();
668     * }</pre>
669     * <p>
670     * Internally, iteration starts from the root object. When next is called,
671     * the transformer is called to examine the object. The transformer will return
672     * either an iterator or an object. If the object is an Iterator, the next element
673     * from that iterator is obtained and the process repeats. If the element is an object
674     * it is returned.
675     * <p>
676     * Under many circumstances, linking Iterators together in this manner is
677     * more efficient (and convenient) than using nested for loops to extract a list.
678     *
679     * @param <E> the element type
680     * @param root  the root object to start iterating from, null results in an empty iterator
681     * @param transformer  the transformer to use, see above, null uses no effect transformer
682     * @return a new object graph iterator
683     * @since 3.1
684     */
685    public static <E> Iterator<E> objectGraphIterator(final E root,
686            final Transformer<? super E, ? extends E> transformer) {
687        return new ObjectGraphIterator<>(root, transformer);
688    }
689
690    // Transformed
691    //-----------------------------------------------------------------------
692    /**
693     * Gets an iterator that transforms the elements of another iterator.
694     * <p>
695     * The transformation occurs during the next() method and the underlying
696     * iterator is unaffected by the transformation.
697     *
698     * @param <I> the input type
699     * @param <O> the output type
700     * @param iterator  the iterator to use, not null
701     * @param transform  the transform to use, not null
702     * @return a new transforming iterator
703     * @throws NullPointerException if either parameter is null
704     */
705    public static <I, O> Iterator<O> transformedIterator(final Iterator<? extends I> iterator,
706            final Transformer<? super I, ? extends O> transform) {
707
708        if (iterator == null) {
709            throw new NullPointerException("Iterator must not be null");
710        }
711        if (transform == null) {
712            throw new NullPointerException("Transformer must not be null");
713        }
714        return new TransformIterator<>(iterator, transform);
715    }
716
717    // Filtered
718    //-----------------------------------------------------------------------
719    /**
720     * Gets an iterator that filters another iterator.
721     * <p>
722     * The returned iterator will only return objects that match the specified
723     * filtering predicate.
724     *
725     * @param <E> the element type
726     * @param iterator  the iterator to use, not null
727     * @param predicate  the predicate to use as a filter, not null
728     * @return a new filtered iterator
729     * @throws NullPointerException if either parameter is null
730     */
731    public static <E> Iterator<E> filteredIterator(final Iterator<? extends E> iterator,
732                                                   final Predicate<? super E> predicate) {
733        if (iterator == null) {
734            throw new NullPointerException("Iterator must not be null");
735        }
736        if (predicate == null) {
737            throw new NullPointerException("Predicate must not be null");
738        }
739        return new FilterIterator<>(iterator, predicate);
740    }
741
742    /**
743     * Gets a list iterator that filters another list iterator.
744     * <p>
745     * The returned iterator will only return objects that match the specified
746     * filtering predicate.
747     *
748     * @param <E> the element type
749     * @param listIterator  the list iterator to use, not null
750     * @param predicate  the predicate to use as a filter, not null
751     * @return a new filtered iterator
752     * @throws NullPointerException if either parameter is null
753     */
754    public static <E> ListIterator<E> filteredListIterator(final ListIterator<? extends E> listIterator,
755            final Predicate<? super E> predicate) {
756
757        if (listIterator == null) {
758            throw new NullPointerException("ListIterator must not be null");
759        }
760        if (predicate == null) {
761            throw new NullPointerException("Predicate must not be null");
762        }
763        return new FilterListIterator<>(listIterator, predicate);
764    }
765
766    // Looping
767    //-----------------------------------------------------------------------
768    /**
769     * Gets an iterator that loops continuously over the supplied collection.
770     * <p>
771     * The iterator will only stop looping if the remove method is called
772     * enough times to empty the collection, or if the collection is empty
773     * to start with.
774     *
775     * @param <E> the element type
776     * @param coll  the collection to iterate over, not null
777     * @return a new looping iterator
778     * @throws NullPointerException if the collection is null
779     */
780    public static <E> ResettableIterator<E> loopingIterator(final Collection<? extends E> coll) {
781        if (coll == null) {
782            throw new NullPointerException("Collection must not be null");
783        }
784        return new LoopingIterator<>(coll);
785    }
786
787    /**
788     * Gets an iterator that loops continuously over the supplied list.
789     * <p>
790     * The iterator will only stop looping if the remove method is called
791     * enough times to empty the list, or if the list is empty to start with.
792     *
793     * @param <E> the element type
794     * @param list  the list to iterate over, not null
795     * @return a new looping iterator
796     * @throws NullPointerException if the list is null
797     * @since 3.2
798     */
799    public static <E> ResettableListIterator<E> loopingListIterator(final List<E> list) {
800        if (list == null) {
801            throw new NullPointerException("List must not be null");
802        }
803        return new LoopingListIterator<>(list);
804    }
805
806    // org.w3c.dom.NodeList iterators
807    //-----------------------------------------------------------------------
808    /**
809     * Gets an {@link Iterator} that wraps the specified {@link NodeList}.
810     * The returned {@link Iterator} can be used for a single iteration.
811     *
812     * @param nodeList  the node list to use, may not be null
813     * @return a new, single use {@link Iterator}
814     * @throws NullPointerException if nodeList is null
815     * @since 4.0
816     */
817    public static NodeListIterator nodeListIterator(final NodeList nodeList) {
818        if (nodeList == null) {
819            throw new NullPointerException("NodeList must not be null");
820        }
821        return new NodeListIterator(nodeList);
822    }
823
824    /**
825     * Gets an {@link Iterator} that wraps the specified node's childNodes.
826     * The returned {@link Iterator} can be used for a single iteration.
827     * <p>
828     * Convenience method, allows easy iteration over NodeLists:
829     * <pre>
830     *   Iterator&lt;Node&gt; iterator = IteratorUtils.nodeListIterator(node);
831     *   for(Node childNode : IteratorUtils.asIterable(iterator)) {
832     *     ...
833     *   }
834     * </pre>
835     *
836     * @param node  the node to use, may not be null
837     * @return a new, single use {@link Iterator}
838     * @throws NullPointerException if node is null
839     * @since 4.0
840     */
841    public static NodeListIterator nodeListIterator(final Node node) {
842        if (node == null) {
843            throw new NullPointerException("Node must not be null");
844        }
845        return new NodeListIterator(node);
846    }
847
848    // Peeking
849    //-----------------------------------------------------------------------
850
851    /**
852     * Gets an iterator that supports one-element lookahead.
853     *
854     * @param <E> the element type
855     * @param iterator  the iterator to decorate, not null
856     * @return a peeking iterator
857     * @throws NullPointerException if the iterator is null
858     * @since 4.0
859     */
860    public static <E> Iterator<E> peekingIterator(final Iterator<? extends E> iterator) {
861        return PeekingIterator.peekingIterator(iterator);
862    }
863
864    // Pushback
865    //-----------------------------------------------------------------------
866
867    /**
868     * Gets an iterator that supports pushback of elements.
869     *
870     * @param <E> the element type
871     * @param iterator  the iterator to decorate, not null
872     * @return a pushback iterator
873     * @throws NullPointerException if the iterator is null
874     * @since 4.0
875     */
876    public static <E> Iterator<E> pushbackIterator(final Iterator<? extends E> iterator) {
877        return PushbackIterator.pushbackIterator(iterator);
878    }
879
880    // Skipping
881    //-----------------------------------------------------------------------
882    /**
883     * Decorates the specified iterator to skip the first N elements.
884     *
885     * @param <E> the element type
886     * @param iterator  the iterator to decorate
887     * @param offset  the first number of elements to skip
888     * @return a new skipping iterator
889     * @throws NullPointerException if the iterator is null
890     * @throws IllegalArgumentException if offset is negative
891     * @since 4.1
892     */
893    public static <E> SkippingIterator<E> skippingIterator(final Iterator<E> iterator, final long offset) {
894        return new SkippingIterator<>(iterator, offset);
895    }
896
897    // Zipping
898    //-----------------------------------------------------------------------
899    /**
900     * Returns an iterator that interleaves elements from the decorated iterators.
901     *
902     * @param <E> the element type
903     * @param a  the first iterator to interleave
904     * @param b  the second iterator to interleave
905     * @return an iterator, interleaving the decorated iterators
906     * @throws NullPointerException if any iterator is null
907     * @since 4.1
908     */
909    public static <E> ZippingIterator<E> zippingIterator(final Iterator<? extends E> a,
910                                                         final Iterator<? extends E> b) {
911        return new ZippingIterator<>(a, b);
912    }
913
914    /**
915     * Returns an iterator that interleaves elements from the decorated iterators.
916     *
917     * @param <E> the element type
918     * @param a  the first iterator to interleave
919     * @param b  the second iterator to interleave
920     * @param c  the third iterator to interleave
921     * @return an iterator, interleaving the decorated iterators
922     * @throws NullPointerException if any iterator is null
923     * @since 4.1
924     */
925    public static <E> ZippingIterator<E> zippingIterator(final Iterator<? extends E> a,
926                                                         final Iterator<? extends E> b,
927                                                         final Iterator<? extends E> c) {
928        return new ZippingIterator<>(a, b, c);
929    }
930
931    /**
932     * Returns an iterator that interleaves elements from the decorated iterators.
933     *
934     * @param <E> the element type
935     * @param iterators  the array of iterators to interleave
936     * @return an iterator, interleaving the decorated iterators
937     * @throws NullPointerException if any iterator is null
938     * @since 4.1
939     */
940    public static <E> ZippingIterator<E> zippingIterator(final Iterator<? extends E>... iterators) {
941        return new ZippingIterator<>(iterators);
942    }
943
944    // Views
945    //-----------------------------------------------------------------------
946    /**
947     * Gets an iterator that provides an iterator view of the given enumeration.
948     *
949     * @param <E> the element type
950     * @param enumeration  the enumeration to use, may not be null
951     * @return a new iterator
952     * @throws NullPointerException if enumeration is null
953     */
954    public static <E> Iterator<E> asIterator(final Enumeration<? extends E> enumeration) {
955        if (enumeration == null) {
956            throw new NullPointerException("Enumeration must not be null");
957        }
958        return new EnumerationIterator<>(enumeration);
959    }
960
961    /**
962     * Gets an iterator that provides an iterator view of the given enumeration
963     * that will remove elements from the specified collection.
964     *
965     * @param <E> the element type
966     * @param enumeration  the enumeration to use, may not be null
967     * @param removeCollection  the collection to remove elements from, may not be null
968     * @return a new iterator
969     * @throws NullPointerException if enumeration or removeCollection is null
970     */
971    public static <E> Iterator<E> asIterator(final Enumeration<? extends E> enumeration,
972                                             final Collection<? super E> removeCollection) {
973        if (enumeration == null) {
974            throw new NullPointerException("Enumeration must not be null");
975        }
976        if (removeCollection == null) {
977            throw new NullPointerException("Collection must not be null");
978        }
979        return new EnumerationIterator<>(enumeration, removeCollection);
980    }
981
982    /**
983     * Gets an enumeration that wraps an iterator.
984     *
985     * @param <E> the element type
986     * @param iterator  the iterator to use, may not be null
987     * @return a new enumeration
988     * @throws NullPointerException if iterator is null
989     */
990    public static <E> Enumeration<E> asEnumeration(final Iterator<? extends E> iterator) {
991        if (iterator == null) {
992            throw new NullPointerException("Iterator must not be null");
993        }
994        return new IteratorEnumeration<>(iterator);
995    }
996
997    /**
998     * Gets an {@link Iterable} that wraps an iterator.  The returned {@link Iterable} can be
999     * used for a single iteration.
1000     *
1001     * @param <E> the element type
1002     * @param iterator  the iterator to use, may not be null
1003     * @return a new, single use {@link Iterable}
1004     * @throws NullPointerException if iterator is null
1005     */
1006    public static <E> Iterable<E> asIterable(final Iterator<? extends E> iterator) {
1007        if (iterator == null) {
1008            throw new NullPointerException("Iterator must not be null");
1009        }
1010        return new IteratorIterable<>(iterator, false);
1011    }
1012
1013    /**
1014     * Gets an iterable that wraps an iterator.  The returned iterable can be
1015     * used for multiple iterations.
1016     *
1017     * @param <E> the element type
1018     * @param iterator  the iterator to use, may not be null
1019     * @return a new, multiple use iterable
1020     * @throws NullPointerException if iterator is null
1021     */
1022    public static <E> Iterable<E> asMultipleUseIterable(final Iterator<? extends E> iterator) {
1023        if (iterator == null) {
1024            throw new NullPointerException("Iterator must not be null");
1025        }
1026        return new IteratorIterable<>(iterator, true);
1027    }
1028
1029    /**
1030     * Gets a list iterator based on a simple iterator.
1031     * <p>
1032     * As the wrapped Iterator is traversed, a LinkedList of its values is
1033     * cached, permitting all required operations of ListIterator.
1034     *
1035     * @param <E> the element type
1036     * @param iterator  the iterator to use, may not be null
1037     * @return a new iterator
1038     * @throws NullPointerException if iterator parameter is null
1039     */
1040    public static <E> ListIterator<E> toListIterator(final Iterator<? extends E> iterator) {
1041        if (iterator == null) {
1042            throw new NullPointerException("Iterator must not be null");
1043        }
1044        return new ListIteratorWrapper<>(iterator);
1045    }
1046
1047    /**
1048     * Gets an array based on an iterator.
1049     * <p>
1050     * As the wrapped Iterator is traversed, an ArrayList of its values is
1051     * created. At the end, this is converted to an array.
1052     *
1053     * @param iterator  the iterator to use, not null
1054     * @return an array of the iterator contents
1055     * @throws NullPointerException if iterator parameter is null
1056     */
1057    public static Object[] toArray(final Iterator<?> iterator) {
1058        if (iterator == null) {
1059            throw new NullPointerException("Iterator must not be null");
1060        }
1061        final List<?> list = toList(iterator, 100);
1062        return list.toArray();
1063    }
1064
1065    /**
1066     * Gets an array based on an iterator.
1067     * <p>
1068     * As the wrapped Iterator is traversed, an ArrayList of its values is
1069     * created. At the end, this is converted to an array.
1070     *
1071     * @param <E> the element type
1072     * @param iterator  the iterator to use, not null
1073     * @param arrayClass  the class of array to create
1074     * @return an array of the iterator contents
1075     * @throws NullPointerException if iterator parameter or arrayClass is null
1076     * @throws ArrayStoreException if the arrayClass is invalid
1077     */
1078    public static <E> E[] toArray(final Iterator<? extends E> iterator, final Class<E> arrayClass) {
1079        if (iterator == null) {
1080            throw new NullPointerException("Iterator must not be null");
1081        }
1082        if (arrayClass == null) {
1083            throw new NullPointerException("Array class must not be null");
1084        }
1085        final List<E> list = toList(iterator, 100);
1086        @SuppressWarnings("unchecked")
1087        final E[] array = (E[]) Array.newInstance(arrayClass, list.size());
1088        return list.toArray(array);
1089    }
1090
1091    /**
1092     * Gets a list based on an iterator.
1093     * <p>
1094     * As the wrapped Iterator is traversed, an ArrayList of its values is
1095     * created. At the end, the list is returned.
1096     *
1097     * @param <E> the element type
1098     * @param iterator  the iterator to use, not null
1099     * @return a list of the iterator contents
1100     * @throws NullPointerException if iterator parameter is null
1101     */
1102    public static <E> List<E> toList(final Iterator<? extends E> iterator) {
1103        return toList(iterator, 10);
1104    }
1105
1106    /**
1107     * Gets a list based on an iterator.
1108     * <p>
1109     * As the wrapped Iterator is traversed, an ArrayList of its values is
1110     * created. At the end, the list is returned.
1111     *
1112     * @param <E> the element type
1113     * @param iterator  the iterator to use, not null
1114     * @param estimatedSize  the initial size of the ArrayList
1115     * @return a list of the iterator contents
1116     * @throws NullPointerException if iterator parameter is null
1117     * @throws IllegalArgumentException if the size is less than 1
1118     */
1119    public static <E> List<E> toList(final Iterator<? extends E> iterator, final int estimatedSize) {
1120        if (iterator == null) {
1121            throw new NullPointerException("Iterator must not be null");
1122        }
1123        if (estimatedSize < 1) {
1124            throw new IllegalArgumentException("Estimated size must be greater than 0");
1125        }
1126        final List<E> list = new ArrayList<>(estimatedSize);
1127        while (iterator.hasNext()) {
1128            list.add(iterator.next());
1129        }
1130        return list;
1131    }
1132
1133    /**
1134     * Gets a suitable Iterator for the given object.
1135     * <p>
1136     * This method can handle objects as follows
1137     * <ul>
1138     * <li>null - empty iterator
1139     * <li>Iterator - returned directly
1140     * <li>Enumeration - wrapped
1141     * <li>Collection - iterator from collection returned
1142     * <li>Map - values iterator returned
1143     * <li>Dictionary - values (elements) enumeration returned as iterator
1144     * <li>array - iterator over array returned
1145     * <li>object with iterator() public method accessed by reflection
1146     * <li>object - singleton iterator
1147     * <li>NodeList - iterator over the list
1148     * <li>Node - iterator over the child nodes
1149     * </ul>
1150     *
1151     * @param obj  the object to convert to an iterator
1152     * @return a suitable iterator, never null
1153     */
1154    public static Iterator<?> getIterator(final Object obj) {
1155        if (obj == null) {
1156            return emptyIterator();
1157        }
1158        if (obj instanceof Iterator) {
1159            return (Iterator<?>) obj;
1160        }
1161        if (obj instanceof Iterable) {
1162            return ((Iterable<?>) obj).iterator();
1163        }
1164        if (obj instanceof Object[]) {
1165            return new ObjectArrayIterator<>((Object[]) obj);
1166        }
1167        if (obj instanceof Enumeration) {
1168            return new EnumerationIterator<>((Enumeration<?>) obj);
1169        }
1170        if (obj instanceof Map) {
1171            return ((Map<?, ?>) obj).values().iterator();
1172        }
1173        if (obj instanceof NodeList) {
1174            return new NodeListIterator((NodeList) obj);
1175        }
1176        if (obj instanceof Node) {
1177            return new NodeListIterator((Node) obj);
1178        }
1179        if (obj instanceof Dictionary) {
1180            return new EnumerationIterator<>(((Dictionary<?, ?>) obj).elements());
1181        } else if (obj.getClass().isArray()) {
1182            return new ArrayIterator<>(obj);
1183        }
1184        try {
1185            final Method method = obj.getClass().getMethod("iterator", (Class[]) null);
1186            if (Iterator.class.isAssignableFrom(method.getReturnType())) {
1187                final Iterator<?> it = (Iterator<?>) method.invoke(obj, (Object[]) null);
1188                if (it != null) {
1189                    return it;
1190                }
1191            }
1192        } catch (final RuntimeException e) { // NOPMD
1193            // ignore
1194        } catch (final NoSuchMethodException e) { // NOPMD
1195            // ignore
1196        } catch (final IllegalAccessException e) { // NOPMD
1197            // ignore
1198        } catch (final InvocationTargetException e) { // NOPMD
1199            // ignore
1200        }
1201        return singletonIterator(obj);
1202    }
1203
1204    // Utility methods
1205    //-----------------------------------------------------------------------
1206
1207    /**
1208     * Applies the closure to each element of the provided iterator.
1209     *
1210     * @param <E> the element type
1211     * @param iterator  the iterator to use, may be null
1212     * @param closure  the closure to apply to each element, may not be null
1213     * @throws NullPointerException if closure is null
1214     * @since 4.1
1215     */
1216    public static <E> void forEach(final Iterator<E> iterator, final Closure<? super E> closure) {
1217        if (closure == null) {
1218            throw new NullPointerException("Closure must not be null");
1219        }
1220
1221        if (iterator != null) {
1222            while (iterator.hasNext()) {
1223                final E element = iterator.next();
1224                closure.execute(element);
1225            }
1226        }
1227    }
1228
1229    /**
1230     * Executes the given closure on each but the last element in the iterator.
1231     * <p>
1232     * If the input iterator is null no change is made.
1233     *
1234     * @param <E> the type of object the {@link Iterator} contains
1235     * @param iterator  the iterator to get the input from, may be null
1236     * @param closure  the closure to perform, may not be null
1237     * @return the last element in the iterator, or null if iterator is null or empty
1238     * @throws NullPointerException if closure is null
1239     * @since 4.1
1240     */
1241    public static <E> E forEachButLast(final Iterator<E> iterator, final Closure<? super E> closure) {
1242        if (closure == null) {
1243            throw new NullPointerException("Closure must not be null.");
1244        }
1245        if (iterator != null) {
1246            while (iterator.hasNext()) {
1247                final E element = iterator.next();
1248                if (iterator.hasNext()) {
1249                    closure.execute(element);
1250                } else {
1251                    return element;
1252                }
1253            }
1254        }
1255        return null;
1256    }
1257
1258    /**
1259     * Finds the first element in the given iterator which matches the given predicate.
1260     * <p>
1261     * A <code>null</code> or empty iterator returns null.
1262     *
1263     * @param <E> the element type
1264     * @param iterator  the iterator to search, may be null
1265     * @param predicate  the predicate to use, may not be null
1266     * @return the first element of the iterator which matches the predicate or null if none could be found
1267     * @throws NullPointerException if predicate is null
1268     * @since 4.1
1269     */
1270    public static <E> E find(final Iterator<E> iterator, final Predicate<? super E> predicate) {
1271        if (predicate == null) {
1272            throw new NullPointerException("Predicate must not be null");
1273        }
1274
1275        if (iterator != null) {
1276            while (iterator.hasNext()) {
1277                final E element = iterator.next();
1278                if (predicate.evaluate(element)) {
1279                    return element;
1280                }
1281            }
1282        }
1283        return null;
1284    }
1285
1286    /**
1287     * Returns the index of the first element in the specified iterator that
1288     * matches the given predicate.
1289     * <p>
1290     * A <code>null</code> or empty iterator returns -1.
1291     *
1292     * @param <E> the element type
1293     * @param iterator  the iterator to search, may be null
1294     * @param predicate  the predicate to use, may not be null
1295     * @return the index of the first element which matches the predicate or -1 if none matches
1296     * @throws NullPointerException if predicate is null
1297     * @since 4.1
1298     */
1299    public static <E> int indexOf(final Iterator<E> iterator, final Predicate<? super E> predicate) {
1300        if (predicate == null) {
1301            throw new NullPointerException("Predicate must not be null");
1302        }
1303
1304        if (iterator != null) {
1305            for(int index = 0; iterator.hasNext(); index++) {
1306                final E element = iterator.next();
1307                if (predicate.evaluate(element)) {
1308                    return index;
1309                }
1310            }
1311        }
1312        return -1;
1313    }
1314
1315    /**
1316     * Answers true if a predicate is true for any element of the iterator.
1317     * <p>
1318     * A <code>null</code> or empty iterator returns false.
1319     *
1320     * @param <E> the type of object the {@link Iterator} contains
1321     * @param iterator  the {@link Iterator} to use, may be null
1322     * @param predicate  the predicate to use, may not be null
1323     * @return true if any element of the collection matches the predicate, false otherwise
1324     * @throws NullPointerException if predicate is null
1325     * @since 4.1
1326     */
1327    public static <E> boolean matchesAny(final Iterator<E> iterator, final Predicate<? super E> predicate) {
1328        return indexOf(iterator, predicate) != -1;
1329    }
1330
1331    /**
1332     * Answers true if a predicate is true for every element of an iterator.
1333     * <p>
1334     * A <code>null</code> or empty iterator returns true.
1335     *
1336     * @param <E> the type of object the {@link Iterator} contains
1337     * @param iterator  the {@link Iterator} to use, may be null
1338     * @param predicate  the predicate to use, may not be null
1339     * @return true if every element of the collection matches the predicate or if the
1340     *   collection is empty, false otherwise
1341     * @throws NullPointerException if predicate is null
1342     * @since 4.1
1343     */
1344    public static <E> boolean matchesAll(final Iterator<E> iterator, final Predicate<? super E> predicate) {
1345        if (predicate == null) {
1346            throw new NullPointerException("Predicate must not be null");
1347        }
1348
1349        if (iterator != null) {
1350            while (iterator.hasNext()) {
1351                final E element = iterator.next();
1352                if (!predicate.evaluate(element)) {
1353                    return false;
1354                }
1355            }
1356        }
1357        return true;
1358    }
1359
1360    /**
1361     * Checks if the given iterator is empty.
1362     * <p>
1363     * A <code>null</code> or empty iterator returns true.
1364     *
1365     * @param iterator  the {@link Iterator} to use, may be null
1366     * @return true if the iterator is exhausted or null, false otherwise
1367     * @since 4.1
1368     */
1369    public static boolean isEmpty(final Iterator<?> iterator) {
1370        return iterator == null || !iterator.hasNext();
1371    }
1372
1373    /**
1374     * Checks if the object is contained in the given iterator.
1375     * <p>
1376     * A <code>null</code> or empty iterator returns false.
1377     *
1378     * @param <E> the type of object the {@link Iterator} contains
1379     * @param iterator  the iterator to check, may be null
1380     * @param object  the object to check
1381     * @return true if the object is contained in the iterator, false otherwise
1382     * @since 4.1
1383     */
1384    public static <E> boolean contains(final Iterator<E> iterator, final Object object) {
1385        return matchesAny(iterator, EqualPredicate.equalPredicate(object));
1386    }
1387
1388    /**
1389     * Returns the <code>index</code>-th value in {@link Iterator}, throwing
1390     * <code>IndexOutOfBoundsException</code> if there is no such element.
1391     * <p>
1392     * The Iterator is advanced to <code>index</code> (or to the end, if
1393     * <code>index</code> exceeds the number of entries) as a side effect of this method.
1394     *
1395     * @param <E> the type of object in the {@link Iterator}
1396     * @param iterator  the iterator to get a value from
1397     * @param index  the index to get
1398     * @return the object at the specified index
1399     * @throws IndexOutOfBoundsException if the index is invalid
1400     * @since 4.1
1401     */
1402    public static <E> E get(final Iterator<E> iterator, final int index) {
1403        int i = index;
1404        CollectionUtils.checkIndexBounds(i);
1405        while (iterator.hasNext()) {
1406            i--;
1407            if (i == -1) {
1408                return iterator.next();
1409            }
1410            iterator.next();
1411        }
1412        throw new IndexOutOfBoundsException("Entry does not exist: " + i);
1413    }
1414
1415    /**
1416     * Shortcut for {@code get(iterator, 0)}.
1417     * <p>
1418     * Returns the <code>first</code> value in {@link Iterator}, throwing
1419     * <code>IndexOutOfBoundsException</code> if there is no such element.
1420     * </p>
1421     * <p>
1422     * The Iterator is advanced to <code>0</code> (or to the end, if
1423     * <code>0</code> exceeds the number of entries) as a side effect of this method.
1424     * </p>
1425     * @param <E> the type of object in the {@link Iterator}
1426     * @param iterator the iterator to get a value from
1427     * @return the first object
1428     * @throws IndexOutOfBoundsException if the request is invalid
1429     * @since 4.2
1430     */
1431    public static <E> E first(final Iterator<E> iterator) {
1432        return get(iterator, 0);
1433    }
1434
1435    /**
1436     * Returns the number of elements contained in the given iterator.
1437     * <p>
1438     * A <code>null</code> or empty iterator returns {@code 0}.
1439     *
1440     * @param iterator  the iterator to check, may be null
1441     * @return the number of elements contained in the iterator
1442     * @since 4.1
1443     */
1444    public static int size(final Iterator<?> iterator) {
1445        int size = 0;
1446        if (iterator != null) {
1447            while (iterator.hasNext()) {
1448                iterator.next();
1449                size++;
1450            }
1451        }
1452        return size;
1453    }
1454
1455    /**
1456     * Returns a string representation of the elements of the specified iterator.
1457     * <p>
1458     * The string representation consists of a list of the iterator's elements,
1459     * enclosed in square brackets ({@code "[]"}). Adjacent elements are separated
1460     * by the characters {@code ", "} (a comma followed by a space). Elements are
1461     * converted to strings as by {@code String.valueOf(Object)}.
1462     *
1463     * @param <E> the element type
1464     * @param iterator  the iterator to convert to a string, may be null
1465     * @return a string representation of {@code iterator}
1466     * @since 4.1
1467     */
1468    public static <E> String toString(final Iterator<E> iterator) {
1469        return toString(iterator, TransformerUtils.stringValueTransformer(),
1470                        DEFAULT_TOSTRING_DELIMITER, DEFAULT_TOSTRING_PREFIX,
1471                        DEFAULT_TOSTRING_SUFFIX);
1472    }
1473
1474    /**
1475     * Returns a string representation of the elements of the specified iterator.
1476     * <p>
1477     * The string representation consists of a list of the iterable's elements,
1478     * enclosed in square brackets ({@code "[]"}). Adjacent elements are separated
1479     * by the characters {@code ", "} (a comma followed by a space). Elements are
1480     * converted to strings as by using the provided {@code transformer}.
1481     *
1482     * @param <E> the element type
1483     * @param iterator  the iterator to convert to a string, may be null
1484     * @param transformer  the transformer used to get a string representation of an element
1485     * @return a string representation of {@code iterator}
1486     * @throws NullPointerException if {@code transformer} is null
1487     * @since 4.1
1488     */
1489    public static <E> String toString(final Iterator<E> iterator,
1490                                      final Transformer<? super E, String> transformer) {
1491        return toString(iterator, transformer, DEFAULT_TOSTRING_DELIMITER,
1492                        DEFAULT_TOSTRING_PREFIX, DEFAULT_TOSTRING_SUFFIX);
1493    }
1494
1495    /**
1496     * Returns a string representation of the elements of the specified iterator.
1497     * <p>
1498     * The string representation consists of a list of the iterator's elements,
1499     * enclosed by the provided {@code prefix} and {@code suffix}. Adjacent elements
1500     * are separated by the provided {@code delimiter}. Elements are converted to
1501     * strings as by using the provided {@code transformer}.
1502     *
1503     * @param <E> the element type
1504     * @param iterator  the iterator to convert to a string, may be null
1505     * @param transformer  the transformer used to get a string representation of an element
1506     * @param delimiter  the string to delimit elements
1507     * @param prefix  the prefix, prepended to the string representation
1508     * @param suffix  the suffix, appended to the string representation
1509     * @return a string representation of {@code iterator}
1510     * @throws NullPointerException if either transformer, delimiter, prefix or suffix is null
1511     * @since 4.1
1512     */
1513    public static <E> String toString(final Iterator<E> iterator,
1514                                      final Transformer<? super E, String> transformer,
1515                                      final String delimiter,
1516                                      final String prefix,
1517                                      final String suffix) {
1518        if (transformer == null) {
1519            throw new NullPointerException("transformer may not be null");
1520        }
1521        if (delimiter == null) {
1522            throw new NullPointerException("delimiter may not be null");
1523        }
1524        if (prefix == null) {
1525            throw new NullPointerException("prefix may not be null");
1526        }
1527        if (suffix == null) {
1528            throw new NullPointerException("suffix may not be null");
1529        }
1530        final StringBuilder stringBuilder = new StringBuilder(prefix);
1531        if (iterator != null) {
1532            while (iterator.hasNext()) {
1533                final E element = iterator.next();
1534                stringBuilder.append(transformer.transform(element));
1535                stringBuilder.append(delimiter);
1536            }
1537            if(stringBuilder.length() > prefix.length()) {
1538                stringBuilder.setLength(stringBuilder.length() - delimiter.length());
1539            }
1540        }
1541        stringBuilder.append(suffix);
1542        return stringBuilder.toString();
1543    }
1544
1545}