001: /*
002: * $Id: XMLStreamFilterImpl.java,v 1.7 2006/12/01 18:47:07 joehw Exp $
003: */
004:
005: /*
006: * The contents of this file are subject to the terms
007: * of the Common Development and Distribution License
008: * (the License). You may not use this file except in
009: * compliance with the License.
010: *
011: * You can obtain a copy of the license at
012: * https://glassfish.dev.java.net/public/CDDLv1.0.html.
013: * See the License for the specific language governing
014: * permissions and limitations under the License.
015: *
016: * When distributing Covered Code, include this CDDL
017: * Header Notice in each file and include the License file
018: * at https://glassfish.dev.java.net/public/CDDLv1.0.html.
019: * If applicable, add the following below the CDDL Header,
020: * with the fields enclosed by brackets [] replaced by
021: * you own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * [Name of File] [ver.__] [Date]
025: *
026: * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
027: */
028:
029: package com.sun.xml.stream;
030:
031: import javax.xml.XMLConstants;
032: import javax.xml.stream.Location;
033: import javax.xml.stream.XMLStreamReader;
034: import javax.xml.stream.StreamFilter;
035: import javax.xml.stream.XMLStreamException;
036: import javax.xml.namespace.QName;
037: import javax.xml.stream.events.XMLEvent;
038:
039: /**
040: *
041: * @author Joe Wang:
042: * This is an effort to simplify the impl and make the filtered stream reader more compatible
043: * with those in other implementations. Note however, that this version will not solve all the issues
044: * related to the undefined condition in the spec. The No.1 priority is that the simplified impl would
045: * still pass the TCK. Problems arising due to the requirement, such as if hasNext() should advance
046: * the underlining stream, would have to wait until 1.1 in which the filtered stream reader would be
047: * defined more clearly.
048: */
049:
050: public class XMLStreamFilterImpl implements
051: javax.xml.stream.XMLStreamReader {
052:
053: private StreamFilter fStreamFilter = null;
054: private XMLStreamReader fStreamReader = null;
055: private int fCurrentEvent;
056: private boolean fEventAccepted = false;
057:
058: /**the very issue around a long discussion. but since we must pass the TCK, we decide to allow
059: * hasNext() to advance the underlining stream in order to find the next acceptable event
060: */
061: private boolean fStreamAdvancedByHasNext = false;
062:
063: /** Creates a new instance of XMLStreamFilterImpl */
064:
065: public XMLStreamFilterImpl(XMLStreamReader reader,
066: StreamFilter filter) {
067: fStreamReader = reader;
068: this .fStreamFilter = filter;
069:
070: //this is debatable to initiate at an acceptable event,
071: //but it's neccessary in order to pass the TCK and yet avoid skipping element
072: try {
073: if (fStreamFilter.accept(fStreamReader)) {
074: fEventAccepted = true;
075: } else {
076: findNextEvent();
077: }
078: } catch (XMLStreamException xs) {
079: System.err.println("Error while creating a stream Filter"
080: + xs);
081: }
082: }
083:
084: /**
085: *
086: * @param sf
087: */
088: protected void setStreamFilter(StreamFilter sf) {
089: this .fStreamFilter = sf;
090: }
091:
092: /**
093: *
094: * @return
095: * @throws XMLStreamException
096: */
097: public int next() throws XMLStreamException {
098: if (fStreamAdvancedByHasNext && fEventAccepted) {
099: fStreamAdvancedByHasNext = false;
100: return fCurrentEvent;
101: }
102: int event = findNextEvent();
103: if (event != -1) {
104: return event;
105: }
106:
107: throw new IllegalStateException(
108: "The stream reader has reached the end of the document, or there are no more "
109: + " items to return");
110: }
111:
112: /**
113: *
114: * @throws XMLStreamException
115: * @return
116: */
117: public int nextTag() throws XMLStreamException {
118: if (fStreamAdvancedByHasNext
119: && fEventAccepted
120: && (fCurrentEvent == XMLEvent.START_ELEMENT || fCurrentEvent == XMLEvent.START_ELEMENT)) {
121: fStreamAdvancedByHasNext = false;
122: return fCurrentEvent;
123: }
124:
125: int event = findNextTag();
126: if (event != -1) {
127: return event;
128: }
129: throw new IllegalStateException(
130: "The stream reader has reached the end of the document, or there are no more "
131: + " items to return");
132: }
133:
134: /**
135: *
136: * @throws XMLStreamException
137: * @return
138: */
139: public boolean hasNext() throws XMLStreamException {
140: if (fStreamReader.hasNext()) {
141: if (!fEventAccepted) {
142: if ((fCurrentEvent = findNextEvent()) == -1) {
143: return false;
144: } else {
145: fStreamAdvancedByHasNext = true;
146: }
147: }
148: return true;
149: }
150: return false;
151: }
152:
153: private int findNextEvent() throws XMLStreamException {
154: fStreamAdvancedByHasNext = false;
155: while (fStreamReader.hasNext()) {
156: fCurrentEvent = fStreamReader.next();
157: if (fStreamFilter.accept(fStreamReader)) {
158: fEventAccepted = true;
159: return fCurrentEvent;
160: }
161: }
162: //although it seems that IllegalStateException should be thrown when next() is called
163: //on a stream that has no more items, we have to assume END_DOCUMENT is always accepted
164: //in order to pass the TCK
165: if (fCurrentEvent == XMLEvent.END_DOCUMENT)
166: return fCurrentEvent;
167: else
168: return -1;
169: }
170:
171: private int findNextTag() throws XMLStreamException {
172: fStreamAdvancedByHasNext = false;
173: while (fStreamReader.hasNext()) {
174: fCurrentEvent = fStreamReader.nextTag();
175: if (fStreamFilter.accept(fStreamReader)) {
176: fEventAccepted = true;
177: return fCurrentEvent;
178: }
179: }
180: if (fCurrentEvent == XMLEvent.END_DOCUMENT)
181: return fCurrentEvent;
182: else
183: return -1;
184: }
185:
186: /**
187: *
188: * @throws XMLStreamException
189: */
190: public void close() throws XMLStreamException {
191: fStreamReader.close();
192: }
193:
194: /**
195: *
196: * @return
197: */
198: public int getAttributeCount() {
199: return fStreamReader.getAttributeCount();
200: }
201:
202: /**
203: *
204: * @param index
205: * @return
206: */
207: public QName getAttributeName(int index) {
208: return fStreamReader.getAttributeName(index);
209: }
210:
211: /**
212: *
213: * @param index
214: * @return
215: */
216: public String getAttributeNamespace(int index) {
217: return fStreamReader.getAttributeNamespace(index);
218: }
219:
220: /**
221: *
222: * @param index
223: * @return
224: */
225: public String getAttributePrefix(int index) {
226: return fStreamReader.getAttributePrefix(index);
227: }
228:
229: /**
230: *
231: * @param index
232: * @return
233: */
234: public String getAttributeType(int index) {
235: return fStreamReader.getAttributeType(index);
236: }
237:
238: /**
239: *
240: * @param index
241: * @return
242: */
243: public String getAttributeValue(int index) {
244: return fStreamReader.getAttributeValue(index);
245: }
246:
247: /**
248: *
249: * @param namespaceURI
250: * @param localName
251: * @return
252: */
253: public String getAttributeValue(String namespaceURI,
254: String localName) {
255: return fStreamReader.getAttributeValue(namespaceURI, localName);
256: }
257:
258: /**
259: *
260: * @return
261: */
262: public String getCharacterEncodingScheme() {
263: return fStreamReader.getCharacterEncodingScheme();
264: }
265:
266: /**
267: *
268: * @throws XMLStreamException
269: * @return
270: */
271: public String getElementText() throws XMLStreamException {
272: return fStreamReader.getElementText();
273: }
274:
275: /**
276: *
277: * @return
278: */
279: public String getEncoding() {
280: return fStreamReader.getEncoding();
281: }
282:
283: /**
284: *
285: * @return
286: */
287: public int getEventType() {
288: return fStreamReader.getEventType();
289: }
290:
291: /**
292: *
293: * @return
294: */
295: public String getLocalName() {
296: return fStreamReader.getLocalName();
297: }
298:
299: /**
300: *
301: * @return
302: */
303: public javax.xml.stream.Location getLocation() {
304: return fStreamReader.getLocation();
305: }
306:
307: /**
308: *
309: * @return
310: */
311: public javax.xml.namespace.QName getName() {
312: return fStreamReader.getName();
313: }
314:
315: /**
316: *
317: * @return
318: */
319: public javax.xml.namespace.NamespaceContext getNamespaceContext() {
320: return fStreamReader.getNamespaceContext();
321: }
322:
323: /**
324: *
325: * @return
326: */
327: public int getNamespaceCount() {
328: return fStreamReader.getNamespaceCount();
329: }
330:
331: /**
332: *
333: * @param index
334: * @return
335: */
336: public String getNamespacePrefix(int index) {
337: return fStreamReader.getNamespacePrefix(index);
338: }
339:
340: /**
341: *
342: * @return
343: */
344: public String getNamespaceURI() {
345: return fStreamReader.getNamespaceURI();
346: }
347:
348: /**
349: *
350: * @param index
351: * @return
352: */
353: public String getNamespaceURI(int index) {
354: return fStreamReader.getNamespaceURI(index);
355: }
356:
357: /**
358: *
359: * @param prefix
360: * @return
361: */
362: public String getNamespaceURI(String prefix) {
363: return fStreamReader.getNamespaceURI(prefix);
364: }
365:
366: /**
367: *
368: * @return
369: */
370: public String getPIData() {
371: return fStreamReader.getPIData();
372: }
373:
374: /**
375: *
376: * @return
377: */
378: public String getPITarget() {
379: return fStreamReader.getPITarget();
380: }
381:
382: /**
383: *
384: * @return
385: */
386: public String getPrefix() {
387: return fStreamReader.getPrefix();
388: }
389:
390: /**
391: *
392: * @param name
393: * @throws IllegalArgumentException
394: * @return
395: */
396: public Object getProperty(java.lang.String name)
397: throws java.lang.IllegalArgumentException {
398: return fStreamReader.getProperty(name);
399: }
400:
401: /**
402: *
403: * @return
404: */
405: public String getText() {
406: return fStreamReader.getText();
407: }
408:
409: /**
410: *
411: * @return
412: */
413: public char[] getTextCharacters() {
414: return fStreamReader.getTextCharacters();
415: }
416:
417: /**
418: *
419: * @param sourceStart
420: * @param target
421: * @param targetStart
422: * @param length
423: * @throws XMLStreamException
424: * @return
425: */
426: public int getTextCharacters(int sourceStart, char[] target,
427: int targetStart, int length) throws XMLStreamException {
428: return fStreamReader.getTextCharacters(sourceStart, target,
429: targetStart, length);
430: }
431:
432: /**
433: *
434: * @return
435: */
436: public int getTextLength() {
437: return fStreamReader.getTextLength();
438: }
439:
440: /**
441: *
442: * @return
443: */
444: public int getTextStart() {
445: return fStreamReader.getTextStart();
446: }
447:
448: /**
449: *
450: * @return
451: */
452: public String getVersion() {
453: return fStreamReader.getVersion();
454:
455: }
456:
457: /**
458: *
459: * @return
460: */
461: public boolean hasName() {
462: return fStreamReader.hasName();
463: }
464:
465: /**
466: *
467: * @return
468: */
469: public boolean hasText() {
470: return fStreamReader.hasText();
471: }
472:
473: /**
474: *
475: * @return
476: * @param index
477: */
478: public boolean isAttributeSpecified(int index) {
479: return fStreamReader.isAttributeSpecified(index);
480: }
481:
482: /**
483: *
484: * @return
485: */
486: public boolean isCharacters() {
487: return fStreamReader.isCharacters();
488: }
489:
490: /**
491: *
492: * @return
493: */
494: public boolean isEndElement() {
495: return fStreamReader.isEndElement();
496: }
497:
498: /**
499: *
500: * @return
501: */
502: public boolean isStandalone() {
503: return fStreamReader.isStandalone();
504: }
505:
506: /**
507: *
508: * @return
509: */
510: public boolean isStartElement() {
511: return fStreamReader.isStartElement();
512: }
513:
514: /**
515: *
516: * @return
517: */
518: public boolean isWhiteSpace() {
519: return fStreamReader.isWhiteSpace();
520: }
521:
522: /**
523: *
524: * @param type
525: * @param namespaceURI
526: * @param localName
527: * @throws XMLStreamException
528: */
529: public void require(int type, String namespaceURI, String localName)
530: throws XMLStreamException {
531: fStreamReader.require(type, namespaceURI, localName);
532: }
533:
534: /**
535: *
536: * @return
537: */
538: public boolean standaloneSet() {
539: return fStreamReader.standaloneSet();
540: }
541:
542: /**
543: *
544: * @param index
545: * @return
546: */
547: public String getAttributeLocalName(int index) {
548: return fStreamReader.getAttributeLocalName(index);
549: }
550:
551: }
|