1 /*
2 * Copyright 2002 - 2007 JEuclid, http://jeuclid.sf.net
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /* $Id: SAXBuilder.java 422 2007-08-16 09:36:52Z maxberger $ */
18
19 package net.sourceforge.jeuclid;
20
21 import java.util.Stack;
22
23 import net.sourceforge.jeuclid.elements.AbstractJEuclidElement;
24 import net.sourceforge.jeuclid.elements.JEuclidElementFactory;
25 import net.sourceforge.jeuclid.elements.generic.DocumentElement;
26 import net.sourceforge.jeuclid.elements.support.attributes.AttributeMap;
27 import net.sourceforge.jeuclid.elements.support.attributes.SAXAttributeMap;
28
29 import org.w3c.dom.Node;
30 import org.w3c.dom.mathml.MathMLElement;
31 import org.xml.sax.Attributes;
32 import org.xml.sax.ContentHandler;
33 import org.xml.sax.Locator;
34
35 /**
36 * Generator for creating a MathElement tree from SAX events.
37 *
38 * @author <a href="mailto:stephan@vern.chem.tu-berlin.de">Stephan Michels</a>
39 * @author Max Berger
40 * @version $Revision: 422 $
41 */
42 public class SAXBuilder implements ContentHandler {
43 private DocumentElement rootElement;
44
45 private final Stack<Node> stack = new Stack<Node>();;
46
47 private final MathBase mbase;
48
49 /**
50 * Logger for this class.
51 */
52 // unused
53 // private static final Log LOGGER =
54 // LogFactory.getLog(SAXMathBuilder.class);
55 /**
56 * default constructor.
57 */
58 public SAXBuilder() {
59 this.mbase = new MathBase(MathBase.getDefaultParameters());
60 }
61
62 /**
63 * Returns the created math root element.
64 *
65 * @return Math root element
66 */
67 public DocumentElement getMathRootElement() {
68 return this.rootElement;
69 }
70
71 /**
72 * Receive notification of character data.
73 *
74 * @param ch
75 * The characters from the XML document.
76 * @param start
77 * The start position in the array.
78 * @param length
79 * The number of characters to read from the array.
80 */
81 public void characters(final char[] ch, final int start, final int length) {
82 if (!this.stack.empty()) {
83 ((AbstractJEuclidElement) this.stack.peek()).addText(new String(
84 ch, start, length));
85 }
86 }
87
88 /**
89 * Receive notification of the end of a document.
90 */
91 public void endDocument() {
92 this.rootElement.fireChangeForSubTree();
93 }
94
95 /**
96 * Receive notification of the end of an element.
97 *
98 * @param namespaceURI
99 * The Namespace URI, or the empty string if the element has no
100 * Namespace URI or if Namespace processing is not being
101 * performed.
102 * @param localName
103 * The local name (without prefix), or the empty string if
104 * Namespace processing is not being performed.
105 * @param qName
106 * The qualified XML 1.0 name (with prefix), or the empty
107 * string if qualified names are not available.
108 */
109 public void endElement(final String namespaceURI, final String localName,
110 final String qName) {
111 if (!this.stack.empty()) {
112 this.stack.pop();
113
114 }
115 }
116
117 /**
118 * Receive notification of the beginning of a document.
119 */
120 public void startDocument() {
121 this.rootElement = null;
122 this.stack.clear();
123 this.rootElement = new DocumentElement(this.mbase);
124 this.mbase.setRootElement(this.rootElement);
125 this.stack.push(this.rootElement);
126 }
127
128 /**
129 * Receive notification of the beginning of an element.
130 *
131 * @param namespaceURI
132 * The Namespace URI, or the empty string if the element has no
133 * Namespace URI or if Namespace processing is not being
134 * performed.
135 * @param localName
136 * The local name (without prefix), or the empty string if
137 * Namespace processing is not being performed.
138 * @param qName
139 * The qualified name (with prefix), or the empty string if
140 * qualified names are not available.
141 * @param attributes
142 * The attributes attached to the element. If there are no
143 * attributes, it shall be an empty Attributes object.
144 */
145 public void startElement(final String namespaceURI,
146 final String localName, final String qName,
147 final Attributes attributes) {
148 if (this.stack.empty()) {
149 return;
150 }
151
152 final AttributeMap aMap = new SAXAttributeMap(attributes);
153 final MathMLElement element = JEuclidElementFactory.elementFromName(
154 localName, aMap, this.mbase);
155
156 if (!this.stack.empty()) {
157 this.stack.peek().appendChild(element);
158 }
159
160 this.stack.push(element);
161 }
162
163 /**
164 * End the scope of a prefix-URI mapping.
165 *
166 * @param prefix
167 * Prefix
168 */
169 public void endPrefixMapping(final String prefix) {
170 }
171
172 /**
173 * Receive notification of ignorable whitespace in element content.
174 *
175 * @param ch
176 * Space char
177 * @param start
178 * Start position
179 * @param length
180 * Length
181 */
182 public void ignorableWhitespace(final char[] ch, final int start,
183 final int length) {
184 }
185
186 /**
187 * Receive notification of a processing instruction.
188 *
189 * @param target
190 * Target
191 * @param data
192 * Data
193 */
194 public void processingInstruction(final String target, final String data) {
195 }
196
197 /**
198 * Receive an object for locating the origin of SAX document events.
199 *
200 * @param locator
201 * Locator
202 */
203 public void setDocumentLocator(final Locator locator) {
204 }
205
206 /**
207 * Receive notification of a skipped entity.
208 *
209 * @param name
210 * Entity name
211 */
212 public void skippedEntity(final String name) {
213 }
214
215 /**
216 * Begin the scope of a prefix-URI Namespace mapping.
217 *
218 * @param prefix
219 * Prefix
220 * @param uri
221 * Uri
222 */
223 public void startPrefixMapping(final String prefix, final String uri) {
224 }
225
226 }