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