001    
002    package brs;
003    
004    /**
005     * Models the binary tree structure using the state pattern and the visitor
006     * pattern. Provides only structural behaviors and a hook to execute any
007     * visitor algorithm.
008     * Exercise: Override the toString() method anonymous inner visitor classes.
009     * @author Dung X. Nguyen - Copyright 2002 - All rights reserved.
010     * @author Mathias Ricken - Copyright 2008 - All rights reserved.
011     */
012    public class BiTree<T> {
013        /**
014         * the state of this BiTree.
015         */
016        private ANode<T> _rootNode;
017    
018        /** Visitor to generate string representation. */
019        private ToString<T> _toString = new ToString<T>();
020        
021        /**
022        * Initializes this BiTree to the empty state.
023        */
024        public BiTree() {
025            _rootNode = new EmptyNode<T>();
026        }
027    
028        /**
029        * Gets the root data of this BiTree if it exists.
030        * @return the root data element of this BiTree if it exists.
031        * @exception NoSuchElementException if this BiTree is empty.
032        */
033        public T getRootDat() {
034            return _rootNode.getRootDat (this);
035        }
036    
037        /**
038        * Sets the root data element to a given object.
039        * @param dat the new root data.
040        * @exception NoSuchElementException if this BiTree is empty.
041        */
042        public void setRootDat(T dat) {
043            _rootNode.setRootDat (this, dat);
044        }
045    
046        /**
047        * Gets the left subtree of this BiTree if it exists.
048        * @return the left subtree of this BiTree if it exists.
049        * @exception NoSuchElementException if this BiTree is empty.
050        */
051        public BiTree<T> getLeftSubTree() {
052            return _rootNode.getLeftSubTree (this);
053        }
054    
055        /**
056        * Gets the right subtree of this BiTree if it exsists.
057        * @return the right subtree of this BiTree if it exists.
058        * @exception NoSuchElementException if this BiTree is empty.
059        */
060        public BiTree<T> getRightSubTree() {
061            return _rootNode.getRightSubTree (this);
062        }
063    
064        /**
065        * Attaches a new left subtree to the left of this BiTree, allowing this
066        * BiTree to grow to the left.
067        * @param biTree to replace the current left subtree.
068        * @exception NoSuchElementException if this BiTree is empty.
069        */
070        public void setLeftSubTree(BiTree<T> biTree) {
071            _rootNode.setLeftSubTree(this, biTree);
072        }
073    
074        /**
075        * Attaches a new right subtree to the left of this BiTree, allowing this
076        * BiTree to grow to the right.
077        * @param biTree to replace the current right subtree.
078        * @exception NoSuchElementException if this BiTree is empty.
079        */
080        public void setRightSubTree(BiTree<T> biTree) {
081            _rootNode.setRightSubTree(this, biTree);
082        }
083    
084        /**
085        * Inserts a root element to this BiTree.
086        * Allows for state change from empty to non-empty.
087        * @param dat the new root data.
088        * @exception IllegalStateException if this BiTree has more than one element.
089        */
090        public void insertRoot(T dat) {
091            _rootNode.insertRoot(this, dat);
092        }
093    
094        /**
095        * Removes and returns the root data element of this BiTree.
096        * @return the root data element of this BiTree.
097        * @exception NoSuchElementException if this BiTree is empty.
098        * @exception IllegalStateException if one of the subtrees is not empty.
099        */
100        public T remRoot() {
101            return _rootNode.remRoot(this);
102        }
103    
104        /**
105         * Hook to execute any algorithm that presents itself as a visitor to this
106         * BiTree.
107         * @param algo a visitor to a BiTree.
108         * @param inp the vararg input for the algo visitor.
109         * @return the output for the execution of algo.
110         */
111        public <R,P> R execute(IVisitor<T,R,P> algo, P... inp) {
112            return _rootNode.execute(this, algo, inp);
113        }
114    
115        public String toString () {
116            return (String)execute(_toString);
117        // EXERCISE FOR STUDENTS: The above line of code does not conform to the
118        // state pattern because it does not forward the request to the state.
119        // Rewrite the code to conform to the state pattern.  You will need to add
120        // appropriate methods to the states.  Review what we did with toString()
121        // for linear recursive structures.
122        }
123    
124        /**
125        * Changes this BiTree to a given new node (i.e. state).
126        * @param node a new root node (i.e.state) for this BiTree.
127        */
128        final void setRootNode(ANode<T> node) {
129            _rootNode = node;
130        }
131    
132        /**
133         * Returns the current node (i.e. state) of this BiTree.
134         * @return the current root node (state) of this BiTree.
135         */
136        final ANode<T> getRootNode() {
137            return _rootNode;
138        }
139    }