package org.jcon.util;

import java.util.Enumeration;
import java.util.Vector;
import javax.swing.tree.DefaultMutableTreeNode;

/**
 * Used to list a DefaultMutableTreeNode, such as TNode.
 * Designed for testing and debugging.
 *
 * @author Jack Harich
 */
public class TNodeList {

//---------- Private Fields ------------------------------
private DefaultMutableTreeNode root;
private int      indent = 4;

// Contains the root and all its nodes in hierarchial sequence.
private Vector sequenceNodes = new Vector();

//---------- Initialization ------------------------------
/**
 * Creates a TNodeList given a node to use for the root.
 * This node is usually the tree root.
 */
public TNodeList(DefaultMutableTreeNode root) {
    this.root = root;
}
//---------- Superclass Overrides ------------------------
/**
 * Provides a textural representation of the tree. This is
 * the main use of this class.
 */
public String toString() {
    String text = "";
    refresh();
    int nodeCount = getNodeCount();
    for (int i = 0; i < nodeCount; i++) {
        DefaultMutableTreeNode node = getNode(i);
        // Set prefix
        int level = node.getLevel(); // 0 if root
        int spaces = level * indent;
        String prefix = "";
        for (int j = 1; j <= spaces; j++) {
            prefix += " ";
        }
        // Set name
        String name = "";
        if (node.getUserObject() == null) {
            name = "ROOT";
        } else {
            name = node.getUserObject().toString();
        }
        // Accumulate line
        text += prefix + name + "\n";
    }
    text += "Total of " + nodeCount + " items in tree\n";
    return text;
}
//---------- Public Methods ------------------------------
/**
 * Call refresh() when the root's contents have changed,
 * such as when a new TNodeList is been created.
 */
public void refresh() {
    // Rebuild nodes Vector
    sequenceNodes.removeAllElements();
    addNodeChildren(root, sequenceNodes);
}
public int getNodeCount() {
    return sequenceNodes.size();
}
public DefaultMutableTreeNode getNode(int index) {
    return (DefaultMutableTreeNode)sequenceNodes.elementAt(index);
}
/**
 * Sets the number of spaces used for indentation. The
 * default is 4 spaces.
 */
public void setIndent(int indent) {
    this.indent = indent;
}
public int getIndent() {
    return indent;
}
//---------- Public Static Methods -----------------------
/**
 * A one liner that returns the hierarchial list given
 * the node to start listing at, which is usually the root.
 */
public static String listTree(DefaultMutableTreeNode root) {
    return new TNodeList(root).toString();
}
//---------- Private Methods -----------------------------
// RECURSIVE
private void addNodeChildren(DefaultMutableTreeNode node,
                                Vector nodes) {
    nodes.addElement(node);
    // Get children vector
    Vector children = new Vector();
    Enumeration enum = node.children();
    while (enum.hasMoreElements()) {
        children.addElement(enum.nextElement());
    }
    // Recursion stops if no children
    for (int i = 0; i < children.size(); i++) {
        DefaultMutableTreeNode child = (DefaultMutableTreeNode)children.elementAt(i);
        addNodeChildren(child, nodes);
    }
}
//--- Std
private static void print(String text) {
    System.out.println(text);
}

} // End class
