2
* Licensed to the Apache Software Foundation (ASF) under one or more
3
* contributor license agreements. See the NOTICE file distributed with
4
* this work for additional information regarding copyright ownership.
5
* The ASF licenses this file to You under the Apache License, Version 2.0
6
* (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
9
* http://www.apache.org/licenses/LICENSE-2.0
11
* Unless required by applicable law or agreed to in writing, software
12
* distributed under the License is distributed on an "AS IS" BASIS,
13
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
* See the License for the specific language governing permissions and
15
* limitations under the License.
17
package dom.traversal;
19
import java.awt.BorderLayout;
20
import java.awt.Dimension;
22
import java.awt.event.ActionEvent;
23
import java.awt.event.ActionListener;
24
import java.util.Enumeration;
25
import java.util.Hashtable;
27
import javax.swing.BorderFactory;
28
import javax.swing.JButton;
29
import javax.swing.JCheckBox;
30
import javax.swing.JFrame;
31
import javax.swing.JList;
32
import javax.swing.JPanel;
33
import javax.swing.JScrollPane;
34
import javax.swing.JTextArea;
35
import javax.swing.JTextField;
36
import javax.swing.event.ListSelectionEvent;
37
import javax.swing.event.ListSelectionListener;
38
import javax.swing.event.TreeSelectionEvent;
39
import javax.swing.event.TreeSelectionListener;
40
import javax.swing.tree.DefaultTreeModel;
41
import javax.swing.tree.MutableTreeNode;
42
import javax.swing.tree.TreeNode;
43
import javax.swing.tree.TreePath;
44
import javax.swing.tree.TreeSelectionModel;
46
import org.apache.xerces.parsers.DOMParser;
47
import org.w3c.dom.DOMException;
48
import org.w3c.dom.Document;
49
import org.w3c.dom.Node;
50
import org.w3c.dom.traversal.DocumentTraversal;
51
import org.w3c.dom.traversal.NodeFilter;
52
import org.w3c.dom.traversal.TreeWalker;
53
import org.xml.sax.ErrorHandler;
54
import org.xml.sax.SAXException;
55
import org.xml.sax.SAXParseException;
57
import ui.DOMTreeFull;
59
/** This class shows a DOM Document in a JTree, and presents controls
60
* which allow the user to create and view the progress of a TreeWalker
63
public class TreeWalkerView
65
implements ActionListener {
67
private static final long serialVersionUID = 3257566187583189559L;
70
TreeNode lastSelected;
72
JTextArea messageText;
73
JScrollPane messageScroll;
75
TreeWalker treeWalker;
76
NameNodeFilter nameNodeFilter;
86
JTextField nameFilter;
88
// treeWalker specific buttons
90
JButton nextSiblingButton;
91
JButton previousSiblingButton;
92
JButton firstChildButton;
93
JButton lastChildButton;
94
JButton currentButton;
96
String whatArray[] = new String [] {
104
"PROCESSING_INSTRUCTION",
115
public static void main (String args[]) {
117
if (args.length > 0) {
118
String filename = args[0];
120
TreeWalkerView frame = new TreeWalkerView(filename) ;
121
frame.addWindowListener(new java.awt.event.WindowAdapter() {
122
public void windowClosing(java.awt.event.WindowEvent e) {
126
frame.setSize(640, 700);
127
frame.setVisible(true);
128
} catch (Exception e) {
129
e.printStackTrace(System.err);
134
Hashtable treeNodeMap = new Hashtable();
137
public TreeWalkerView (String filename) {
138
super("TreeWalkerView: "+filename);
140
parser = new DOMParser();
141
parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", true);
142
parser.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true);
143
Errors errors = new Errors();
144
parser.setErrorHandler(errors);
145
parser.parse(filename);
146
document = parser.getDocument();
148
if (!document.isSupported("Traversal", "2.0")) {
149
// This cannot happen with the DOMParser...
150
throw new RuntimeException("This DOM Document does not support Traversal");
155
jtree = new DOMTreeFull((Node)document);
156
jtree.getSelectionModel().setSelectionMode
157
(TreeSelectionModel.SINGLE_TREE_SELECTION);
159
// Listen for when the selection changes, call nodeSelected(node)
160
jtree.addTreeSelectionListener(
161
new TreeSelectionListener() {
162
public void valueChanged(TreeSelectionEvent e) {
163
TreePath path = (TreePath)e.getPath();
164
TreeNode treeNode = (TreeNode)path.getLastPathComponent();
165
if(jtree.getSelectionModel().isPathSelected(path))
166
nodeSelected(treeNode);
175
BorderLayout borderLayout = new BorderLayout();
178
JPanel iteratePanel = new JPanel();
179
iteratePanel.setBorder(BorderFactory.createCompoundBorder(
180
BorderFactory.createTitledBorder("Document Order Traversal"),
181
BorderFactory.createEmptyBorder(4, 4, 4, 4)
184
prevButton = new JButton("Previous");
185
iteratePanel.add(prevButton);
186
prevButton.addActionListener(this);
188
nextButton = new JButton("Next");
189
iteratePanel.add(nextButton);
190
nextButton.addActionListener(this);
193
JPanel walkerPanel = new JPanel();
194
walkerPanel.setLayout(new BorderLayout());
195
walkerPanel.setBorder(BorderFactory.createCompoundBorder(
196
BorderFactory.createTitledBorder("Walk"),
197
BorderFactory.createEmptyBorder(4, 4, 4, 4)
200
parentButton = new JButton("Parent");
201
walkerPanel.add(parentButton, BorderLayout.NORTH);
202
parentButton.addActionListener(this);
205
JPanel childPanel = new JPanel();
206
firstChildButton = new JButton("First Child");
207
childPanel.add(firstChildButton);
208
firstChildButton.addActionListener(this);
210
lastChildButton = new JButton("Last Child");
211
childPanel.add(lastChildButton);
212
lastChildButton.addActionListener(this);
213
walkerPanel.add(childPanel, BorderLayout.SOUTH);
215
nextSiblingButton = new JButton("Next Sibling");
216
walkerPanel.add(nextSiblingButton, BorderLayout.EAST);
217
nextSiblingButton.addActionListener(this);
219
previousSiblingButton = new JButton("Previous Sibling");
220
walkerPanel.add(previousSiblingButton, BorderLayout.WEST);
221
previousSiblingButton.addActionListener(this);
224
JPanel domPanel = new JPanel();
225
domPanel.setLayout(new BorderLayout());
226
domPanel.setBorder(BorderFactory.createCompoundBorder(
227
BorderFactory.createTitledBorder("Selected Node"),
228
BorderFactory.createEmptyBorder(4, 4, 4, 4)
231
JPanel buttonPanel = new JPanel();
232
currentButton = new JButton("Current");
233
buttonPanel.add(currentButton);
234
currentButton.addActionListener(this);
236
removeButton = new JButton("Remove");
237
buttonPanel.add(removeButton);
238
removeButton.addActionListener(this);
240
addButton = new JButton("Append Text");
241
addText = new JTextField(10);
242
buttonPanel.add(addButton);
243
domPanel.add(buttonPanel, BorderLayout.NORTH);
244
domPanel.add(addText, BorderLayout.CENTER);
245
addButton.addActionListener(this);
247
// treeWalker settings
248
JPanel settingsPanel = new JPanel();
249
settingsPanel.setLayout(new BorderLayout());
250
settingsPanel.setBorder(BorderFactory.createCompoundBorder(
251
BorderFactory.createTitledBorder("Filter Settings"),
252
BorderFactory.createEmptyBorder(4, 4, 4, 4)
254
JPanel treeWalkerPanel = new JPanel();
255
treeWalkerPanel.setLayout(new BorderLayout());
257
newIterator = new JButton("createTreeWalker");
258
treeWalkerPanel.add(newIterator, BorderLayout.NORTH);
259
expandERs = new JCheckBox("expandEntityReferences");
260
expandERs.setSelected(true);
261
treeWalkerPanel.add(expandERs, BorderLayout.SOUTH);
262
settingsPanel.add(treeWalkerPanel, BorderLayout.NORTH);
263
newIterator.addActionListener(this);
265
JPanel whatPanel = new JPanel();
266
whatPanel.setBorder(BorderFactory.createCompoundBorder(
267
BorderFactory.createTitledBorder("whatToShow"),
268
BorderFactory.createEmptyBorder(0, 0, 0, 0)
270
whatToShow = new JList(whatArray);
271
JScrollPane whatScroll =
272
new JScrollPane(whatToShow) {
273
private static final long serialVersionUID = 3545240236637305138L;
274
public Dimension getPreferredSize(){
275
return new Dimension(200, 65 );
279
whatPanel.add(whatScroll);
282
JPanel filterPanel = new JPanel();
283
filterPanel.setBorder(BorderFactory.createCompoundBorder(
284
BorderFactory.createTitledBorder("NodeNameFilter"),
285
BorderFactory.createEmptyBorder(4, 4, 4, 4)
287
filterPanel.setLayout(new BorderLayout());
288
match = new JCheckBox("match/ignore node name", true);
289
nameFilter = new JTextField(10);
290
filterPanel.add(match, BorderLayout.NORTH);
291
filterPanel.add(nameFilter, BorderLayout.SOUTH);
293
settingsPanel.add(treeWalkerPanel, BorderLayout.NORTH);
294
settingsPanel.add(whatPanel, BorderLayout.CENTER);
295
settingsPanel.add(filterPanel, BorderLayout.SOUTH);
298
// Listen for when the selection changes, call nodeSelected(node)
299
whatToShow.addListSelectionListener(
300
new ListSelectionListener() {
301
public void valueChanged(ListSelectionEvent e) {
302
// do nothing on selection...
308
JPanel controlsPanel = new JPanel(new BorderLayout());
309
controlsPanel.setFont(new Font("Dialog", Font.PLAIN, 8));
310
JPanel buttonsPanel = new JPanel(new BorderLayout());
311
buttonsPanel.add(iteratePanel, BorderLayout.NORTH);
312
buttonsPanel.add(walkerPanel, BorderLayout.CENTER);
313
buttonsPanel.add(domPanel, BorderLayout.SOUTH);
314
controlsPanel.add(buttonsPanel, BorderLayout.NORTH);
315
controlsPanel.add(settingsPanel, BorderLayout.CENTER);
317
controlsPanel.setBorder(BorderFactory.createCompoundBorder(
318
BorderFactory.createTitledBorder("Controls"),
319
BorderFactory.createEmptyBorder(4, 4, 4, 4)
324
JPanel treePanel = new JPanel(new BorderLayout());
326
JScrollPane treeScroll = new JScrollPane(jtree) ;
327
treeScroll.setBorder(BorderFactory.createCompoundBorder(
328
BorderFactory.createTitledBorder("Tree View"),
329
BorderFactory.createEmptyBorder(4, 4, 4, 4)
332
// message text UI setup
333
messageText = new JTextArea(3,5);
335
JPanel messagePanel = new JPanel(new BorderLayout());
336
messageScroll = new JScrollPane(messageText);
337
messagePanel.add(messageScroll);
338
messagePanel.setBorder(BorderFactory.createCompoundBorder(
339
BorderFactory.createTitledBorder("Messages"),
340
BorderFactory.createEmptyBorder(4, 4, 4, 4)
343
JPanel mainPanel = new JPanel();
344
mainPanel.setLayout(new BorderLayout());
345
mainPanel.add(controlsPanel, BorderLayout.EAST);
346
mainPanel.add(treeScroll, BorderLayout.CENTER);
347
mainPanel.add(messagePanel, BorderLayout.SOUTH);
348
getContentPane().add(mainPanel);
350
Hashtable errorNodes = errors.getErrorNodes();
351
Enumeration elements = errorNodes.elements();
352
while (elements.hasMoreElements()) {
353
//*** append errors to messageText
354
messageText.append( (String)elements.nextElement());
357
boolean expand = expandERs.isSelected();
358
treeWalker = ((DocumentTraversal)document).
362
new NameNodeFilter(),
365
} catch (Exception e) {
366
e.printStackTrace(System.err);
370
public void actionPerformed(ActionEvent e) {
372
if (e.getSource() == newIterator) {
374
TreeNode treeNode = (TreeNode)jtree.getLastSelectedPathComponent();
375
if (treeNode == null) {
376
messageText.append("Must select a tree component.");
380
Node node = jtree.getNode(treeNode);
382
setMessage("No current Node in TreeNode: "+node);
385
// whatToShow section
386
int [] indices = whatToShow.getSelectedIndices();
388
for (int i = 0; i < indices.length; i++) {
389
if (indices[i] == 0) {
393
mask = mask | 1<<indices[i]-1;
398
String nameText = nameFilter.getText();
399
boolean matched = match.isSelected();
400
if (nameNodeFilter==null) {
401
nameNodeFilter = new NameNodeFilter();
403
if (nameText.equals("")) {
404
setMessage("NodeNameFilter name is \"\". Assuming null.");
407
nameNodeFilter.setName(nameText);
408
nameNodeFilter.setMatch(matched);
410
// expand Entity References?
411
boolean expand = expandERs.isSelected();
413
treeWalker = ((DocumentTraversal)document).
419
setMessage("createTreeWalker:"+
421
", whatToShow="+mask+
429
if (e.getSource() == currentButton) {
431
TreeNode treeNode = (TreeNode)jtree.getLastSelectedPathComponent();
432
if (treeNode == null) {
433
messageText.append("Must select a tree component.");
437
Node node = jtree.getNode(treeNode);
439
setMessage("No current Node in TreeNode: "+node);
441
treeWalker.setCurrentNode(node);
445
if (e.getSource() == addButton) {
447
String text = addText.getText();
449
if (text==null) return;
451
TreeNode treeNode = (TreeNode)jtree.getLastSelectedPathComponent();
452
if (treeNode == null) {
453
messageText.append("Must select a tree component to add a child to it.");
456
TreePath path = new TreePath(
457
((DefaultTreeModel)jtree.getModel()).getPathToRoot(treeNode));
459
setMessage("Could not create a path.");
462
if(!jtree.getSelectionModel().isPathSelected(path))
464
Node node = jtree.getNode(treeNode);
465
Node textNode = document.createTextNode(text);
467
node.appendChild(textNode);
468
} catch (DOMException dome) {
469
setMessage("DOMException:"+dome.code+", "+dome);
472
((DOMTreeFull.Model)jtree.getModel()).insertNode(textNode, (MutableTreeNode)treeNode);
477
if (e.getSource() == removeButton) {
479
/** If the node is not selected don't remove. */
480
TreeNode treeNode = (TreeNode)jtree.getLastSelectedPathComponent();
481
if (treeNode == null) {
482
messageText.append("Must select a tree component to remove it.");
485
TreePath path = new TreePath(
486
((DefaultTreeModel)jtree.getModel()).getPathToRoot(treeNode));
488
setMessage("Could not create a path.");
491
if(!jtree.getSelectionModel().isPathSelected(path))
493
Node node = jtree.getNode(treeNode);
494
if (node == null) return;
495
Node parent = node.getParentNode();
496
if (parent == null) return;
498
parent.removeChild(node);
500
((DefaultTreeModel)jtree.getModel()).removeNodeFromParent((MutableTreeNode)treeNode);
504
if (e.getSource() == previousSiblingButton) {
505
Node node = treeWalker.previousSibling();
506
handleButton(node, "previousSibling()");
510
if (e.getSource() == firstChildButton) {
511
Node node = treeWalker.firstChild();
512
handleButton(node, "firstChild()");
516
if (e.getSource() == lastChildButton) {
517
Node node = treeWalker.lastChild();
518
handleButton(node, "lastChild()");
522
if (e.getSource() == nextSiblingButton) {
523
Node node = treeWalker.nextSibling();
524
handleButton(node, "nextSibling()");
528
if (e.getSource() == parentButton) {
529
Node node = treeWalker.parentNode();
530
handleButton(node, "parentNode()");
534
if (e.getSource() == nextButton) {
535
Node node = treeWalker.nextNode();
536
handleButton(node, "nextNode()");
540
if (e.getSource() == prevButton) {
541
Node node = treeWalker.previousNode();
542
handleButton(node, "previousNode()");
548
/** handle a button press: output messages and select node. */
549
void handleButton( Node node, String function) {
551
setMessage("treeWalker."+function+" == "+node);
553
if (node==null) return;
555
TreeNode treeNode = jtree.getTreeNode(node);
556
if (treeNode == null) {
557
setMessage("No JTree TreeNode for Node name:" + node.getNodeName());
561
TreePath path = new TreePath(
562
((DefaultTreeModel)jtree.getModel()).getPathToRoot(treeNode));
563
jtree.requestFocus();
564
jtree.setSelectionPath(path);
565
jtree.scrollPathToVisible(path);
568
/** Helper function to set messages */
569
void setMessage(String string) {
570
messageText.selectAll();
572
messageText.append(string);
573
messageText.setCaretPosition(0);
576
/** called when our JTree's nodes are selected.
578
void nodeSelected(TreeNode treeNode) {
580
lastSelected = treeNode;
581
Node node = jtree.getNode(treeNode);
583
if (node == null) return;
585
setMessage(DOMTreeFull.toString(node));
588
/** Utility function to expand the jtree */
590
for (int i = 0; i < jtree.getRowCount(); i++) {
595
class Errors implements ErrorHandler {
597
Hashtable errorNodes = new Hashtable();
599
public void warning(SAXParseException ex) {
600
store(ex, "[Warning]");
603
public void error(SAXParseException ex) {
604
store(ex, "[Error]");
607
public void fatalError(SAXParseException ex) throws SAXException {
608
store(ex, "[Fatal Error]");
611
public Hashtable getErrorNodes() {
615
public Object getError(Node node) {
616
return errorNodes.get(node);
619
public void clearErrors() {
623
void store(SAXParseException ex, String type) {
626
String errorString= type+" at line number, "+ex.getLineNumber()
627
+": "+ex.getMessage()+"\n";
629
Node currentNode = null;
631
currentNode = (Node)parser.getProperty("http://apache.org/xml/properties/dom-node");
632
} catch (SAXException se) {
633
System.err.println(se.getMessage());
636
if (currentNode == null) return;
638
// accumulate any multiple errors per node in the Hashtable.
639
String previous = (String) errorNodes.get(currentNode);
640
if (previous != null)
641
errorNodes.put(currentNode, previous +errorString);
643
errorNodes.put(currentNode, errorString);