/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ui; import java.io.Serializable; import java.util.Hashtable; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeNode; import org.w3c.dom.Attr; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Notation; /** * DOMTree class to enter every DOM node into a Swing JTree tree. * The forward and backward mappings between Nodes to TreeNodes are kept. * * @version $Id$ */ public class DOMTreeFull extends JTree { private static final long serialVersionUID = 3978144335541975344L; // // 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); } // () // // 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 { private static final long serialVersionUID = 3258131375181018673L; // // 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