package extensions.util;
import java.util.*;

/**
  * Smalltalk styled select enumeration.
  * When the accept() method is not override to act
  * as a filter, Select selects all elements of
  * the Enumeration supplied thus acting as simply
  * an Enumeration isolator, i.e. the original collection
  * can change elements that the original enumeration was
  * based on without effecting the Select "all" enumeration!
  * @version 1.0.2
  * @author John Webster Small
  */
public class Select implements Enumeration
{
  private int idx;
  private Vector v;
  private Enumeration candidates;
  private boolean reject;

  /** Override to define select block.
    * @return returns true if candidate is acceptable
    */
  protected boolean accept(Object candidate)
    { return true; }  // Selects all elements by default

  /** Call from your overridden constructor. */
  protected void init()
  {
    Object c;
    if (reject)  {
      while (candidates.hasMoreElements())
        if (!accept(c = candidates.nextElement()))
          v.addElement(c);
    }
    else  {
      while (candidates.hasMoreElements())
        if (accept(c = candidates.nextElement()))
          v.addElement(c);
    }
    v.trimToSize();
  }

  /** Make selection of candidates based on accept().
    * @see #accept
    * @param candidates choose from among these
    * @param reject negative the sense of accept()
    */
  public Select(Enumeration candidates, boolean reject)
  {
    idx = 0;
    v = new Vector();
    this.candidates = candidates;
    this.reject = reject;
  }

  /** Make selection of candidates based on accept().
    * @see #accept
    * @param candidates choose from among these
    */
  public Select(Enumeration candidates)
    { this(candidates,false); }

  /**
    * @return true if this enumeration
    * contains more elements, false otherwise.
    */
  public final boolean hasMoreElements()
    { return idx < v.size(); }

  /**
    * @return the next element of this enumeration
    * @exception NoSuchElementException if no more elements exist
    */
  public final Object nextElement()
    {
      try {
        return v.elementAt(idx++);
      } catch (Exception e)  {
        throw new NoSuchElementException
          ("Select");
      }
    }
}
