001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.compilers.opt.util;
014    
015    import java.util.Enumeration;
016    
017    
018    /**
019     *  This class is a generic tree.  It uses TreeNode and some enumeration
020     *  classes.
021     */
022    public class Tree {
023    
024      /**
025       *  A tree is simply a pointer to the root
026       */
027      private TreeNode root;
028    
029      /**
030       * constructor where the root is not initially known
031       */
032      public Tree() {
033        root = null;
034      }
035    
036      /**
037       * constructor where the root is initially known
038       * @param node  Root of the tree.
039       */
040      public Tree(TreeNode node) {
041        root = node;
042      }
043    
044      /**
045       * Is the tree empty?
046       * @return whether the tree is empty
047       */
048      public final boolean isEmpty() {
049        return root == null;
050      }
051    
052      /**
053       * Gets the root of the tree
054       * @return the root of the tree
055       */
056      public final TreeNode getRoot() {
057        return root;
058      }
059    
060      /**
061       * Sets the root of the tree to be the passed node.
062       * WARNING: the tree should be empty when this occurs
063       */
064      public final void setRoot(TreeNode node) {
065        node.clear();  // make sure all pointers are pointing anywhere else
066        root = node;
067      }
068    
069      /**
070       * Provides an undefined enumeration over all elements in the tree
071       * @return enumeration
072       */
073      public final Enumeration<TreeNode> elements() {
074        return new TreeTopDownEnumerator(root);
075      }
076    
077      /**
078       * Counts and returns the number of nodes
079       * @return the number of nodes.
080       */
081      public final int numberOfNodes() {
082        int n = 0;
083        if (root == null) return n;
084        for (Enumeration<TreeNode> e = elements(); e.hasMoreElements();) {
085          e.nextElement();
086          n++;
087        }
088        return n;
089      }
090    
091      /**
092       * Provides a bottom-up enumeration over all elements in the tree
093       * @return enumeration
094       */
095      public final Enumeration<TreeNode> getBottomUpEnumerator() {
096        return new TreeBottomUpEnumerator(root);
097      }
098    
099      /**
100       * Provides a top-down enumeration over all elements in the tree
101       * @return enumeration
102       */
103      public final Enumeration<TreeNode> getTopDownEnumerator() {
104        return new TreeTopDownEnumerator(root);
105      }
106    
107      /**
108       * Prints the tree
109       * @return the tree as a string
110       */
111      @Override
112      public final String toString() {
113        StringBuffer sb = new StringBuffer();
114    
115        // visit the nodes in a depth first traversal, printing the nodes
116        //  as they are visited, indenting by the depth of the traversal
117        sb = DFS(sb, root, 0);
118        return sb.toString();
119      }
120    
121      /**
122       * A preorder depth first traversal, printing node as visited
123       * @param sb  the string buffer to insert the results
124       * @param node the node to process
125       * @param depth the current depth (root = 0) in the tree
126       */
127      private StringBuffer DFS(StringBuffer sb, TreeNode node, int depth) {
128        // indent appropriate spaces and print node
129        for (int i = 0; i < 2 * depth; i++) {
130          sb.append(" ");
131        }
132        sb.append(node).append("\n");
133    
134        Enumeration<TreeNode> childEnum = node.getChildren();
135        while (childEnum.hasMoreElements()) {
136          TreeNode child = childEnum.nextElement();
137          DFS(sb, child, depth + 1);
138        }
139        return sb;
140      }
141    }