/* * 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 dom.traversal; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Enumeration; import java.util.Hashtable; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import org.apache.xerces.parsers.DOMParser; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.traversal.DocumentTraversal; import org.w3c.dom.traversal.NodeFilter; import org.w3c.dom.traversal.TreeWalker; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import ui.DOMTreeFull; /** * This class shows a DOM Document in a JTree, and presents controls * which allow the user to create and view the progress of a TreeWalker * in the DOM tree. * * @version $Id: TreeWalkerView.java 950355 2010-06-02 03:43:24Z mrglavas $ */ public class TreeWalkerView extends JFrame implements ActionListener { private static final long serialVersionUID = 3257566187583189559L; Document document; TreeNode lastSelected; DOMParser parser; JTextArea messageText; JScrollPane messageScroll; DOMTreeFull jtree; TreeWalker treeWalker; NameNodeFilter nameNodeFilter; JButton nextButton; JButton prevButton; JButton removeButton; JButton addButton; JTextField addText; JButton newIterator; JList whatToShow; JCheckBox match; JTextField nameFilter; // treeWalker specific buttons JButton parentButton; JButton nextSiblingButton; JButton previousSiblingButton; JButton firstChildButton; JButton lastChildButton; JButton currentButton; String whatArray[] = new String [] { "ALL", "ELEMENT", "ATTRIBUTE", "TEXT", "CDATA_SECTION", "ENTITY_REFERENCE", "ENTITY", "PROCESSING_INSTRUCTION", "COMMENT", "DOCUMENT", "DOCUMENT_TYPE", "DOCUMENT_FRAGMENT", "NOTATION" }; JCheckBox expandERs; /** main */ public static void main (String args[]) { if (args.length > 0) { String filename = args[0]; try { TreeWalkerView frame = new TreeWalkerView(filename) ; frame.addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent e) { System.exit(0); } }); frame.setSize(640, 700); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(System.err); } } } Hashtable treeNodeMap = new Hashtable(); /** Constructor */ public TreeWalkerView (String filename) { super("TreeWalkerView: "+filename); try { parser = new DOMParser(); parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", true); parser.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true); Errors errors = new Errors(); parser.setErrorHandler(errors); parser.parse(filename); document = parser.getDocument(); if (!document.isSupported("Traversal", "2.0")) { // This cannot happen with the DOMParser... throw new RuntimeException("This DOM Document does not support Traversal"); } // jtree UI setup jtree = new DOMTreeFull((Node)document); jtree.getSelectionModel().setSelectionMode (TreeSelectionModel.SINGLE_TREE_SELECTION); // Listen for when the selection changes, call nodeSelected(node) jtree.addTreeSelectionListener( new TreeSelectionListener() { public void valueChanged(TreeSelectionEvent e) { TreePath path = (TreePath)e.getPath(); TreeNode treeNode = (TreeNode)path.getLastPathComponent(); if(jtree.getSelectionModel().isPathSelected(path)) nodeSelected(treeNode); } } ); // // controls // BorderLayout borderLayout = new BorderLayout(); //iterate panel JPanel iteratePanel = new JPanel(); iteratePanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("Document Order Traversal"), BorderFactory.createEmptyBorder(4, 4, 4, 4) )); prevButton = new JButton("Previous"); iteratePanel.add(prevButton); prevButton.addActionListener(this); nextButton = new JButton("Next"); iteratePanel.add(nextButton); nextButton.addActionListener(this); //walkerPanel JPanel walkerPanel = new JPanel(); walkerPanel.setLayout(new BorderLayout()); walkerPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("Walk"), BorderFactory.createEmptyBorder(4, 4, 4, 4) )); parentButton = new JButton("Parent"); walkerPanel.add(parentButton, BorderLayout.NORTH); parentButton.addActionListener(this); JPanel childPanel = new JPanel(); firstChildButton = new JButton("First Child"); childPanel.add(firstChildButton); firstChildButton.addActionListener(this); lastChildButton = new JButton("Last Child"); childPanel.add(lastChildButton); lastChildButton.addActionListener(this); walkerPanel.add(childPanel, BorderLayout.SOUTH); nextSiblingButton = new JButton("Next Sibling"); walkerPanel.add(nextSiblingButton, BorderLayout.EAST); nextSiblingButton.addActionListener(this); previousSiblingButton = new JButton("Previous Sibling"); walkerPanel.add(previousSiblingButton, BorderLayout.WEST); previousSiblingButton.addActionListener(this); //DOM tree panel JPanel domPanel = new JPanel(); domPanel.setLayout(new BorderLayout()); domPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("Selected Node"), BorderFactory.createEmptyBorder(4, 4, 4, 4) )); JPanel buttonPanel = new JPanel(); currentButton = new JButton("Current"); buttonPanel.add(currentButton); currentButton.addActionListener(this); removeButton = new JButton("Remove"); buttonPanel.add(removeButton); removeButton.addActionListener(this); addButton = new JButton("Append Text"); addText = new JTextField(10); buttonPanel.add(addButton); domPanel.add(buttonPanel, BorderLayout.NORTH); domPanel.add(addText, BorderLayout.CENTER); addButton.addActionListener(this); // treeWalker settings JPanel settingsPanel = new JPanel(); settingsPanel.setLayout(new BorderLayout()); settingsPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("Filter Settings"), BorderFactory.createEmptyBorder(4, 4, 4, 4) )); JPanel treeWalkerPanel = new JPanel(); treeWalkerPanel.setLayout(new BorderLayout()); newIterator = new JButton("createTreeWalker"); treeWalkerPanel.add(newIterator, BorderLayout.NORTH); expandERs = new JCheckBox("expandEntityReferences"); expandERs.setSelected(true); treeWalkerPanel.add(expandERs, BorderLayout.SOUTH); settingsPanel.add(treeWalkerPanel, BorderLayout.NORTH); newIterator.addActionListener(this); JPanel whatPanel = new JPanel(); whatPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("whatToShow"), BorderFactory.createEmptyBorder(0, 0, 0, 0) )); whatToShow = new JList(whatArray); JScrollPane whatScroll = new JScrollPane(whatToShow) { private static final long serialVersionUID = 3545240236637305138L; public Dimension getPreferredSize(){ return new Dimension(200, 65 ); } }; whatPanel.add(whatScroll); JPanel filterPanel = new JPanel(); filterPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("NodeNameFilter"), BorderFactory.createEmptyBorder(4, 4, 4, 4) )); filterPanel.setLayout(new BorderLayout()); match = new JCheckBox("match/ignore node name", true); nameFilter = new JTextField(10); filterPanel.add(match, BorderLayout.NORTH); filterPanel.add(nameFilter, BorderLayout.SOUTH); settingsPanel.add(treeWalkerPanel, BorderLayout.NORTH); settingsPanel.add(whatPanel, BorderLayout.CENTER); settingsPanel.add(filterPanel, BorderLayout.SOUTH); // Listen for when the selection changes, call nodeSelected(node) whatToShow.addListSelectionListener( new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { // do nothing on selection... } } ); JPanel controlsPanel = new JPanel(new BorderLayout()); controlsPanel.setFont(new Font("Dialog", Font.PLAIN, 8)); JPanel buttonsPanel = new JPanel(new BorderLayout()); buttonsPanel.add(iteratePanel, BorderLayout.NORTH); buttonsPanel.add(walkerPanel, BorderLayout.CENTER); buttonsPanel.add(domPanel, BorderLayout.SOUTH); controlsPanel.add(buttonsPanel, BorderLayout.NORTH); controlsPanel.add(settingsPanel, BorderLayout.CENTER); controlsPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("Controls"), BorderFactory.createEmptyBorder(4, 4, 4, 4) )); // tree panel JPanel treePanel = new JPanel(new BorderLayout()); JScrollPane treeScroll = new JScrollPane(jtree) ; treeScroll.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("Tree View"), BorderFactory.createEmptyBorder(4, 4, 4, 4) )); // message text UI setup messageText = new JTextArea(3,5); JPanel messagePanel = new JPanel(new BorderLayout()); messageScroll = new JScrollPane(messageText); messagePanel.add(messageScroll); messagePanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("Messages"), BorderFactory.createEmptyBorder(4, 4, 4, 4) )); JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); mainPanel.add(controlsPanel, BorderLayout.EAST); mainPanel.add(treeScroll, BorderLayout.CENTER); mainPanel.add(messagePanel, BorderLayout.SOUTH); getContentPane().add(mainPanel); Hashtable errorNodes = errors.getErrorNodes(); Enumeration elements = errorNodes.elements(); while (elements.hasMoreElements()) { //*** append errors to messageText messageText.append( (String)elements.nextElement()); } boolean expand = expandERs.isSelected(); treeWalker = ((DocumentTraversal)document). createTreeWalker( document, NodeFilter.SHOW_ALL, new NameNodeFilter(), expand); } catch (Exception e) { e.printStackTrace(System.err); } } public void actionPerformed(ActionEvent e) { if (e.getSource() == newIterator) { TreeNode treeNode = (TreeNode)jtree.getLastSelectedPathComponent(); if (treeNode == null) { messageText.append("Must select a tree component."); return; } Node node = jtree.getNode(treeNode); if (node == null) { setMessage("No current Node in TreeNode: "+node); } // whatToShow section int [] indices = whatToShow.getSelectedIndices(); int mask = 0x0; for (int i = 0; i < indices.length; i++) { if (indices[i] == 0) { mask = 0xFFFF; break; } else { mask = mask | 1<<indices[i]-1; } } // filter section String nameText = nameFilter.getText(); boolean matched = match.isSelected(); if (nameNodeFilter==null) { nameNodeFilter = new NameNodeFilter(); } if (nameText.length() == 0) { setMessage("NodeNameFilter name is \"\". Assuming null."); nameText = null; } nameNodeFilter.setName(nameText); nameNodeFilter.setMatch(matched); // expand Entity References? boolean expand = expandERs.isSelected(); treeWalker = ((DocumentTraversal)document). createTreeWalker( node, mask, nameNodeFilter, expand); setMessage("createTreeWalker:"+ " root="+node+ ", whatToShow="+mask+ ", match="+matched+ ", name="+nameText ); return; } if (e.getSource() == currentButton) { TreeNode treeNode = (TreeNode)jtree.getLastSelectedPathComponent(); if (treeNode == null) { messageText.append("Must select a tree component."); return; } Node node = jtree.getNode(treeNode); if (node == null) { setMessage("No current Node in TreeNode: "+node); } treeWalker.setCurrentNode(node); return; } if (e.getSource() == addButton) { String text = addText.getText(); if (text==null) return; TreeNode treeNode = (TreeNode)jtree.getLastSelectedPathComponent(); if (treeNode == null) { messageText.append("Must select a tree component to add a child to it."); return; } TreePath path = new TreePath( ((DefaultTreeModel)jtree.getModel()).getPathToRoot(treeNode)); if (path == null) { setMessage("Could not create a path."); return; } if(!jtree.getSelectionModel().isPathSelected(path)) return; Node node = jtree.getNode(treeNode); Node textNode = document.createTextNode(text); try { node.appendChild(textNode); } catch (DOMException dome) { setMessage("DOMException:"+dome.code+", "+dome); return; } ((DOMTreeFull.Model)jtree.getModel()).insertNode(textNode, (MutableTreeNode)treeNode); return; } if (e.getSource() == removeButton) { /** If the node is not selected don't remove. */ TreeNode treeNode = (TreeNode)jtree.getLastSelectedPathComponent(); if (treeNode == null) { messageText.append("Must select a tree component to remove it."); return; } TreePath path = new TreePath( ((DefaultTreeModel)jtree.getModel()).getPathToRoot(treeNode)); if (path == null) { setMessage("Could not create a path."); return; } if(!jtree.getSelectionModel().isPathSelected(path)) return; Node node = jtree.getNode(treeNode); if (node == null) return; Node parent = node.getParentNode(); if (parent == null) return; parent.removeChild(node); ((DefaultTreeModel)jtree.getModel()).removeNodeFromParent((MutableTreeNode)treeNode); return; } if (e.getSource() == previousSiblingButton) { Node node = treeWalker.previousSibling(); handleButton(node, "previousSibling()"); return; } if (e.getSource() == firstChildButton) { Node node = treeWalker.firstChild(); handleButton(node, "firstChild()"); return; } if (e.getSource() == lastChildButton) { Node node = treeWalker.lastChild(); handleButton(node, "lastChild()"); return; } if (e.getSource() == nextSiblingButton) { Node node = treeWalker.nextSibling(); handleButton(node, "nextSibling()"); return; } if (e.getSource() == parentButton) { Node node = treeWalker.parentNode(); handleButton(node, "parentNode()"); return; } if (e.getSource() == nextButton) { Node node = treeWalker.nextNode(); handleButton(node, "nextNode()"); return; } if (e.getSource() == prevButton) { Node node = treeWalker.previousNode(); handleButton(node, "previousNode()"); return; } } /** handle a button press: output messages and select node. */ void handleButton( Node node, String function) { setMessage("treeWalker."+function+" == "+node); if (node==null) return; TreeNode treeNode = jtree.getTreeNode(node); if (treeNode == null) { setMessage("No JTree TreeNode for Node name:" + node.getNodeName()); return; } TreePath path = new TreePath( ((DefaultTreeModel)jtree.getModel()).getPathToRoot(treeNode)); jtree.requestFocus(); jtree.setSelectionPath(path); jtree.scrollPathToVisible(path); } /** Helper function to set messages */ void setMessage(String string) { messageText.selectAll(); messageText.cut(); messageText.append(string); messageText.setCaretPosition(0); } /** called when our JTree's nodes are selected. */ void nodeSelected(TreeNode treeNode) { lastSelected = treeNode; Node node = jtree.getNode(treeNode); if (node == null) return; setMessage(DOMTreeFull.toString(node)); } /** Utility function to expand the jtree */ void expandTree() { for (int i = 0; i < jtree.getRowCount(); i++) { jtree.expandRow(i); } } class Errors implements ErrorHandler { Hashtable errorNodes = new Hashtable(); public void warning(SAXParseException ex) { store(ex, "[Warning]"); } public void error(SAXParseException ex) { store(ex, "[Error]"); } public void fatalError(SAXParseException ex) throws SAXException { store(ex, "[Fatal Error]"); } public Hashtable getErrorNodes() { return errorNodes; } public Object getError(Node node) { return errorNodes.get(node); } public void clearErrors() { errorNodes.clear(); } void store(SAXParseException ex, String type) { // build error text String errorString= type+" at line number, "+ex.getLineNumber() +": "+ex.getMessage()+"\n"; Node currentNode = null; try { currentNode = (Node)parser.getProperty("http://apache.org/xml/properties/dom-node"); } catch (SAXException se) { System.err.println(se.getMessage()); return; } if (currentNode == null) return; // accumulate any multiple errors per node in the Hashtable. String previous = (String) errorNodes.get(currentNode); if (previous != null) errorNodes.put(currentNode, previous +errorString); else errorNodes.put(currentNode, errorString); } } }