| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 1999,2000 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("<"); |
| break; |
| } |
| case '>': { |
| str.append(">"); |
| break; |
| } |
| case '&': { |
| str.append("&"); |
| break; |
| } |
| case '"': { |
| str.append("""); |
| 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 |
| |