Brought to you by EarthWeb
ITKnowledge Logo Login Graphic Click to go to the Oscars.
Click to go to the Oscars.
ITKnowledge
Search this book:
 
Search the site:
 
EXPERT SEARCH ----- nav

EarthWeb Direct

EarthWeb Direct

EarthWeb sites: other sites

Previous Table of Contents Next


Tree Nodes

The JFC tree data structure defines two interfaces for tree nodes. The first, TreeNode, defines a static node. Once constructed and placed into a tree, this type of node cannot change its position in the tree or its children structure. The second interface is the MutableTreeNode interface. This type of node can be relocated in a tree, moved from one tree to another, and have its children structure change dynamically. These two interfaces are shown in Listing 11.4.

Listing 11.4 The TreeNode and MutableTreeNode Interfaces

public interface TreeNode
{
    /**
     * Returns the child <code>TreeNode</code> at index
     * <code>childIndex</code>.
     */
    TreeNode getChildAt(int childIndex);

    /**
     * Returns the number of children <code>TreeNode</code>s the receiver
     * contains.
     */
    int getChildCount();

    /**
     * Returns the parent <code>TreeNode</code> of the receiver.
     */
    TreeNode getParent();

    /**
     * Returns the index of <code>node</code> in the receiver’s children.
     * If the receiver does not contain <code>node</code>, -1 will be
     * returned.
     */
    int getIndex(TreeNode node);

    /**
     * Returns true if the receiver allows children.
     */
    boolean getAllowsChildren();

    /**
     * Returns true if the receiver is a leaf.
     */
    boolean isLeaf();

    /**
     * Returns the children of the receiver as an Enumeration.
     */
    Enumeration children();
}

public interface MutableTreeNode extends TreeNode
{
    /**
     * Adds <code>child</code> to the receiver at <code>index</code>.
     * <code>child</code> will be messaged with <code>setParent</code>.
     */
    void insert(MutableTreeNode child, int index);

    /**
     * Removes the child at <code>index</code> from the receiver.
     */
    void remove(int index);

    /**
     * Removes <code>node</code> from the receiver.
     * <code>setParent</code> will be messaged on <code>node</code>.

     */
    void remove(MutableTreeNode node);

    /**
     * Resets the user object of the receiver to <code>object</code>.
     */
    void setUserObject(Object object);

    /**
     * Removes the receiver from its parent.
     */
    void removeFromParent();

    /**
     * Sets the parent of the receiver to <code>newParent</code>.
     */
    void setParent(MutableTreeNode newParent);
}

The TreeNode interface defines a node that does not change its structure, or its location in the tree, for its lifetime. This type of node can still have children; it simply cannot dynamically add or remove children. The TreeNode class must be capable of returning its parent node in tree from the getParent method. However, the interface does not define a method for setting the parent. Thus, a class that implements TreeNode should take a reference to its parent in its constructor. The remainder of the methods defined in the TreeNode interface manages the node’s children. However, the interface doesn’t contain methods to create the children’s structure. Like the parent reference, the children can be specified in an implementation class’s constructor.

The MutableTreeNode interface extends the TreeNode interface. It adds methods to allow the node to change its location in the tree and the number of children it contains. The removeFromParent and setParent methods allow the node to be moved in the tree while leaving the node’s children unaltered. The insert and remove methods allow the children of the node to be dynamically added and removed. The final method defined in the MutableTreeNode interface, setUserObject, is a bit strange. The user object concept is sound; it allows the node to contain a reference to one object that is not interpreted by the node and that the application can use as it sees fit without having to keep another data structure mapping the user objects to the tree nodes. However, there is not a method to get the user object, so the application is out of luck trying to query the user object from the node.

Classes that implement the TreeNode interface can benefit from the user object reference just as much as those that implement the MutableTreeNode interface. To keep the TreeNode interface non-mutable, it should contain the getUserObject method and require the binding to be done at construction time. This would be similar to what is done with the parent reference at this time.

This apparent oddity can be explained by the fact that the JFC contains only one class that implements the node interfaces, the DefaultMutableTreeNode class. As its name implies, it implements the MutableTreeNode interface. This class defines a getUserObject method. It looks as though not containing this method in the TreeNode interface was an oversight by the JFC development team. It is unfortunate, though, because it forces a great deal of code to assume an implementation of the MutableTreeNode class, rather than the much more desirable condition of working at the interface level.

Internally, the DefaultMutableTreeNode class is the workhorse node class in the JFC. It is the lone tree node implementation in the tree package. It implements the MutableTreeNode interface. As such, it serves as a general-purpose tree node that can be dynamically altered in any way desired. Looking at the documentation for the DefaultMutableTreeNode class shows that its public API is far richer than that found in the MutableTreeNode interface. However, using the extra methods not defined in the interface ties your code to that implementation of the MutableTreeNode interface and makes it more difficult to incorporate new tree node implementations later.

When a DefaultMutableTreeNode instance has a non-null user object, its toString method is called when the toString method is called for the node. This allows the text in the tree to display the user object’s toString text. This class contains the getUserObject method that is not defined in either of the tree node interfaces.

The DefaultMutableTreeNode class contains many methods for querying the children and structure of the node. Many of these methods are generally applicable to a tree node and rely on the fact that the node is mutable. For example, the getLeafCount method returns the number of leaf instances that are descendants from the current node. This method is valid for non-mutable nodes as well as mutable nodes. It would have been desirable to split the rich API contained in the DefaultMutableTreeNode into two classes: a non-mutable version containing the static structure methods, and a mutable node that contains the mutation methods.


Previous Table of Contents Next
HomeAbout UsSearchSubscribeAdvertising InfoContact UsFAQs
Use of this site is subject to certain Terms & Conditions.
Copyright (c) 1996-1999 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.