/**
 * This class exists to demonstrate how to access the guts of a class _using_
 * an inner class.  Note that this class does _not_ provide a get() method.
 * The _only_ way for callers to look at its data is via the iterator.  (This
 * is more restrictive than you probably want for many real classes -- you
 * usually want a get() method -- but it demonstrates how you can provide a
 * restrictive interface.)
 *
 * This is basically a wrapper around a fixed size int array that only allows
 * insertion of non-negative integers.
 *
 * @author <a href="mailto:terran@cs.unm.edu">Terran Lane</a>
 * @version 1.0
 */

import java.util.Iterator;

public class TableB implements TDRLTable {
  /**
   * Creates a <code>TableB</code> instance of the specified size.
   *
   * @param sz Table size to create.  Must be non-negative.
   * @throws IllegalArgumentException If <code>sz<=0</code>
   */
  public TableB(int sz) {
    if (sz<=0) {
      throw new IllegalArgumentException("Size must be >0");
    }
    _table=new int[sz];
  }

  public int size() { return _table.length; }

  public void put(int item, int idx) {
    if (idx<0 || idx>=size()) {
      throw new IllegalArgumentException("Idx must be in range " +
					 "0<=idx<size()");
    }
    if (item<0) {
      throw new IllegalArgumentException("TableA only stores " +
					 "non-negative integers");
    }
    _table[idx]=item;
  }

  public Iterator getIterator() {
    return new _innerIterator();
  }

  /* ******************** end of public interface ******************** */

  /** The actual data store */
  private int[] _table;

  /**
   * This inner class provides an Iterator implementation whose details are
   * enclosed within TableB.  By virtue of being an inner class, it has
   * direct access to the private contents of TableB.  By virtue of
   * implementing Iterator, it acts like an Iterator object with respect to
   * the rest of the universe.  Because it's private, only a TableB can
   * construct one of these things.
   */
  private class _innerIterator implements Iterator {
    public _innerIterator() {
      // note -- this size() call is actually TableB.size() of the instance
      // of TableB that created this particular _innerIterator.
      _currPtr=size()-1;
    }

    public boolean hasNext() {
      return _currPtr>=0;
    }

    public Object next() {
      return new Integer(_table[_currPtr--]);
    }

    public void remove() {
      throw new RuntimeException("Removing from TDRLTables not allowed.");
      // The following is the _correct_ exception to throw.  Doesn't compile
      // properly on my Mac -- not sure why...
      //    throw UnsupportedOperationException("Removing from TDRLTables " +
      //					"not allowed.");
    }

    /* *************** end of _innerIterator public interface ************ */
    private int _currPtr;
  }
}
