Frames | No Frames |
1: /* ======================================================================== 2: * JCommon : a free general purpose class library for the Java(tm) platform 3: * ======================================================================== 4: * 5: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 6: * 7: * Project Info: http://www.jfree.org/jcommon/index.html 8: * 9: * This library is free software; you can redistribute it and/or modify it 10: * under the terms of the GNU Lesser General Public License as published by 11: * the Free Software Foundation; either version 2.1 of the License, or 12: * (at your option) any later version. 13: * 14: * This library is distributed in the hope that it will be useful, but 15: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 17: * License for more details. 18: * 19: * You should have received a copy of the GNU Lesser General Public 20: * License along with this library; if not, write to the Free Software 21: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 22: * USA. 23: * 24: * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 25: * in the United States and other countries.] 26: * 27: * ----------- 28: * Parser.java 29: * ----------- 30: * (C)opyright 2003-2005, by Thomas Morgner and Contributors. 31: * 32: * Original Author: Thomas Morgner (taquera@sherito.org); 33: * Contributor(s): David Gilbert (for Object Refinery Limited); 34: * 35: * $Id: Parser.java,v 1.8 2005/11/14 10:58:02 mungady Exp $ 36: * 37: * Changes 38: * ------- 39: * 09-Jan-2003 : Initial version. 40: * 29-Apr-2003 : Distilled from the JFreeReport project and moved into JCommon 41: * 14-Jul-2003 : More help with the error location given by catching all exceptions. 42: * 43: */ 44: 45: package org.jfree.xml; 46: 47: import java.util.HashMap; 48: import java.util.Stack; 49: 50: import org.xml.sax.Attributes; 51: import org.xml.sax.SAXException; 52: 53: /** 54: * The Parser handles the SAXEvents and forwards the event call to the currently 55: * active ElementDefinitionHandler. Contains methods to manage and 56: * configure the parsing process. 57: * <p> 58: * An initial report definition handler must be set before the parser can be used. 59: * 60: * @author Thomas Morgner 61: */ 62: public abstract class Parser extends FrontendDefaultHandler { 63: 64: /** A key for the content base. */ 65: public static final String CONTENTBASE_KEY = "content-base"; 66: 67: /** A stack for the active factories. */ 68: private Stack activeFactories; 69: 70: /** The initial factory. */ 71: private ElementDefinitionHandler initialFactory; 72: 73: /** Storage for temporary objects and factories used during the parsing process. */ 74: private HashMap parserHelperObjects; 75: 76: /** 77: * Creates a new parser. 78: */ 79: public Parser() { 80: this.activeFactories = new Stack(); 81: this.parserHelperObjects = new HashMap(); 82: } 83: 84: /** 85: * Returns the currently collected comments. 86: * @return the comments. 87: */ 88: public String[] getComments() { 89: return getCommentHandler().getComments(); 90: } 91: 92: /** 93: * Pushes a handler onto the stack. 94: * 95: * @param factory the handler. 96: */ 97: public void pushFactory(final ElementDefinitionHandler factory) { 98: this.activeFactories.push(factory); 99: } 100: 101: /** 102: * Reads a handler off the stack without removing it. 103: * 104: * @return The handler. 105: */ 106: public ElementDefinitionHandler peekFactory() { 107: return (ElementDefinitionHandler) this.activeFactories.peek(); 108: } 109: 110: /** 111: * Pops a handler from the stack. 112: * 113: * @return The handler. 114: */ 115: public ElementDefinitionHandler popFactory() { 116: this.activeFactories.pop(); 117: return peekFactory(); 118: } 119: 120: /** 121: * Receive notification of the end of the document. 122: * 123: * <p>By default, do nothing. Application writers may override this 124: * method in a subclass to take specific actions at the end 125: * of a document (such as finalising a tree or closing an output 126: * file).</p> 127: * 128: * @exception SAXException Any SAX exception, possibly wrapping another exception. 129: * 130: * @see org.xml.sax.ContentHandler#endDocument 131: */ 132: public void endDocument() throws SAXException { 133: // ignored 134: } 135: 136: /** 137: * Receive notification of the beginning of the document. 138: * 139: * <p>By default, do nothing. Application writers may override this 140: * method in a subclass to take specific actions at the beginning 141: * of a document (such as allocating the root node of a tree or 142: * creating an output file).</p> 143: * 144: * @exception SAXException Any SAX exception, possibly wrapping another exception. 145: * @see org.xml.sax.ContentHandler#startDocument 146: */ 147: public void startDocument() throws SAXException { 148: this.activeFactories.clear(); 149: pushFactory(getInitialFactory()); 150: } 151: 152: /** 153: * Receive notification of character data inside an element. 154: * 155: * <p>By default, do nothing. Application writers may override this 156: * method to take specific actions for each chunk of character data 157: * (such as adding the data to a node or buffer, or printing it to 158: * a file).</p> 159: * 160: * @param ch the characters. 161: * @param start the start position in the character array. 162: * @param length the number of characters to use from the character array. 163: * 164: * @exception SAXException Any SAX exception, possibly wrapping another exception. 165: * @see org.xml.sax.ContentHandler#characters 166: */ 167: public void characters(final char[] ch, final int start, final int length) 168: throws SAXException { 169: try { 170: peekFactory().characters(ch, start, length); 171: } 172: catch (ParseException pe) { 173: throw pe; 174: } 175: catch (Exception e) { 176: throw new ParseException(e, getLocator()); 177: } 178: } 179: 180: /** 181: * Receive notification of the end of an element. 182: * 183: * <p>By default, do nothing. Application writers may override this 184: * method in a subclass to take specific actions at the end of 185: * each element (such as finalising a tree node or writing 186: * output to a file).</p> 187: * 188: * @param uri the URI. 189: * @param localName the element type name. 190: * @param qName the name. 191: * 192: * @exception SAXException Any SAX exception, possibly 193: * wrapping another exception. 194: * @see org.xml.sax.ContentHandler#endElement 195: */ 196: public void endElement(final String uri, final String localName, final String qName) 197: throws SAXException { 198: try { 199: peekFactory().endElement(qName); 200: } 201: catch (ParseException pe) { 202: throw pe; 203: } 204: catch (Exception e) { 205: throw new ParseException(e, getLocator()); 206: } 207: finally { 208: getCommentHandler().clearComments(); 209: } 210: } 211: 212: 213: /** 214: * Receive notification of the start of an element. 215: * 216: * <p>By default, do nothing. Application writers may override this 217: * method in a subclass to take specific actions at the start of 218: * each element (such as allocating a new tree node or writing 219: * output to a file).</p> 220: * 221: * @param uri the URI. 222: * @param localName the element type name. 223: * @param qName the name. 224: * @param attributes the specified or defaulted attributes. 225: * 226: * @exception SAXException Any SAX exception, possibly 227: * wrapping another exception. 228: * @see org.xml.sax.ContentHandler#startElement 229: */ 230: public void startElement(final String uri, final String localName, 231: final String qName, final Attributes attributes) 232: throws SAXException { 233: try { 234: peekFactory().startElement(qName, attributes); 235: } 236: catch (ParseException pe) { 237: throw pe; 238: } 239: catch (Exception e) { 240: throw new ParseException(e, getLocator()); 241: } 242: finally { 243: getCommentHandler().clearComments(); 244: } 245: } 246: 247: /** 248: * Sets the initial handler. 249: * 250: * @param factory the initial handler. 251: */ 252: public void setInitialFactory(final ElementDefinitionHandler factory) { 253: this.initialFactory = factory; 254: } 255: 256: /** 257: * Returns the initial handler. 258: * 259: * @return The initial handler. 260: */ 261: public ElementDefinitionHandler getInitialFactory() { 262: return this.initialFactory; 263: } 264: 265: /** 266: * Sets a helper object. 267: * 268: * @param key the key. 269: * @param value the value. 270: */ 271: public void setHelperObject(final String key, final Object value) { 272: if (value == null) { 273: this.parserHelperObjects.remove(key); 274: } 275: else { 276: this.parserHelperObjects.put(key, value); 277: } 278: } 279: 280: /** 281: * Returns a helper object. 282: * 283: * @param key the key. 284: * 285: * @return The object. 286: */ 287: public Object getHelperObject(final String key) { 288: return this.parserHelperObjects.get(key); 289: } 290: 291: /** 292: * Returns a new instance of the parser. 293: * 294: * @return a new instance of the parser. 295: */ 296: public abstract Parser getInstance(); 297: 298: 299: public final FrontendDefaultHandler newInstance() { 300: return getInstance(); 301: } 302: 303: /** 304: * Returns the parsed result object after the parsing is complete. Calling 305: * this function during the parsing is undefined and may result in an 306: * IllegalStateException. 307: * 308: * @return the parsed result. 309: */ 310: public abstract Object getResult(); 311: }