com.phoenixst.collections.FilteredIterator.java Source code

Java tutorial

Introduction

Here is the source code for com.phoenixst.collections.FilteredIterator.java

Source

/*
 *  $Id: FilteredIterator.java,v 1.7 2005/10/03 15:11:54 rconner Exp $
 *
 *  Copyright (C) 1994-2005 by Phoenix Software Technologists,
 *  Inc. and others.  All rights reserved.
 *
 *  THIS PROGRAM AND DOCUMENTATION IS PROVIDED UNDER THE TERMS OF THE
 *  COMMON PUBLIC LICENSE ("AGREEMENT") WHICH ACCOMPANIES IT.  ANY
 *  USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES
 *  RECIPIENT'S ACCEPTANCE OF THE AGREEMENT.
 *
 *  The license text can also be found at
 *    http://opensource.org/licenses/cpl.php
 */

package com.phoenixst.collections;

import java.util.*;

import org.apache.commons.collections.Predicate;

/**
 *  A filtered <code>Iterator</code>.  Because this class must advance
 *  the underlying <code>Iterator</code> to correctly implement {@link
 *  #hasNext()}, {@link #remove()} has unusual semantics.  See the
 *  javadocs for that method for details.
 *
 *  @version    $Revision: 1.7 $
 *  @author     Ray A. Conner
 *
 *  @since      1.0
 */
public class FilteredIterator implements Iterator {

    private final Iterator delegate;
    private final Predicate predicate;

    private Object current;
    private Object next;

    private boolean isCurrentValid = false;
    private boolean isNextValid = false;

    ////////////////////////////////////////
    // Constructors
    ////////////////////////////////////////

    /**
     *  Creates a new <code>FilteredIterator</code>.
     */
    public FilteredIterator(Iterator delegate, Predicate predicate) {
        super();
        this.delegate = delegate;
        this.predicate = predicate;
    }

    ////////////////////////////////////////
    // Iterator
    ////////////////////////////////////////

    public boolean hasNext() {
        if (!isNextValid) {
            while (delegate.hasNext()) {
                Object object = delegate.next();
                if (predicate.evaluate(object)) {
                    next = object;
                    isNextValid = true;
                    break;
                }
            }
        }
        return isNextValid;
    }

    public Object next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        current = next;
        isCurrentValid = true;
        isNextValid = false;
        return current;
    }

    /**
     *  Removes from the last object returned by {@link #next}.
     *  Because the underlying <code>Iterator</code> must be advanced
     *  to correctly implement {@link #hasNext}, this method has
     *  unusual semantics.  These are the possible states that an
     *  instance of this class may be in, and how this method will
     *  behave:
     *
     *  <UL>
     *
     *    <LI>If <code>next()</code> has not yet been called or
     *        <code>remove()</code> was called after the last call to
     *        <code>next()</code>, throws an
     *        <code>IllegalStateException</code>.  These are the same
     *        conditions under which any implementation of
     *        <code>Iterator.remove</code> should throw an exception.
     *
     *    <LI>If <code>next()</code> was called after the last calls
     *        to both <code>hasNext()</code> and <code>remove()</code>
     *        (if any), delegates to the <code>remove()</code> method
     *        of the underlying <code>Iterator</code>.
     *
     *    <LI>If <code>hasNext()</code> was called after the last
     *        calls to both <code>next()</code> and
     *        <code>remove()</code> (if any) and <code>remove()</code>
     *        has not been called after the last call to
     *        <code>next()</code>, calls {@link #remove(Object)
     *        remove( Object )} with the element last returned by
     *        <code>next()</code>.  In other words, the underlying
     *        <code>Iterator</code> has been advanced beyond the
     *        element to be removed.
     *
     *  </UL>
     *
     *  <P><b>Description copied from interface: {@link
     *  Iterator}</b><br> {@inheritDoc}
     */
    public void remove() {
        if (!isCurrentValid) {
            throw new IllegalStateException();
        }
        if (!isNextValid) {
            delegate.remove();
        } else {
            remove(current);
        }
        isCurrentValid = false;
    }

    /**
     *  This method is called by {@link #remove()} if
     *  <code>hasNext()</code> was called after the last calls to both
     *  <code>next()</code> and <code>remove()</code> (if any) and
     *  <code>remove()</code> has not been called after the last call
     *  to <code>next()</code>.  In other words, this method is called
     *  if the call sequence goes something like <code>next(),
     *  hasNext(), remove()</code>, which means the underlying
     *  <code>Iterator</code> has been advanced beyond the element to
     *  be removed.  This provides an extension point for an
     *  implementation to correctly handle this case if it is capable
     *  of doing so.
     *
     *  <P>This implementation throws an
     *  <code>IllegalStateException</code>.
     */
    protected void remove(Object object) {
        throw new IllegalStateException(
                "The remove() method cannot be called after hasNext()" + " without an intervening call to next().");
    }

}