import Tree;
import TreeVertex;

/**
 * A node-based implementation of a vertex in a generic tree.
 *
 * @author Samuel A. Rebelsky
 * @version 1.0 of April 2000
 */
public class TreeNode
  implements TreeVertex
{
    // +--------+----------------------------------------
    // | Fields |
    // +--------+

    /** The contents. */
    protected Object contents;

    /** The parent.  Set to null when this vertex is the root. */
    protected TreeNode parent;

    /** 
     * The children.  Set to null when this vertex is a leaf. 
     * The vertex always has exactly children.length children. 
     */
    protected TreeNode[] children;

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

    /**
     * Build a new tree node with particular contents.
     */
    public TreeNode(Object contents) {
      this.contents = contents;
      this.children = null;
      this.parent = null;
    } // TreeNode(Object)

    // +------------+------------------------------------
    // | Extractors |
    // +------------+

    /**
     * Get a child.  The children are numbered starting
     * with 1.
     */
    public TreeVertex getChild(int childNum) {
      return this.children[childNum-1];
    } // getChild(int)

    /**
     * Get a parent.
     * Pre: Not the root.
     * Post: Returns the vertex of the parent.
     */
    public TreeVertex getParent() {
      return this.parent;
    } // getParent();

    /**
     * What values lurks at this vertex?
     */
    public Object getValue() {
      return this.contents;
    } // getValue();

    /**
     * Is the vertex a leaf of the tree?
     */
    public boolean isLeaf() {
      return (this.children == null);
    } // isLeaf()

    /**
     * Is the vertex the root of the tree?
     */
    public boolean isRoot() {
      return (this.parent == null);
    } // isRoot()

    /**
     * Determine how many children the vertex has.
     * Pre: None
     * Post: Returns the number of children.  Note
     *       that a leaf has 0 children.
     */
    public int numChildren() {
      if (this.children == null) return 0;
      else return this.children.length;
    } // numChildren()

    // +-----------+-------------------------------------
    // | Modifiers |
    // +-----------+

    /**
     * Add a new child.
     */
    public void addChild(Object newChild) {
      // Build the vertex for hte child.
      TreeNode childVertex = new TreeNode(newChild);
      childVertex.parent = this;
      // Special case: No children.  Make a new array.
      if (children == null) {
        this.children = new TreeNode[1];
        this.children[0] = childVertex;
      }
      // Normal case: Expand the array and add.
      else {
        TreeNode[] newChildren = 
          new TreeNode[this.children.length + 1];
        for (int i = 0; i < this.children.length; i++) {
          newChildren[i] = this.children[i];
        } // for
        newChildren[this.children.length] = childVertex;
        this.children = newChildren;
      } // if there's already a children array
    } // addChild(Object newChild)

    /**
     * Delete the ith child.
     * Pre: 1 <= childNum <= this.numChildren().
     * Post: One fewer child.
     */
    public void deleteChild(int childNum) {
        // Update for 0-based arrays
        childNum = childNum - 1;
        // Create the new child array
        TreeNode[] newChildren = 
            new TreeNode[this.children.length - 1];
        for (int i = 0; i < childNum; i++) {
            newChildren[i] = this.children[i];
        }
        for (int i = childNum+1; i < this.children.length; i++) {
            newChildren[i-1] = this.children[i];
        }
        this.children = newChildren;
    } // deleteChild(int)

    /**
     * Set the value associated with a vertex.  Changes
     * the whole dang tree.
     */
    public void setValue(Object newValue) {
      this.contents = newValue;
    } // setValue(Object)

} // interface TreeVertex

