Source code: org/objectstyle/cayenne/util/AbstractHandler.java
1 /* ====================================================================
2 *
3 * The ObjectStyle Group Software License, Version 1.0
4 *
5 * Copyright (c) 2002-2003 The ObjectStyle Group
6 * and individual authors of the software. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. The end-user documentation included with the redistribution, if
21 * any, must include the following acknowlegement:
22 * "This product includes software developed by the
23 * ObjectStyle Group (http://objectstyle.org/)."
24 * Alternately, this acknowlegement may appear in the software itself,
25 * if and wherever such third-party acknowlegements normally appear.
26 *
27 * 4. The names "ObjectStyle Group" and "Cayenne"
28 * must not be used to endorse or promote products derived
29 * from this software without prior written permission. For written
30 * permission, please contact andrus@objectstyle.org.
31 *
32 * 5. Products derived from this software may not be called "ObjectStyle"
33 * nor may "ObjectStyle" appear in their names without prior written
34 * permission of the ObjectStyle Group.
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This software consists of voluntary contributions made by many
51 * individuals on behalf of the ObjectStyle Group. For more
52 * information on the ObjectStyle Group, please see
53 * <http://objectstyle.org/>.
54 *
55 */
56 package org.objectstyle.cayenne.util;
57
58 import org.xml.sax.Attributes;
59 import org.xml.sax.ContentHandler;
60 import org.xml.sax.SAXException;
61 import org.xml.sax.XMLReader;
62 import org.xml.sax.helpers.DefaultHandler;
63
64
65 /**
66 * The common superclass for all SAX event handlers used to parse
67 * the configuration file. Each method just throws an exception,
68 * so subclasses should override what they can handle.
69 *
70 * Each type of XML element (map, node, etc.) has
71 * a specific subclass.
72 *
73 * In the constructor, this class takes over the handling of SAX
74 * events from the parent handler and returns
75 * control back to the parent in the endElement method.
76 * <p>
77 * The idea to use nested handlers for XML document parsing
78 * (and code to implement it) were taken from org.apache.tools.ant.ProjectHelper
79 * from Jakarta-Ant project (Copyright: Apache Software Foundation).
80 * This may not be the best way to build objects from XML, but it is rather
81 * consistent. For each nested element in the XML tree a dedicated handler
82 * is created (subclass of this AbstractHandler). Once the element is parsed,
83 * control is handled back to the parent handler.
84 * </p>
85 *
86 * @author Andrei Adamchik
87 */
88 public class AbstractHandler extends DefaultHandler {
89 /** Current parser. */
90 protected XMLReader parser;
91
92 /** Previous handler for the document.
93 * When the next element is finished, control returns
94 * to this handler. */
95 protected ContentHandler parentHandler;
96
97 /**
98 * Creates a handler and sets the parser to use it
99 * for the current element.
100 *
101 * @param parser Currently used XML parser.
102 * Must not be <code>null</code>.
103 * @param parentHandler The handler which should be restored to the
104 * parser at the end of the element.
105 * Must not be <code>null</code>.
106 */
107 public AbstractHandler(XMLReader parser, ContentHandler parentHandler) {
108 this.parentHandler = parentHandler;
109 this.parser = parser;
110
111 // Start handling SAX events
112 parser.setContentHandler(this);
113 }
114
115 /** Returns currently used XMLReader. */
116 public XMLReader getParser() {
117 return parser;
118 }
119
120
121 /**
122 * Handles the start of an element. This base implementation just
123 * throws an exception.
124 *
125 * @param tag The name of the element being started.
126 * Will not be <code>null</code>.
127 * @param attrs Attributes of the element being started.
128 * Will not be <code>null</code>.
129 *
130 * @exception SAXException if this method is not overridden, or in
131 * case of error in an overridden version
132 */
133 public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
134 throws SAXException {
135 throw new SAXException(this.getClass().getName() + ": unexpected element \"" + localName + "\"");
136 }
137
138 /**
139 * Handles text within an element. This base implementation just
140 * throws an exception.
141 *
142 * @param buf A character array of the text within the element.
143 * Will not be <code>null</code>.
144 * @param start The start element in the array.
145 * @param count The number of characters to read from the array.
146 *
147 * @exception SAXException if this method is not overridden, or in
148 * case of error in an overridden version
149 */
150 public void characters(char[] buf, int start, int count) throws SAXException {
151 String s = new String(buf, start, count).trim();
152
153 if (s.length() > 0) {
154 throw new SAXException(this.getClass().getName() + ": unexpected text \"" + s + "\"");
155 }
156 }
157
158 /**
159 * Called when this element and all elements nested into it have been
160 * handled.
161 */
162 protected void finished() {}
163
164
165 /**
166 * Handles the end of an element. Any required clean-up is performed
167 * by the finished() method and then the original handler is restored to
168 * the parser.
169 *
170 * @see #finished()
171 */
172 public void endElement(String namespaceURI, String localName, String qName)
173 throws SAXException {
174 finished();
175 // Let parent resume handling SAX events
176 parser.setContentHandler(parentHandler);
177 }
178 }
179