| /* |
| * 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.awt.*; |
| import java.awt.event.*; |
| import java.util.*; |
| import java.io.*; |
| import javax.swing.*; |
| import javax.swing.tree.*; |
| import javax.swing.event.*; |
| import java.net.URL; |
| import java.net.MalformedURLException; |
| |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Text; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.ErrorHandler; |
| import org.xml.sax.Locator; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXParseException; |
| import org.apache.xerces.parsers.DOMParser; |
| import ui.DOMParserSaveEncoding; |
| |
| |
| |
| /** |
| * A sample DOM Tree Viewer. This sample program illustrates how to |
| * traverse a DOM tree and display it in a Swing JTree View. |
| * |
| * @version |
| */ |
| public class TreeView extends JFrame implements ActionListener, TextListener { |
| |
| // |
| // Constants |
| // |
| |
| static final boolean DEBUG = true; |
| |
| /** Default parser name. */ |
| static final String |
| DEFAULT_PARSER_NAME = "org.apache.xerces.parsers.DOMParser"; |
| static int WARNING = 0; |
| static int ERROR=1; |
| static int FATAL_ERROR=2; |
| |
| |
| static final String title = "TreeViewer"; |
| static final String openString = "Open"; |
| static final String quitString = "Quit"; |
| static final String reloadString = "Reload current XML file"; |
| static final String expandString = "Expand Tree"; |
| static final String collapseString = "Collapse Tree"; |
| |
| // |
| // Data |
| // |
| |
| ErrorStorer ef; |
| String fname; |
| DOMTree m_tree; |
| JTextArea sourceText, messageText; |
| Vector textLine; |
| FileNameInput fni; |
| DOMParserSaveEncoding parser; |
| Image openFolder; |
| Image closedFolder; |
| Image leafImage; |
| |
| /** |
| * Constructor |
| */ |
| public TreeView() { |
| this(null); |
| } |
| |
| /** |
| * Constructor |
| */ |
| public TreeView(String uri) { |
| super(uri); |
| openFolder = DefaultImages.createOpenFolderImage(); |
| closedFolder = DefaultImages.createClosedFolderImage(); |
| leafImage = DefaultImages.createLeafImage(); |
| parser = new DOMParserSaveEncoding(); |
| ef = new ErrorStorer(); |
| fname = uri; |
| JMenuBar jmb = new JMenuBar(); |
| JMenu fileMenu = new JMenu("File"); |
| JMenuItem item; |
| |
| item = new JMenuItem(openString); |
| fileMenu.add(item); |
| item.addActionListener(this); |
| |
| item = new JMenuItem(quitString); |
| fileMenu.add(item); |
| item.addActionListener(this); |
| |
| JMenu shortcutMenu = new JMenu("Shortcuts"); |
| |
| item = new JMenuItem(expandString); |
| shortcutMenu.add(item); |
| item.addActionListener(this); |
| |
| item = new JMenuItem(collapseString); |
| shortcutMenu.add(item); |
| item.addActionListener(this); |
| |
| item = new JMenuItem(reloadString); |
| shortcutMenu.add(item); |
| item.addActionListener(this); |
| |
| jmb.add(fileMenu); |
| jmb.add(shortcutMenu); |
| setJMenuBar(jmb); |
| |
| getContentPane().add(createUI(fname)); |
| |
| } |
| |
| /** create and return the entire UI from the root TreeNode |
| */ |
| JComponent createUI(String filename) { |
| if (DEBUG) System.out.println("START createUI:"+filename); |
| |
| // create the message panel first so we can send messages to it... |
| messageText = new JTextArea(3,40); |
| messageText.setFont(new Font("dialog", Font.PLAIN, 12)); |
| JPanel messagePanel = new JPanel(new BorderLayout()); |
| messagePanel.add(new JScrollPane(messageText) { |
| public Dimension getPreferredSize(){ |
| Dimension size = TreeView.this.getSize(); |
| return new Dimension(size.width, size.height / 4); |
| } |
| public Dimension getMinimumSize(){ |
| return new Dimension(100, 100); |
| } |
| }, |
| BorderLayout.CENTER); |
| messagePanel.setBorder(BorderFactory.createCompoundBorder( |
| BorderFactory.createTitledBorder("Messages"), |
| BorderFactory.createEmptyBorder(4, 4, 4, 4) |
| )); |
| |
| // create the TextArea for XML source |
| sourceText = new JTextArea(); |
| sourceText.setFont(new Font("monospaced", Font.PLAIN, 12)); |
| sourceText.setBackground(Color.white); |
| sourceText.setForeground(Color.black); |
| sourceText.setSelectedTextColor(Color.black); |
| sourceText.setSelectionColor(Color.red); |
| sourceText.setEditable(false); |
| JPanel sourcePanel = new JPanel(new BorderLayout()); |
| sourcePanel.add(new JScrollPane(sourceText){ |
| public Dimension getPreferredSize(){ |
| Dimension size = TreeView.this.getSize(); |
| return new Dimension(size.width / 2, size.height * 3 / 5); |
| } |
| public Dimension getMinimumSize(){ |
| return new Dimension(100, 100); |
| } |
| }, |
| BorderLayout.CENTER); |
| sourcePanel.setBorder(BorderFactory.createCompoundBorder( |
| BorderFactory.createTitledBorder("Source View"), |
| BorderFactory.createEmptyBorder(4, 4, 4, 4) |
| )); |
| |
| // create the JTree and scroll pane. |
| JPanel treePanel = new JPanel(new BorderLayout()); |
| m_tree = new DOMTree(); |
| m_tree.setCellRenderer(new XMLTreeCellRenderer()); |
| m_tree.getSelectionModel().setSelectionMode |
| (TreeSelectionModel.SINGLE_TREE_SELECTION); |
| |
| // Listen for when the selection changes, call nodeSelected(node) |
| m_tree.addTreeSelectionListener( |
| new TreeSelectionListener() { |
| public void valueChanged(TreeSelectionEvent e) { |
| TreeNode node = (TreeNode) |
| (e.getPath().getLastPathComponent()); |
| |
| nodeSelected(node); |
| } |
| } |
| ); |
| m_tree.setRowHeight(18); |
| m_tree.setFont(new Font("dialog", Font.PLAIN, 12)); |
| |
| treePanel.add(new JScrollPane(m_tree) { |
| public Dimension getPreferredSize(){ |
| Dimension size = TreeView.this.getSize(); |
| return new Dimension(size.width / 2, size.height * 3 / 5); |
| } |
| public Dimension getMinimumSize(){ |
| return new Dimension(100, 100); |
| } |
| }, |
| BorderLayout.CENTER); |
| |
| treePanel.setBorder(BorderFactory.createCompoundBorder( |
| BorderFactory.createTitledBorder("Tree View"), |
| BorderFactory.createEmptyBorder(4, 4, 4, 4) |
| )); |
| |
| // refreshUI loads everthything! |
| refreshUI(filename); |
| |
| // use the new JSplitPane to dynamically resize... |
| JComponent split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, |
| true, treePanel, sourcePanel); |
| |
| JComponent mainSplitPane = |
| new JSplitPane(JSplitPane.VERTICAL_SPLIT, |
| true, split, messagePanel); |
| |
| if (DEBUG) System.out.println("END createUI:"+filename); |
| return mainSplitPane; |
| } |
| |
| /** refreshUI is called when we have a new filename to parse. |
| */ |
| void refreshUI(String filename) { |
| if (DEBUG) System.out.println("START refreshUI:"+filename); |
| |
| messageText.selectAll(); |
| messageText.cut(); |
| |
| if (filename == null || filename.equals("")) { |
| messageText.setForeground(Color.red); |
| messageText.append("No input XML filename specified:"+filename+"\n"); |
| return; |
| } |
| |
| fname = filename; |
| Document newRoot = getRoot(filename); |
| if (newRoot == null) { |
| messageText.setForeground(Color.red); |
| messageText.append("Unable to get new DOM Tree for:"+filename+"\n"); |
| return; |
| } |
| m_tree.setDocument(newRoot); |
| |
| // new Source |
| sourceText.selectAll(); |
| sourceText.cut(); |
| readXMLFile(fname, sourceText); |
| |
| setTitle(title+": "+filename); |
| |
| if (m_tree!= null) |
| expandTree(); |
| |
| |
| if (ef != null && ef.getErrorNodes()!=null |
| && ef.getErrorNodes().size() > 0 ) { |
| messageText.setForeground(Color.red); |
| messageText.append("XML source, "+fname+" has errors.\n"); |
| messageText.append("Please click on red Tree View items for details.\n"); |
| /***/ |
| Hashtable errors = ef.getErrorNodes(); |
| Enumeration keys = errors.keys(); |
| while (keys.hasMoreElements()) { |
| Node node = (Node)keys.nextElement(); |
| messageText.append("node="+node.getNodeName() |
| +", error="+((ParseError)errors.get(node)).getMsg()+"\n"); |
| } |
| } |
| if (DEBUG) System.out.println("END refreshUI:"+filename); |
| } |
| |
| /** |
| * Invoke the Parser on fname and return the root TreeNode. |
| */ |
| public Document getRoot(String filename) { |
| if (DEBUG) System.out.println("START getRoot:"+filename); |
| |
| if (filename == null || filename.equals("")) |
| return null; |
| |
| try { |
| // |
| // Reset the Error Storage and handling |
| // |
| |
| ef.resetErrors(); |
| parser.setErrorHandler(ef); |
| parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false); // otherwise parser.getCurrentNode() == null |
| parser.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true); |
| parser.setFeature("http://apache.org/xml/features/allow-java-encodings", true); |
| parser.parse(filename); |
| Document document = parser.getDocument(); |
| /***/ |
| return document; |
| } catch (Exception e) { |
| System.err.println( "Error: Invalid XML document could not get ROOT" ); |
| System.exit( 1 ); |
| //e.printStackTrace(System.err); |
| } |
| return null; |
| } |
| |
| /** read the xml file from filename and append it to the JTextArea |
| */ |
| synchronized void readXMLFile(String filename, JTextArea ta) { |
| |
| if (DEBUG) System.out.println("START readXMLFile"+filename); |
| if (filename == null || filename.equals("")) |
| return; |
| InputStream fis = null; |
| BufferedReader dis = null; |
| try { |
| java.net.URL file = createURL(filename); |
| fis = file.openStream(); |
| |
| String javaEncoding = parser.getJavaEncoding(); // get saved java encoding |
| try |
| { |
| dis = new BufferedReader(new InputStreamReader(fis, javaEncoding )); |
| } |
| catch( UnsupportedEncodingException ex ) |
| { |
| dis = new BufferedReader(new InputStreamReader(fis )); |
| } |
| } catch (Exception ex) { |
| System.err.println("ERROR: Xerces.readXMLFile: "+ex); |
| return; |
| } |
| |
| String line; |
| int i = 0; |
| |
| int len = 0; |
| textLine = new Vector(); |
| String nl = "\n"; |
| int nllen = nl.length(); |
| StringBuffer sb = new StringBuffer(); |
| |
| try{ |
| readline: while ((line = dis.readLine()) != null) { |
| sb.append(line+nl); |
| textLine.addElement(new Integer(len)); |
| len += line.length()+nllen; |
| } |
| ta.append(sb.toString()); |
| } catch (IOException io) { |
| System.err.println(io); |
| return; |
| } |
| |
| // relayout because contents have changed |
| //ta.revalidate(); |
| |
| if (DEBUG) System.out.println("END readXMLFile"+filename); |
| return; |
| |
| } |
| |
| /** called when our JTree's nodes are selected. |
| */ |
| void nodeSelected(TreeNode treeNode) { |
| |
| Node node = m_tree.getNode(treeNode); |
| |
| if( node == null ) // It is possible to get a null node |
| return; |
| |
| StringBuffer sb = new StringBuffer(); |
| messageText.selectAll(); |
| messageText.cut(); |
| |
| |
| //fix |
| |
| //JTextArea sourceText = sourceText; |
| Object errorObject = ef == null ? null : ef.getError(node); |
| if (errorObject != null) { |
| // There *is* an error in this node. |
| messageText.setForeground(Color.red); |
| ParseError eip = (ParseError)errorObject; |
| sb.append("Error: "+eip.getMsg()+"\n"); |
| int lineNo = eip.getLineNo(); |
| int pos = 0; |
| int next = 0; |
| int sizeOfTextLine = textLine.size(); |
| |
| if( lineNo < sizeOfTextLine ) |
| { |
| pos = ((Integer)textLine.elementAt(lineNo-1)).intValue(); |
| next = (lineNo == sizeOfTextLine ) ? |
| pos : |
| (((Integer)textLine.elementAt(lineNo)).intValue()); |
| } |
| else |
| { |
| pos = (( Integer) textLine.elementAt( sizeOfTextLine - 1 )).intValue(); |
| next = pos + 2; |
| } |
| |
| sourceText.select(pos, next ); |
| //m_textScrollPane.repaint(); |
| } else { |
| messageText.setForeground(Color.black); |
| sourceText.select(0, 0 ); |
| } |
| |
| //fix |
| |
| |
| if (node.getNodeType() == Node.ELEMENT_NODE |
| || node.getNodeType() == Node.TEXT_NODE |
| || node.getNodeType() == Node.CDATA_SECTION_NODE ) |
| { |
| sb.append(node.toString()); |
| } |
| |
| messageText.append(sb.toString()); |
| } |
| |
| /** called when a the text value has changed in the FileNameInput. |
| * read in new XML file. |
| */ |
| public void textValueChanged(TextEvent e) { |
| try { |
| if (fni != null) |
| fni.setVisible(false); |
| fname = ((JTextField)e.getSource()).getText(); |
| if (DEBUG) System.out.println("textValueChanged:"+fname); |
| refreshUI(fname); |
| |
| } catch (Exception ex) { |
| System.err.println( "Error: while trying to refresh gui" ); |
| System.exit( 1 ); |
| // ex.printStackTrace(); |
| } |
| } |
| |
| /** called to handle menu actions. |
| */ |
| public void actionPerformed(java.awt.event.ActionEvent e) { |
| if (DEBUG) System.err.println("ACTION: "+e.getActionCommand()+", "+e.paramString()); |
| |
| if (e.getActionCommand().equals(quitString)) { |
| System.exit(0); |
| } |
| else if (e.getActionCommand().equals(openString)) { |
| |
| fni = new FileNameInput("Open File"); |
| fni.addTextListener(this); |
| fni.setVisible(true); |
| } |
| else if (e.getActionCommand().equals(expandString)) { |
| expandTree(); |
| } |
| else if (e.getActionCommand().equals(collapseString)) { |
| int rows = m_tree.getRowCount(); |
| for (int i = 0; i < rows; i++) { |
| m_tree.collapseRow(i); |
| } |
| } |
| else |
| //if (e.getActionCommand().equals(reloadString)) { |
| refreshUI(fname); |
| //} |
| } |
| |
| void expandTree() { |
| int rows = 0; |
| for (int levels=0; levels <= 4; levels++) { |
| rows=m_tree.getRowCount(); |
| for (int i = 0; i < rows; i++) { |
| m_tree.expandRow(i); |
| } |
| } |
| } |
| |
| /* |
| * The XMLTreeCellRenderer is an inner class which enables the |
| * highlighting of errors in the tree and shows the gender values |
| * as different icons. |
| */ |
| class XMLTreeCellRenderer extends DefaultTreeCellRenderer |
| { |
| |
| public Component getTreeCellRendererComponent(JTree tree, Object value, |
| boolean selected, boolean expanded, |
| boolean leaf, int row, |
| boolean hasFocus) |
| { |
| Node node = ((DOMTree)tree).getNode(value); |
| Component comp = super.getTreeCellRendererComponent(tree, value, |
| selected, expanded, leaf, row, hasFocus); |
| if (selected) { |
| comp.setBackground(Color.blue); |
| } |
| if (ef != null |
| && ef.getErrorNodes() != null |
| && value != null |
| && node != null |
| && ef.getErrorNodes().containsKey( node )) { |
| comp.setForeground(Color.red); |
| } |
| |
| if (node != null) { |
| if (leaf) { |
| setIcon(new ImageIcon(leafImage)); |
| } else if (expanded) { |
| setIcon(new ImageIcon(openFolder)); |
| } else { |
| setIcon(new ImageIcon(closedFolder)); |
| } |
| } |
| if (node != null && node instanceof Element) { |
| |
| Element txNode = (Element)node; |
| Attr txAtt = (Attr)txNode.getAttributeNode("gender"); |
| if (txAtt != null) { |
| if (txAtt.getValue().equals("male")) { |
| setIcon(new ImageIcon("male.gif")); |
| } else |
| if (txAtt.getValue().equals("female")) { |
| setIcon(new ImageIcon("female.gif")); |
| } |
| } |
| } |
| |
| return comp; |
| } |
| } |
| |
| /* |
| * The FileNameInput is an inner class which allows the user |
| * to enter a filename. It exists due to a Swing bug which |
| * has problems with the real file input panel. |
| */ |
| class FileNameInput extends JFrame implements ActionListener { |
| |
| |
| JLabel fileLabel; |
| JTextField textField; |
| JButton ok; |
| JButton cancel; |
| Vector textListeners; |
| |
| public FileNameInput() { |
| this(""); |
| } |
| |
| public FileNameInput(String title) { |
| |
| super(title); |
| |
| fileLabel = new JLabel("Enter XML file name:"); |
| textField = new JTextField(); |
| textField.addActionListener(this); |
| ok = new JButton("ok"); |
| cancel = new JButton("cancel"); |
| JPanel buttonPanel = new JPanel(); |
| buttonPanel.add(ok); |
| buttonPanel.add(cancel); |
| ok.addActionListener(this); |
| cancel.addActionListener(this); |
| getContentPane().add(fileLabel, BorderLayout.NORTH); |
| getContentPane().add(textField, BorderLayout.CENTER); |
| getContentPane().add(buttonPanel, BorderLayout.SOUTH); |
| setSize(400,100); |
| } |
| |
| public void actionPerformed(ActionEvent e) { |
| |
| if (e.getSource() == ok || e.getSource() == textField) { |
| System.out.println("FileNameInput: pressed OK"); |
| TextEvent event = new TextEvent(textField, TextEvent.TEXT_VALUE_CHANGED); |
| deliverEvent(event); |
| setVisible(false); |
| } else |
| if (e.getSource() == cancel) { |
| System.out.println("FileNameInput: pressed cancel"); |
| setVisible(false); |
| } |
| } |
| |
| /** |
| * Adds a TextListener event listener. |
| * |
| * @param listener The listener to add. |
| * |
| * @see #removeTextListener |
| */ |
| public void addTextListener(TextListener listener) { |
| |
| // is there anything to do? |
| if (listener == null) |
| return; |
| |
| if (textListeners == null) |
| textListeners = new Vector(); |
| |
| // add listener |
| textListeners.addElement(listener); |
| } |
| |
| /** |
| * Removes a TextListener event listener. |
| * |
| * @param listener The listener to remove. |
| * |
| * @see #addTextListener |
| */ |
| public void removeTextListener(TextListener listener) { |
| |
| // is there anything to do? |
| if (listener == null || textListeners == null) |
| return; |
| |
| // add listener |
| textListeners.removeElement(listener); |
| } |
| |
| |
| /** |
| * This function delivers TextListener events, when the ok |
| * button is clicked. |
| * |
| * @param evt The event to deliver. |
| */ |
| protected void deliverEvent(EventObject evt) { |
| |
| if (evt instanceof TextEvent) { |
| TextEvent event = (TextEvent)evt; |
| |
| Vector l; |
| synchronized (textListeners) { l = (Vector)textListeners.clone(); } |
| |
| int size = l.size(); |
| for (int i = 0; i < size; i++) |
| ((TextListener)l.elementAt(i)).textValueChanged(event); |
| } |
| } |
| } |
| |
| // |
| // Create a URL object from either a URL string or a plain file name. |
| // |
| static URL createURL(String name) throws Exception { |
| try { |
| URL u = new URL(name); |
| return u; |
| } catch (MalformedURLException ex) { |
| } |
| URL u = new URL("file:" + new File(name).getAbsolutePath()); |
| return u; |
| } |
| |
| /** |
| * The ErrorStorer maps Nodes to errors. It receives a reference |
| * to the ErrorTreeFactory in the Constructor. |
| * |
| * When error is called, it asks the |
| * ErrorTreeFactory for the current node, and uses this as the |
| * "key" of a Hashtable, with the error as a value. The error |
| * value is wrapped up nicely in an ParseError object. |
| * |
| * It is used in the XML Tutorial to illustrate how to implement |
| * the ErrorListener to provide error storage for later reference. |
| * |
| */ |
| class ErrorStorer |
| implements ErrorHandler |
| |
| { |
| |
| // |
| // Data |
| // |
| Hashtable errorNodes = null; |
| |
| /** |
| * Constructor |
| */ |
| public ErrorStorer() { |
| } |
| |
| /** |
| * The client is is allowed to get a reference to the Hashtable, |
| * and so could corrupt it, or add to it... |
| */ |
| public Hashtable getErrorNodes() { |
| return errorNodes; |
| } |
| |
| /** |
| * The ParseError object for the node key is returned. |
| * If the node doesn't have errors, null is returned. |
| */ |
| public Object getError(Node node) { |
| if (errorNodes == null) |
| return null; |
| return errorNodes.get(node); |
| } |
| |
| /** |
| * Reset the error storage. |
| */ |
| public void resetErrors() { |
| if (errorNodes != null) |
| errorNodes.clear(); |
| } |
| |
| /***/ |
| public void warning(SAXParseException ex) { |
| handleError(ex, WARNING); |
| } |
| |
| public void error(SAXParseException ex) { |
| handleError(ex, ERROR); |
| } |
| |
| public void fatalError(SAXParseException ex) throws SAXException { |
| handleError(ex, FATAL_ERROR); |
| } |
| |
| private void handleError(SAXParseException ex, int type) { |
| System.out.println("!!! handleError: "+ex.getMessage()); |
| |
| StringBuffer errorString = new StringBuffer(); |
| errorString.append("at line number, "); |
| errorString.append(ex.getLineNumber()); |
| errorString.append(": "); |
| errorString.append(ex.getMessage()); |
| |
| // Node current = parser.getCurrentNode(); |
| |
| Node current = null ; |
| |
| try |
| { |
| current = ( Node ) parser.getProperty( "http://apache.org/xml/properties/dom/current-element-node" ); |
| |
| } |
| catch( SAXException exception ) |
| { |
| ; |
| } |
| |
| if (current == null) { |
| System.err.println("Error in handleError. getCurrentNode()==null!"); |
| return; |
| } |
| |
| if (errorNodes == null) |
| errorNodes = new Hashtable(); |
| ParseError previous = (ParseError) errorNodes.get(current); |
| ParseError eip = null; |
| // if a Node already has an error, we accumulate the text here... |
| if (previous != null) { |
| eip = previous; |
| errorString = new StringBuffer(previous.getMsg()+"\n"+errorString.toString()); |
| eip.setMsg(errorString.toString()); |
| } else { |
| eip = new |
| ParseError( |
| ex.getSystemId(), |
| ex.getLineNumber(), |
| ex.getColumnNumber(), |
| "", |
| errorString.toString()); |
| } |
| |
| // put it in the Hashtable. |
| errorNodes.put(current, eip); |
| } |
| |
| } |
| |
| /** |
| * The ParseError class wraps up all the error info from |
| * the ErrorStorer's error method. |
| * |
| * @see ErrorStorer |
| */ |
| class ParseError extends Object { |
| |
| // |
| // Data |
| // |
| |
| String fileName; |
| int lineNo; |
| int charOffset; |
| Object key; |
| String msg; |
| |
| /** |
| * Constructor |
| */ |
| public ParseError(String fileName, int lineNo, int charOffset, |
| Object key, |
| String msg) |
| { |
| this. fileName=fileName; |
| this. lineNo=lineNo; |
| this. charOffset=charOffset; |
| this. key=key; |
| this. msg=msg; |
| } |
| |
| // |
| // Getters... |
| // |
| public String getFileName() { return fileName; } |
| public int getLineNo() { return lineNo; } |
| public int getCharOffset() { return charOffset;} |
| public Object getKey() { return key; } |
| public String getMsg() { return msg; } |
| public void setMsg(String s) { msg = s; } |
| } |
| |
| |
| // |
| // Main |
| // |
| |
| /** Main program entry point. */ |
| public static void main(String argv[]) { |
| |
| // vars |
| int parserNameIndex = -1; |
| String parserName = DEFAULT_PARSER_NAME; |
| |
| // check parameters |
| for (int i = 0; i < argv.length; i++) { |
| String arg = argv[i]; |
| |
| // options |
| if (arg.startsWith("-")) { |
| if (arg.equals("-p")) { |
| if (i == argv.length - 1) { |
| System.err.println("error: missing parser class"); |
| System.exit(1); |
| } |
| parserName = argv[++i]; |
| parserNameIndex = i; |
| continue; |
| } |
| |
| if (arg.equals("-h")) { |
| printUsage(); |
| System.exit(1); |
| } |
| } |
| |
| // print uri |
| System.err.println(arg+':'); |
| |
| JFrame frame = null; |
| if (parserNameIndex == argv.length-1) { |
| // null behaviour is blank screen - eg no JTree, or file dispalyed |
| frame = new TreeView(""); |
| } else { |
| frame = new TreeView(arg); |
| } |
| frame.addWindowListener(new java.awt.event.WindowAdapter() { |
| public void windowClosing(java.awt.event.WindowEvent e) { |
| System.exit(0); |
| } |
| }); |
| frame.setSize(790, 590); |
| frame.setVisible(true); |
| } |
| } // main(String[]) |
| |
| /** Prints the usage. */ |
| private static void printUsage() { |
| |
| System.err.println("usage: java ui.TreeViewer (options) uri ..."); |
| System.err.println(); |
| System.err.println("options:"); |
| System.err.println(" -p name Specify DOM parser class by name."); |
| System.err.println(" Default parser: "+DEFAULT_PARSER_NAME); |
| System.err.println(" -h This help screen."); |
| |
| } // printUsage() |
| |
| } // class TreeViewer |