package lrs;

/**
 * Represents the abstract list state. Has a concrete toString () method that
 * uses anynomous inner classes to compute the String representation of the
 * LRStruct owner.
 * @author Dung X. Nguyen and Stephen Wong  Copyright 2005 - All rights reserved.
 * @since 8/25/05
 * @stereotype abstract state
 */
abstract class ANode {
    /**
     * Uses anonymous visitor class to compute a String representation.
     */
    private static final IAlgo ToStringAlgo = new IAlgo() {
        private final IAlgo Helper = new IAlgo() {
            public Object emptyCase(LRStruct h, Object... i) {
                return ")";
            }
            
            public Object nonEmptyCase(LRStruct h, Object... i) {
                return " " + h.getFirst() + h.getRest().execute (this);
            }
        };
        
        public Object emptyCase(LRStruct host, Object... inp) {
            return "()";
        }
        
        public Object nonEmptyCase(LRStruct host, Object... inp) {
            return "(" + host.getFirst() + host.getRest().execute(Helper);
        }
    };
    
    String toString(LRStruct owner) {
        return (String)owner.execute (ToStringAlgo);
    }
    
    /**
     * Returns the tail LRStruct of the referencing LRStruct.
     * @param owner the LRStruct referencing this ANode.
     * @return the tail LRStruct of owner.
     * @throw java.util.NoSuchElementException if empty.
     */
    abstract LRStruct getRest(LRStruct owner);
    
    /**
     * Returns the first data object of the referencing LRStruct.
     * @param owner the LRStruct referencing this ANode.
     * @return the tail LRStruct of owner.
     * @throw java.util.NoSuchElementException if empty.
     */
    abstract Object getFirst(LRStruct owner);
    
    /**
     * Sets a new tail for the referencing LRStruct.
     * @param tail the new tail for the owner LRStruct.
     * @param owner the LRS referencing this ANode.
     * @throw java.util.NoSuchElementException if empty.
     * @return <code>LRStruct</code> owner
     */
    abstract LRStruct setRest(LRStruct tail, LRStruct owner);
    
    /**
     * Sets a new first data object for the referencing LRStruct.
     * @param first the new data object for this ANode.
     * @param owner the LRS referencing this ANode.
     * @throw java.util.NoSuchElementException if empty.
     * @return <code>LRStruct</code> owner
     */
    abstract LRStruct setFirst(Object dat, LRStruct owner);
    
    /**
     * Inserts a data object at the front of the LRStruct owner.
     * @param dat the object to be inserted at the front.
     * @param owner the LRS referencing this ANode.
     * @return <code>LRStruct</code> owner
     */
    abstract LRStruct insertFront(Object dat, LRStruct owner);
    
    /**
     * Removes and returns the first data object for the referencing LRStruct.
     * @param owner the LRS referencing this ANode.
     * @return the front data of the LRStruct owner.
     */
    abstract Object removeFront(LRStruct owner);
    
    /**
     * Executes a visitor algorithm and returns the output.
     * @param owner the LRStruct referencing this ANode.
     * @param algo the visitor algorithm to be executed.
     * @param inp the inputs needed by the algorithm.
     */
    abstract Object execute(LRStruct owner, IAlgo algo, Object... inp);
}

