package com.mindprod.business;

import java.util.ListIterator;
import java.util.NoSuchElementException;

/**
 * A Fancier ArrayIterator that implements ListIterator.
 * Iterator for iterating over an array of <code>Object</code>s.
 * The {@link #remove()} and {@link #add(Object)} methods are unsupported,
 * use an ArrayList for these operations.
 * @author Boudewijn Dijkstra <usenet@bdijkstra.tmfweb.nl>
 */
public class ArrayIterator implements ListIterator
   {

   /** The array over which is being iterated. */
   protected Object[] array;

   /** The length of the array is buffered here. */
   protected int length;

   /**
    * This member is used to keep track of the cursor of the iterator.
    * When iterating, it is used to obtain an index into the array.
    */
   protected int cursor;

   /** The index of the last returned element is stored here, for use in  set(Object). */
   protected int lastIndex;

   public ArrayIterator(Object[] array)
      {
      this.array = array;
      length = array.length;
      cursor = -1; // don't know initial direction
      lastIndex = -1;
      }

   public boolean hasNext()
      {
      if ( cursor == -1 )
         return length > 0;
      return cursor < length;
      }

   public Object next()
      {
      int cursor = this.cursor;
      if ( cursor == -1 )
         cursor = 0;
      try
         {
         Object o = array[cursor];
         lastIndex = cursor;
         this.cursor = cursor + 1; // post-increment
         return o;
         }
      catch ( ArrayIndexOutOfBoundsException aioobe )
         {
         NoSuchElementException rethrow
         = new NoSuchElementException( "ArrayIndexOutOfBoundsException" );
         rethrow.initCause(aioobe);
         throw rethrow;
         }
      }

   public boolean hasPrevious()
      {
      if ( cursor == -1 )
         return length > 0;
      return cursor > 0;
      }

   public Object previous()
      {
      int cursor = this.cursor;
      if ( cursor == -1 )
         cursor = length;
      try
         {
         Object o = array[--cursor]; // pre-decrement
         lastIndex = cursor;
         this.cursor = cursor;
         return o;
         }
      catch ( ArrayIndexOutOfBoundsException aioobe )
         {
         NoSuchElementException rethrow = new
                                          NoSuchElementException( "ArrayIndexOutOfBoundsException" );
         rethrow.initCause(aioobe);
         throw rethrow;
         }
      }

   public int nextIndex()
      {
      return lastIndex + 1;
      }

   public int previousIndex()
      {
      return lastIndex - 1;
      }

   // unsupported
   public void remove()
      {
      throw new UnsupportedOperationException( "Size of array is fixed" );
      }

   public void set(Object o)
      {
      try
         {
         array[lastIndex] = o;
         }
      catch ( ArrayIndexOutOfBoundsException aioobe )
         {
         IllegalStateException rethrow =
         new IllegalStateException( "Neither next() nor previous() have been called" );
         rethrow.initCause(aioobe);
         throw rethrow;
         }
      }

   // unsupported
   public void add(Object o)
      {
      throw new UnsupportedOperationException( "Size of array is fixed" );
      }
   }