/**
 * An implementation of "expandable" arrays.  Intented to help us
 * better understand java.util.Vector (and to give us confidence that
 * we could write that class if we had to).
 *
 * @author Yvonne Palm
 * @author Samuel A. Rebelsky
 * @version 1.0 of September 2003
 */
public class MyVector
{
  // +-----------+-----------------------------------------------
  // | Constants |
  // +-----------+

  /**
   * The default starting capacity.
   */
  public static final int INITIAL_CAPACITY = 5;


  // +--------+--------------------------------------------------
  // | Fields |
  // +--------+

  /** 
   * The contents of the vector.
   */
  Object[] contents;

  /**
   * The number of elements in the vector.
   */
  int length;

  // +--------------+--------------------------------------------
  // | Constructors |
  // +--------------+

  /** Build a new vector. */
  public MyVector()
  {
    this.contents = new Object[INITIAL_CAPACITY];
    this.length = 0;
  } // MyVector()

  // +------------------+----------------------------------------
  // | Exported Methods |
  // +------------------+

  /** Add an element to the end of the vector. */
  public void add(Object newValue)
  {
    // Make sure there's enough space!
    if (this.contents.length == this.length) {
      expandToSize(2*this.contents.length);
    }
    // Put the object in the length position
    this.contents[this.length] = newValue;
    // The length increases by one.
    this.length++;
  } // add(Object)

  /** 
   * Set an element within the vector. 
   * Set any undefined elements to 0.
   */
  public void set(int pos, Object value)
  {
    // If the new element fits in the existing array
    if (pos < this.contents.length) {
      // Set the value at the particular position
      this.contents[pos] = value;
      // Update the length, if appropriate.
      if (pos >= this.length) {
        this.length = pos+1;
      }
    } // If the new element fits in the existing array
    else { // The new element does not fit
      // Expand the array
      expandToSize(pos+5);  // yeah, 5 is completely arbitrary
      // Set the value.
      this.contents[pos] = value;
      // Update the length.
      this.length = pos+1;
    } // The new element does not fit
  } // set(int, Object)

  /** Get an element at a specified position. */
  public Object get(int pos)
  {
    if ((pos >= 0) && (pos < this.contents.length)) {
     return this.contents[pos];
   }
   else {
     return null;
   }
  } // get(int)

  /** Determine the length of a vector. */
  public int length()
  {
    return this.length;  
  } // length()

  /** Convert this vector to a string for testing. */
  public String toString()
  {
    if (0 == this.length) { return "[]"; }
    String result = "[" + this.contents[0];
    for (int i = 1; i < this.length; i++) {
      result = result + "," + this.contents[i];
    }
    return result + "]";
  } // toString()


  // +---------------+-------------------------------------------
  // | Local Methods |
  // +---------------+

  /**
   * Expand the internal representation to the given size.
   */
  private void expandToSize(int newSize)
  {
    // Create a bigger array.
    Object[] temp = new Object[newSize];
    // Copy the elements into the new array.
    for (int i = 0; i < this.contents.length; i++) {
      temp[i] = this.contents[i];
    } // for
    // Make contents refer to this array
    this.contents = temp;
  } // expandToSize(int)

} // class MyVector
