
package brs;

/**
 * Stores data and represents a non-empty state.
 * @author Dung X. Nguyen - Copyright 2001 - All rights reserved.
 */
class DatNode extends ANode {
    /**
     * Data Invariant: != null.
     * @SBGen Variable (,left,,64)
     */
    private BiTree _leftTree = new BiTree ();
    /**
     * the stored data element.
     */
    private Object _dat;
    /**
     * Data Invariant: != null.
     * @SBGen Variable (,right,,64)
     */
    private BiTree _rightTree = new BiTree ();
    
    /**
     * Initialize the data element to a given object.
     * @param dat a given data object.
     */
    DatNode(Object dat) {
        _dat = dat;
    }
    
    
    /**
     * Gets the root data of the owner Tree.
     * @param owner the BiTree holding this DatNode.
     * @return the data element of this DatNode.
     */
    Object getRootDat(BiTree owner) {
        return _dat;
    }
    
    /**
     * Sets the data element of this node to a given data object.
     * @param dat a given data object.
     * @param owner the BiTree holding this DatNode.
     */
    void setRootDat(Object dat, BiTree owner) {
        _dat = dat;
    }
    
    /**
     * Gets the left subtree of the owner tree.
     * @param owner the BiTree holding this DatNode.
     * @return the left subtree of this DatNode.
     */
    BiTree getLeftSubTree(BiTree owner) {
        return _leftTree;
    }
    
    /**
     * Gets the right subtree of the owner tree.
     * @param owner the BiTree holding this DatNode.
     * @return the right subtree of this DatNode.
     */
    BiTree getRightSubTree(BiTree owner) {
        return _rightTree;
    }
    
    /**
     * Sets the left subtree of this Datnode to a given tree.
     * Allows for growing the owner tree.
     * @param biTree != null.  Does not check for null!
     * @param owner the BiTree holding this DatNode.
     */
    void setLeftSubTree(BiTree biTree, BiTree owner)  {
        _leftTree = biTree;
    }
    
    /**
     * Sets the right subtree of this node to a given tree.
     * Allows for growing the owner tree.
     * @param biTree != null.  Does not check for null!
     * @param owner the BiTree holding this DatNode.
     */
    void setRightSubTree(BiTree biTree, BiTree owner) {
        _rightTree = biTree;
    }
    
    /**
     * Throws an IllegalStateException because the owner tree is not empty.
     * @exception IllegaStateException.
     */
    void insertRoot(Object dat, BiTree owner) {
        throw new IllegalStateException ("DatNode.insertRoot().");
    }
    
    /**
     * Removes and returns the root element from the owner tree by asking the
     * left subtree and, if necessary, the right subtree to help do the job.
     * The subtrees help determine whether or not the root element can be removed
     * by executing appropriate anonymous visitors.
     * @param owner the BiTree holding this DatNode.  Why is it final?
     * @exception IllegaStateException if both subtrees of owner are non-empty.
     */
    Object remRoot(final BiTree owner) {
        return _leftTree.execute(new IVisitor() {
            /**
             * The left subtree is empty. The parent tree can simply become the
             * right subtree.
             */
            public Object emptyCase(BiTree host, Object... notUsed) {
                owner.setRootNode(_rightTree.getRootNode());
                return _dat;
                
            }
            
            /**
             * The left subtree is not empty!  The right subtree must determine
             * whether or not the parent root can be removed.
             */
            public Object nonEmptyCase(BiTree host, Object... inp) {
                return _rightTree.execute(new IVisitor() {
                    /**
                     * At this point both the lef and right subtrees are empty.
                     */
                    public Object emptyCase(BiTree h, Object... notUsed) {
                        owner.setRootNode(_leftTree.getRootNode());
                        return _dat;
                    }
                    
                    /**
                     * Both left and right subtrees are not empty!
                     * Cannot remove root!
                     */
                    public Object nonEmptyCase(BiTree h, Object... notUsed) {
                        throw new IllegalStateException ("Not a leaf.");
                    }
                });            }
        });
    }
    
    /**
     * Calls algo's nonEmptyCase() method to execute the algorithm algo.
     * @param algo an algorithm on owner.
     * @param inp the input algo needs.
     * @param owner the BiTree holding this DatNode.
     * @return the output for the nonEmptyCase() of algo.
     */
    Object execute(BiTree owner, IVisitor algo, Object... inp) {
        return algo.nonEmptyCase (owner, inp);
    }
}

