blob: e14a6562875d586fc7d7bdecce1e146293b43757 [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package ui;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import org.w3c.dom.*;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.Hashtable;
import java.util.Enumeration;
/**
* DOMTree class to enter every DOM node into a Swing JTree tree.
* The forward and backward mappings between Nodes to TreeNodes are kept.
*
*/
public class DOMTreeFull
extends JTree
{
//
// Constructors
//
/** Default constructor. */
public DOMTreeFull() {
this(null);
}
/** Constructs a tree with the specified document. */
public DOMTreeFull(Node root) {
super(new Model());
// set tree properties
setRootVisible(false);
// set properties
setRootNode(root);
} // <init>()
//
// Public methods
//
/** Sets the root. */
public void setRootNode(Node root) {
((Model)getModel()).setRootNode(root);
expandRow(0);
}
/** Returns the root. */
public Node getRootNode() {
return ((Model)getModel()).getRootNode();
}
/** get the org.w3c.Node for a MutableTreeNode. */
public Node getNode(Object treeNode) {
return ((Model)getModel()).getNode(treeNode);
}
/** get the TreeNode for the org.w3c.Node */
public TreeNode getTreeNode(Object node) {
return ((Model)getModel()).getTreeNode(node);
}
//
// Classes
//
/**
* DOM tree model.
*
*/
public static class Model
extends DefaultTreeModel
implements Serializable
{
//
// Data
//
/** Root. */
private Node root;
/** Node Map. */
private Hashtable nodeMap = new Hashtable();
/** Tree Node Map. */
private Hashtable treeNodeMap = new Hashtable();
//
// Constructors
//
/** Default constructor. */
public Model() {
this(null);
}
/** Constructs a model from the specified root. */
public Model(Node node) {
super(new DefaultMutableTreeNode());
if (node!=null)
setRootNode(node);
}
//
// Public methods
//
/** Sets the root. */
public synchronized void setRootNode(Node root) {
// save root
this.root = root;
// clear tree and re-populate
DefaultMutableTreeNode where = (DefaultMutableTreeNode)getRoot();
where.removeAllChildren();
nodeMap.clear();
treeNodeMap.clear();
buildTree(root, where);
fireTreeStructureChanged(this, new Object[] { getRoot() }, new int[0], new Object[0]);
} // setRootNode(Node)
/** Returns the root. */
public Node getRootNode() {
return root;
}
/** get the org.w3c.Node for a MutableTreeNode. */
public Node getNode(Object treeNode) {
return (Node)nodeMap.get(treeNode);
}
public Hashtable getAllNodes() {
return nodeMap;
}
/** get the org.w3c.Node for a MutableTreeNode. */
public TreeNode getTreeNode(Object node) {
Object object = treeNodeMap.get(node);
return (TreeNode)object;
}
//
// Private methods
//
/** Builds the tree. */
private void buildTree(Node node, MutableTreeNode where) {
// is there anything to do?
if (node == null) { return; }
MutableTreeNode treeNode = insertNode(node, where);
// iterate over children of this node
NodeList nodes = node.getChildNodes();
int len = (nodes != null) ? nodes.getLength() : 0;
for (int i = 0; i < len; i++) {
Node child = nodes.item(i);
buildTree(child, treeNode);
}
} // buildTree()
/** Inserts a node and returns a reference to the new node. */
private MutableTreeNode insertNode(String what, MutableTreeNode where) {
MutableTreeNode node = new DefaultMutableTreeNode(what);
insertNodeInto(node, where, where.getChildCount());
return node;
} // insertNode(Node,MutableTreeNode):MutableTreeNode
/** Inserts a text node. */
public MutableTreeNode insertNode(Node what, MutableTreeNode where) {
MutableTreeNode treeNode = insertNode(DOMTreeFull.toString(what), where);
nodeMap.put(treeNode, what);
treeNodeMap.put(what, treeNode);
return treeNode;
}
} // class Model
public static String whatArray[] = new String [] {
"ALL",
"ELEMENT",
"ATTRIBUTE",
"TEXT",
"CDATA_SECTION",
"ENTITY_REFERENCE",
"ENTITY",
"PROCESSING_INSTRUCTION",
"COMMENT",
"DOCUMENT",
"DOCUMENT_TYPE",
"DOCUMENT_FRAGMENT",
"NOTATION"
};
//
// Public methods
//
public static String toString(Node node) {
StringBuffer sb = new StringBuffer();
// is there anything to do?
if (node == null) {
return "";
}
int type = node.getNodeType();
sb.append(whatArray[type]);
sb.append(" : ");
sb.append(node.getNodeName());
String value = node.getNodeValue();
if (value != null) {
sb.append(" Value: \"");
sb.append(value);
sb.append("\"");
}
switch (type) {
// document
case Node.DOCUMENT_NODE: {
break;
}
// element with attributes
case Node.ELEMENT_NODE: {
Attr attrs[] = sortAttributes(node.getAttributes());
if (attrs.length > 0)
sb.append(" ATTRS:");
for (int i = 0; i < attrs.length; i++) {
Attr attr = attrs[i];
sb.append(' ');
sb.append(attr.getNodeName());
sb.append("=\"");
sb.append(normalize(attr.getNodeValue()));
sb.append('"');
}
sb.append('>');
break;
}
// handle entity reference nodes
case Node.ENTITY_REFERENCE_NODE: {
break;
}
// cdata sections
case Node.CDATA_SECTION_NODE: {
break;
}
// text
case Node.TEXT_NODE: {
break;
}
// processing instruction
case Node.PROCESSING_INSTRUCTION_NODE: {
break;
}
// comment node
case Node.COMMENT_NODE: {
break;
}
// DOCTYPE node
case Node.DOCUMENT_TYPE_NODE: {
break;
}
// Notation node
case Node.NOTATION_NODE: {
sb.append("public:");
String id = ((Notation)node).getPublicId();
if (id == null) {
sb.append("PUBLIC ");
sb.append(id);
sb.append(" ");
}
id = ((Notation)node).getSystemId();
if (id == null) {
sb.append("system: ");
sb.append(id);
sb.append(" ");
}
break;
}
}
return sb.toString();
}
/** Normalizes the given string. */
static protected String normalize(String s) {
StringBuffer str = new StringBuffer();
int len = (s != null) ? s.length() : 0;
for (int i = 0; i < len; i++) {
char ch = s.charAt(i);
switch (ch) {
case '<': {
str.append("&lt;");
break;
}
case '>': {
str.append("&gt;");
break;
}
case '&': {
str.append("&amp;");
break;
}
case '"': {
str.append("&quot;");
break;
}
case '\r':
case '\n':
default: {
str.append(ch);
}
}
}
return str.toString();
} // normalize(String):String
/** Returns a sorted list of attributes. */
static protected Attr[] sortAttributes(NamedNodeMap attrs) {
int len = (attrs != null) ? attrs.getLength() : 0;
Attr array[] = new Attr[len];
for (int i = 0; i < len; i++) {
array[i] = (Attr)attrs.item(i);
}
for (int i = 0; i < len - 1; i++) {
String name = array[i].getNodeName();
int index = i;
for (int j = i + 1; j < len; j++) {
String curName = array[j].getNodeName();
if (curName.compareTo(name) < 0) {
name = curName;
index = j;
}
}
if (index != i) {
Attr temp = array[i];
array[i] = array[index];
array[index] = temp;
}
}
return array;
} // sortAttributes(NamedNodeMap):Attr[]
} // class DOMTreeFull