/*
* (c) Copyright 2003, 2004, 2005, 2006, 2007 Hewlett-Packard Development
* Company, LP All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.enilink.commons.iterator;
import java.util.Enumeration;
import java.util.Iterator;
/**
* A WrappedIterator is an ExtendedIterator wrapping around a plain (or
* presented as plain) Iterator. The wrapping allows the usual extended
* operations (filtering, concatenating) to be done on an Iterator derived from
* some other source. <br>
*
*/
public class WrappedIterator<T> extends NiceIterator<T> {
private static class EnumerationIterator<E> implements Iterator<E> {
Enumeration<E> e;
private EnumerationIterator(Enumeration<E> e) {
this.e = e;
}
@Override
public boolean hasNext() {
return e.hasMoreElements();
}
@Override
public E next() {
return e.nextElement();
}
@Override
public void remove() {
throw new UnsupportedOperationException(
"Underlying enumeration does not support removal of elements");
}
}
/**
* set to <code>true</code> if this wrapping doesn't permit the use of
* .remove(). Otherwise the .remove() is delegated to the base iterator.
*/
protected boolean removeDenied;
/**
* Answer an ExtendedIterator returning the elements of <code>it</code>. If
* <code>it</code> is itself an ExtendedIterator, return that; otherwise
* wrap <code>it</code>.
*/
public static <T> IExtendedIterator<T> create(Iterator<T> it) {
return it instanceof IExtendedIterator<?> ? (IExtendedIterator<T>) it
: new WrappedIterator<T>(it, false);
}
/**
* Answer an ExtendedIterator returning the elements of <code>e</code>.
*/
public static <T> IExtendedIterator<T> create(Enumeration<T> e) {
return new WrappedIterator<T>(new EnumerationIterator<T>(e), false);
}
/**
* Answer an ExtendedIterator wrapped round <code>it</code> which does not
* permit <code>.remove()</code> even if <code>it</code> does.
*/
public static <T> WrappedIterator<T> createNoRemove(Iterator<T> it) {
return new WrappedIterator<T>(it, true);
}
/** the base iterator that we wrap */
protected final Iterator<? extends T> base;
/** constructor: remember the base iterator */
protected WrappedIterator(Iterator<? extends T> base) {
this(base, false);
}
/**
* Initialise this wrapping with the given base iterator and remove-control.
*
* @param base
* the base iterator that this tierator wraps
* @param removeDenied
* true if .remove() must throw an exception
*/
protected WrappedIterator(Iterator<? extends T> base, boolean removeDenied) {
this.base = base;
this.removeDenied = removeDenied;
}
/** hasNext: defer to the base iterator */
public boolean hasNext() {
return base.hasNext();
}
/** next: defer to the base iterator */
public T next() {
return base.next();
}
/**
* if .remove() is allowed, delegate to the base iterator's .remove;
* otherwise, throw an UnsupportedOperationException.
*/
public void remove() {
if (removeDenied)
throw new UnsupportedOperationException();
base.remove();
}
/** close: defer to the base, iff it is closable */
public void close() {
close(base);
}
/**
* if <code>it</code> is a Closableiterator, close it. Abstracts away from
* tests [that were] scattered through the code.
*/
public static void close(Iterator<?> it) {
NiceIterator.close(it);
}
}