DOMTreeWalkerTreeModel.java Source code

Java tutorial

Introduction

Here is the source code for DOMTreeWalkerTreeModel.java

Source

/*
 * Copyright (c) 2000 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 2nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book (recommended),
 * visit http://www.davidflanagan.com/javaexamples2.
 */

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.TreeWalker;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import org.apache.xerces.internal.parsers.DOMParser;

/**
 * This class implements the Swing TreeModel interface so that the DOM tree
 * returned by a TreeWalker can be displayed in a JTree component.
 */
public class DOMTreeWalkerTreeModel implements TreeModel {
    TreeWalker walker; // The TreeWalker we're modeling for JTree

    /** Create a TreeModel for the specified TreeWalker */
    public DOMTreeWalkerTreeModel(TreeWalker walker) {
        this.walker = walker;
    }

    /**
     * Create a TreeModel for a TreeWalker that returns all nodes in the
     * specified document
     */
    public DOMTreeWalkerTreeModel(Document document) {
        DocumentTraversal dt = (DocumentTraversal) document;
        walker = dt.createTreeWalker(document, NodeFilter.SHOW_ALL, null, false);
    }

    /**
     * Create a TreeModel for a TreeWalker that returns the specified element
     * and all of its descendant nodes.
     */
    public DOMTreeWalkerTreeModel(Element element) {
        DocumentTraversal dt = (DocumentTraversal) element.getOwnerDocument();
        walker = dt.createTreeWalker(element, NodeFilter.SHOW_ALL, null, false);
    }

    // Return the root of the tree
    public Object getRoot() {
        return walker.getRoot();
    }

    // Is this node a leaf? (Leaf nodes are displayed differently by JTree)
    public boolean isLeaf(Object node) {
        walker.setCurrentNode((Node) node); // Set current node
        Node child = walker.firstChild(); // Ask for a child
        return (child == null); // Does it have any?
    }

    // How many children does this node have?
    public int getChildCount(Object node) {
        walker.setCurrentNode((Node) node); // Set the current node
        // TreeWalker doesn't count children for us, so we count ourselves
        int numkids = 0;
        Node child = walker.firstChild(); // Start with the first child
        while (child != null) { // Loop 'till there are no more
            numkids++; // Update the count
            child = walker.nextSibling(); // Get next child
        }
        return numkids; // This is the number of children
    }

    // Return the specified child of a parent node.
    public Object getChild(Object parent, int index) {
        walker.setCurrentNode((Node) parent); // Set the current node
        // TreeWalker provides sequential access to children, not random
        // access, so we've got to loop through the kids one by one
        Node child = walker.firstChild();
        while (index-- > 0)
            child = walker.nextSibling();
        return child;
    }

    // Return the index of the child node in the parent node
    public int getIndexOfChild(Object parent, Object child) {
        walker.setCurrentNode((Node) parent); // Set current node
        int index = 0;
        Node c = walker.firstChild(); // Start with first child
        while ((c != child) && (c != null)) { // Loop 'till we find a match
            index++;
            c = walker.nextSibling(); // Get the next child
        }
        return index; // Return matching position
    }

    // Only required for editable trees; unimplemented here.
    public void valueForPathChanged(TreePath path, Object newvalue) {
    }

    // This TreeModel never fires any events (since it is not editable)
    // so event listener registration methods are left unimplemented
    public void addTreeModelListener(TreeModelListener l) {
    }

    public void removeTreeModelListener(TreeModelListener l) {
    }

    /**
     * This main() method demonstrates the use of this class, the use of the
     * Xerces DOM parser, and the creation of a DOM Level 2 TreeWalker object.
     */
    public static void main(String[] args) throws IOException, SAXException {
        // Obtain an instance of a Xerces parser to build a DOM tree.
        // Note that we are not using the JAXP API here, so this
        // code uses Apache Xerces APIs that are not standards
        DOMParser parser = new org.apache.xerces.parsers.DOMParser();

        // Get a java.io.Reader for the input XML file and
        // wrap the input file in a SAX input source
        Reader in = new BufferedReader(new FileReader(args[0]));
        InputSource input = new org.xml.sax.InputSource(in);

        // Tell the Xerces parser to parse the input source
        parser.parse(input);

        // Ask the parser to give us our DOM Document. Once we've got the DOM
        // tree, we don't have to use the Apache Xerces APIs any more; from
        // here on, we use the standard DOM APIs
        Document document = parser.getDocument();

        // If we're using a DOM Level 2 implementation, then our Document
        // object ought to implement DocumentTraversal
        DocumentTraversal traversal = (DocumentTraversal) document;

        // For this demonstration, we create a NodeFilter that filters out
        // Text nodes containing only space; these just clutter up the tree
        NodeFilter filter = new NodeFilter() {
            public short acceptNode(Node n) {
                if (n.getNodeType() == Node.TEXT_NODE) {
                    // Use trim() to strip off leading and trailing space.
                    // If nothing is left, then reject the node
                    if (((Text) n).getData().trim().length() == 0)
                        return NodeFilter.FILTER_REJECT;
                }
                return NodeFilter.FILTER_ACCEPT;
            }
        };

        // This set of flags says to "show" all node types except comments
        int whatToShow = NodeFilter.SHOW_ALL & ~NodeFilter.SHOW_COMMENT;

        // Create a TreeWalker using the filter and the flags
        TreeWalker walker = traversal.createTreeWalker(document, whatToShow, filter, false);

        // Instantiate a TreeModel and a JTree to display it
        JTree tree = new JTree(new DOMTreeWalkerTreeModel(walker));

        // Create a frame and a scrollpane to display the tree, and pop them up
        JFrame frame = new JFrame("DOMTreeWalkerTreeModel Demo");
        frame.getContentPane().add(new JScrollPane(tree));
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        frame.setSize(500, 250);
        frame.setVisible(true);
    }
}