001: /*
002: * $Id: BaseXMLStreamReader.java,v 1.2 2004/07/15 02:51:32 cniles Exp $
003: *
004: * Copyright (c) 2004, Christian Niles, unit12.net
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions are met:
009: *
010: * * Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * * Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: *
017: * * Neither the name of Christian Niles, Unit12, nor the names of its
018: * contributors may be used to endorse or promote products derived from
019: * this software without specific prior written permission.
020: *
021: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
022: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
023: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
024: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
025: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
026: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
027: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
028: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
029: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
030: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
031: * POSSIBILITY OF SUCH DAMAGE.
032: *
033: */
034: package javanet.staxutils;
035:
036: import javanet.staxutils.SimpleLocation;
037: import javanet.staxutils.StaticLocation;
038: import javanet.staxutils.XMLStreamUtils;
039: import javanet.staxutils.error.IllegalStreamStateException;
040:
041: import javax.xml.namespace.QName;
042: import javax.xml.stream.Location;
043: import javax.xml.stream.XMLStreamConstants;
044: import javax.xml.stream.XMLStreamException;
045: import javax.xml.stream.XMLStreamReader;
046:
047: /**
048: * Abstract base class for {@link XMLStreamReader} implementations.
049: *
050: * @author Christian Niles
051: * @version $Revision: 1.2 $
052: */
053: public abstract class BaseXMLStreamReader implements XMLStreamReader {
054:
055: /** The stream system ID. */
056: protected String systemId;
057:
058: /** The stream encoding. */
059: protected String encoding;
060:
061: public BaseXMLStreamReader() {
062:
063: }
064:
065: public BaseXMLStreamReader(String systemId, String encoding) {
066:
067: this .systemId = systemId;
068: this .encoding = encoding;
069:
070: }
071:
072: public String getSystemId() {
073:
074: return systemId;
075:
076: }
077:
078: public String getEncoding() {
079:
080: return encoding;
081:
082: }
083:
084: /**
085: * Returns the name of the current event type.
086: *
087: * @return The name of the current event type.
088: */
089: public String getEventTypeName() {
090:
091: return XMLStreamUtils.getEventTypeName(getEventType());
092:
093: }
094:
095: public int nextTag() throws XMLStreamException {
096:
097: for (int eventType = next(); hasNext(); eventType = next()) {
098:
099: switch (eventType) {
100:
101: case START_ELEMENT:
102: case END_ELEMENT:
103: return eventType;
104:
105: case CHARACTERS:
106: case CDATA:
107: if (!isWhiteSpace()) {
108: // throw an error
109: break;
110: } else {
111: // fall through
112: }
113:
114: case SPACE:
115: case PROCESSING_INSTRUCTION:
116: case COMMENT:
117: // skip it
118: continue;
119:
120: default:
121: // stop and throw an error
122: break;
123:
124: }
125:
126: }
127:
128: throw new XMLStreamException("Encountered "
129: + getEventTypeName()
130: + " when expecting START_ELEMENT or END_ELEMENT",
131: getStableLocation());
132:
133: }
134:
135: public boolean isCharacters() {
136:
137: return getEventType() == XMLStreamConstants.CHARACTERS;
138:
139: }
140:
141: public boolean isEndElement() {
142:
143: return getEventType() == XMLStreamConstants.END_ELEMENT;
144:
145: }
146:
147: public boolean isStartElement() {
148:
149: return getEventType() == XMLStreamConstants.START_ELEMENT;
150:
151: }
152:
153: public boolean isWhiteSpace() {
154:
155: return getEventType() == XMLStreamConstants.SPACE;
156:
157: }
158:
159: public boolean hasName() {
160:
161: switch (getEventType()) {
162:
163: case XMLStreamConstants.START_ELEMENT:
164: case XMLStreamConstants.END_ELEMENT:
165: return true;
166:
167: default:
168: return false;
169:
170: }
171:
172: }
173:
174: public String getPrefix() {
175:
176: switch (getEventType()) {
177:
178: case XMLStreamConstants.START_ELEMENT:
179: case XMLStreamConstants.END_ELEMENT:
180: return getName().getPrefix();
181:
182: default:
183: throw new IllegalStreamStateException(
184: "Expected START_ELEMENT or END_ELEMENT but was "
185: + getEventTypeName(), getStableLocation());
186:
187: }
188:
189: }
190:
191: public boolean hasText() {
192:
193: switch (getEventType()) {
194:
195: case XMLStreamConstants.SPACE:
196: case XMLStreamConstants.CHARACTERS:
197: case XMLStreamConstants.COMMENT:
198: case XMLStreamConstants.CDATA:
199: case XMLStreamConstants.ENTITY_REFERENCE:
200: return true;
201:
202: default:
203: return false;
204:
205: }
206:
207: }
208:
209: public String getNamespaceURI(String prefix) {
210:
211: if (prefix == null) {
212:
213: throw new IllegalArgumentException(
214: "Namespace prefix was null");
215:
216: }
217:
218: return getNamespaceContext().getNamespaceURI(prefix);
219:
220: }
221:
222: public String getNamespaceURI() {
223:
224: switch (getEventType()) {
225:
226: case XMLStreamConstants.START_ELEMENT:
227: case XMLStreamConstants.END_ELEMENT:
228: return getName().getNamespaceURI();
229:
230: default:
231: throw new IllegalStreamStateException(
232: "Expected START_ELEMENT or END_ELEMENT state, but found "
233: + getEventTypeName(), getStableLocation());
234:
235: }
236:
237: }
238:
239: public String getAttributeLocalName(int index) {
240:
241: return getAttributeName(index).getLocalPart();
242:
243: }
244:
245: public String getAttributeNamespace(int index) {
246:
247: return getAttributeName(index).getNamespaceURI();
248:
249: }
250:
251: public String getAttributePrefix(int index) {
252:
253: return getAttributeName(index).getPrefix();
254:
255: }
256:
257: public void require(int type, String namespaceURI, String localName)
258: throws XMLStreamException {
259:
260: int currType = getEventType();
261: if (currType != type) {
262:
263: throw new XMLStreamException("Expected "
264: + XMLStreamUtils.getEventTypeName(type)
265: + " but found "
266: + XMLStreamUtils.getEventTypeName(currType),
267: getStableLocation());
268:
269: }
270:
271: }
272:
273: public String getElementText() throws XMLStreamException {
274:
275: if (getEventType() != XMLStreamConstants.START_ELEMENT) {
276:
277: throw new XMLStreamException(
278: "Expected START_ELEMENT but found "
279: + getEventTypeName(), getStableLocation());
280:
281: }
282:
283: // save the element name and location so we can use it in the error message
284: // as needed.
285: QName elemName = getName();
286: Location elemLocation = getStableLocation();
287:
288: // read text events until the end tag is reached
289: StringBuffer content = null;
290: for (int eventType = next(); eventType != END_ELEMENT; eventType = next()) {
291:
292: if (hasText()) {
293:
294: if (content == null) {
295:
296: content = new StringBuffer();
297:
298: }
299: content.append(getText());
300:
301: } else {
302:
303: throw new XMLStreamException(
304: "Encountered " + getEventTypeName()
305: + " event within text-only element "
306: + elemName, elemLocation);
307:
308: }
309:
310: }
311:
312: // return content
313: return (content == null ? "" : content.toString());
314:
315: }
316:
317: /**
318: * Constructs a new, stable {@link Location} from the current stream location.
319: * If the stream location implements {@link StaticLocation}, then the stream
320: * location will be returned directly.
321: *
322: * @return Constructs a new, stable {@link Location} from the current stream
323: * location, or the current {@link Location} itself if it is already
324: * stable.
325: */
326: public Location getStableLocation() {
327:
328: Location location = getLocation();
329: if (!(location instanceof StaticLocation)) {
330:
331: // create copy
332: location = new SimpleLocation(location);
333:
334: }
335:
336: return location;
337:
338: }
339:
340: }
|