package lrs;

/**
 * Mutable linear recursive structure.
 <pre>
 * Visitor Pattern: Serves as a host capable of executing algorithms which are
 * visitors.
 </pre>
 * @author Dung X. Nguyen and Stephen Wong  Copyright 2005 - All rights reserved.
 * @since 8/25/05
 */
public class LRStruct {
    /**
     * The state of of this <code>LRStruct</code>.
     */
    private ANode _head;
    
    /**
     * Initializes this <code>LRStruct</code> to the empty state.
     */
    public LRStruct() {
        _head = EmptyNode.Singleton;
    }
    
    /**
     * Returns "()" if empty, otherwise returns the contents of this
     * <code>LRStruct</code> enclosed in parentheses.
     */
    public String toString()  {
        return _head.toString(this);
    }
    
    /**
     * Inserts dat to the front of this LRStruct.<br>
     * post condition: <code>getFirst()</code> now returns dat.
     * @param dat data to be inserted.
     * @return this <code>LRStruct</code>
     */
    public final LRStruct insertFront(Object dat) {
        return _head.insertFront(dat, this);
    }
    
    /**
     * Removes and returns this <code>LRStruct</code>'s first.
     */
    public final Object removeFront() {
        return _head.removeFront(this);
    }
    
    /**
     * Gets the first data element from this <code>LRStruct</code>
     */
    public final Object getFirst() {
        return _head.getFirst (this);
    }
    
    /**
     * Sets first data element to a new value.
     * @param dat replaces the existing first for this <code>LRStruct</code>.
     * @throws NoSuchElementException if this <code>LRStruct</code> is empty.
     * @return this <code>LRStruct</code>
     */
    public final LRStruct setFirst(Object dat) {
        return _head.setFirst (dat, this);
    }
    
    /**
     * Gets the rest of this <code>LRStruct</code>.
     * @throws NoSuchElementException if this <code>LRStruct</code> is empty.
     */
    public final LRStruct getRest() {
        return _head.getRest(this);
    }
    
    /**
     * Sets a new tail for this <code>LRStruct</code>.<br>
     * post condition: <code>getRest()</code> now returns tail.
     * @throws NoSuchElementException if this <code>LRStruct</code> is empty.
     * @return this <code>LRStruct</code>
     */
    public final LRStruct setRest(LRStruct tail) {
        return _head.setRest(tail, this);
    }
    
    /**
     * Hook method to execute an algorithm with a given input and return
     * an appropriate output object.
     * @param algo an algorithm (!= null) that operates on this LRStruct.
     * @param inp input variable argument list of objects needed by visitor algo.
     * @return output object resulting from the execution of algo.
     */
    public final Object execute(IAlgo algo, Object... inp) {
        return _head.execute(this, algo, inp);
    }
    
    /* Package access only: */
    
    /**
     * Initiazes this <code>LRStruct</code> with a given head node.
     * @param node != null.
     */
    LRStruct(ANode node)  {
        _head = node;
    }
    
    /**
     * Changes the head node (i.e. state) of this <code>LRStruct</code>.
     * @param head replaces the exisiting state of this <code>LRStruct</code>.
     * @return this <code>LRStruct</code>
     */
    final LRStruct setHead (ANode head) {
        _head = head;
        return this;
    }
    
    /**
     * Gets the head node (i.e. state) of this <code>LRStruct</code>.
     * @return the head node.
     */
    final ANode getHead () {
        return _head;
    }
}

