views:

42

answers:

2

I have an application with a very large TreeView control in Java. I want to get the contents of the tree control in a list (just strings not a JList) of XPath-like elements of leaves only. Here's an example root

|-Item1
  |-Item1.1
    |-Item1.1.1 (leaf)
  |-Item1.2 (leaf)
|-Item2
  |-Item2.1 (leaf)

Would output:

/Item1/Item1.1/Item1.1.1
/Item1/Item1.2
/Item2/Item2.1

I don't have any source code or anything handy like that. Is there I tool I can use to dig into the Window item itself and pull out this data? I don't mind if there are a few post-processing steps because typing it in by hand is my only other option.

+1  A: 

If we assume that you have a TreeModel (which you can get from a JTree using JTree.getModel()), then the following code would print out the leaves of the tree in the "/"-separated format that you are looking for:

/**
 * Prints the path to each leaf in the given tree to the console as a
 * "/"-separated string.
 * 
 * @param tree
 *          the tree to print
 */
private void printTreeLeaves(TreeModel tree) {
    printTreeLeavesRecursive(tree, tree.getRoot(), new LinkedList<Object>());
}

/**
 * Prints the path to each leaf in the given subtree of the given tree to
 * the console as a "/"-separated string.
 * 
 * @param tree
 *          the tree that is being printed
 * @param node
 *          the root of the subtree to print
 * @param path
 *          the path to the given node
 */
private void printTreeLeavesRecursive(TreeModel tree,
                                      Object node,
                                      List<Object> path) {
    if (tree.getChildCount(node) == 0) {
        for (final Object pathEntry : path) {
            System.out.print("/");
            System.out.print(pathEntry);
        }
        System.out.print("/");
        System.out.println(node);
    }
    else {
        for (int i = 0; i < tree.getChildCount(node); i++) {
            final List<Object> nodePath = new LinkedList<Object>(path);
            nodePath.add(node);
            printTreeLeavesRecursive(tree,
                                     tree.getChild(node, i),
                                     nodePath);
        }
    }
}

Of course, if you didn't just want to print the tree's contents to the console, you could replace the println statements with something else, such as output to a file or such as writing or appending to a Writer or a StringBuilder that is passed to these methods as an additional argument.

Joe Carnahan
+1  A: 

(I'm posting a second answer, depending on the interpretation of the question...)

If you already know what to do once you have a JTree and you're just trying to find the JTree component in an arbitrary Container (including any JComponent, Window, JFrame, etc.), then the following code will search the given Container and return the first JTree it finds (or null if no JTree can be found):

/**
 * Searches the component hierarchy of the given container and returns the
 * first {@link javax.swing.JTree} that it finds.
 * 
 * @param toSearch
 *          the container to search
 * @return the first tree found under the given container, or <code>null</code>
 *         if no {@link javax.swing.JTree} could be found
 */
private JTree findTreeInContainer(Container toSearch) {
    if (toSearch instanceof JTree) {
        return (JTree)toSearch;
    }
    else {
        for (final Component child : toSearch.getComponents()) {
            if (child instanceof Container) {
                JTree result = findTreeInContainer((Container)child);
                if (result != null) {
                    return result;
                }
            }
        }
        return null;
    }
}
Joe Carnahan