001: /*
002: * (C) Copyright 2002-2003, Andy Clark. All rights reserved.
003: *
004: * This file is distributed under an Apache style license. Please
005: * refer to the LICENSE file for specific details.
006: */
007:
008: package org.cyberneko.pull.util;
009:
010: import org.cyberneko.pull.XMLEvent;
011: import org.cyberneko.pull.event.CDATAEvent;
012: import org.cyberneko.pull.event.CharactersEvent;
013: import org.cyberneko.pull.event.CommentEvent;
014: import org.cyberneko.pull.event.DoctypeDeclEvent;
015: import org.cyberneko.pull.event.DocumentEvent;
016: import org.cyberneko.pull.event.ElementEvent;
017: import org.cyberneko.pull.event.GeneralEntityEvent;
018: import org.cyberneko.pull.event.PrefixMappingEvent;
019: import org.cyberneko.pull.event.ProcessingInstructionEvent;
020: import org.cyberneko.pull.event.TextDeclEvent;
021:
022: import java.lang.reflect.Method;
023: import java.util.Enumeration;
024:
025: import org.apache.xerces.util.AugmentationsImpl;
026: import org.apache.xerces.util.XMLAttributesImpl;
027: import org.apache.xerces.util.XMLStringBuffer;
028: import org.apache.xerces.xni.Augmentations;
029: import org.apache.xerces.xni.NamespaceContext;
030: import org.apache.xerces.xni.QName;
031: import org.apache.xerces.xni.XMLAttributes;
032: import org.apache.xerces.xni.XMLDocumentHandler;
033: import org.apache.xerces.xni.XMLLocator;
034: import org.apache.xerces.xni.XMLResourceIdentifier;
035: import org.apache.xerces.xni.XMLString;
036: import org.apache.xerces.xni.XNIException;
037: import org.apache.xerces.xni.parser.XMLComponent;
038: import org.apache.xerces.xni.parser.XMLComponentManager;
039: import org.apache.xerces.xni.parser.XMLConfigurationException;
040: import org.apache.xerces.xni.parser.XMLDocumentSource;
041:
042: /**
043: * This class converts XNI document handler callbacks into pull parser
044: * event objects, storing them on an event queue. In order to work with
045: * any kind of XNI generator, the data passed via the XNI callbacks is
046: * buffered internally when converted to event objects. Therefore, this
047: * class is for general use and is <em>not</em> intended for high
048: * performance pull parsing. For better performance, a parser written
049: * directly to the pull parser API should be used.
050: * <p>
051: * <strong>Note:</strong>
052: * There is a performance hit to buffering the underlying XNI events.
053: * While the difference is negligible for small documents, it becomes
054: * more pronounced as the document size increases.
055: *
056: * @see EventDispatcher
057: *
058: * @author Andy Clark
059: *
060: * @version $Id$
061: */
062: public class EventCollector extends EventQueue implements XMLComponent,
063: XMLDocumentHandler {
064:
065: //
066: // Constants
067: //
068:
069: // features
070:
071: /**
072: * Feature identifer: reuse buffers.
073: * <p color='red'>
074: * <strong>Note:</strong>
075: * This capability is not yet implemented in the Xerces2 parser.
076: * Therefore, this feature identifier is a placeholder for future
077: * capability to improve performance of a pull parser impl built
078: * on top of Xerces2.
079: * </p>
080: */
081: protected static final String REUSE_BUFFERS = "http://apache.org/xml/features/scanner/reuse-buffers";
082:
083: /** Recognized features. */
084: protected static final String[] RECOGNIZED_FEATURES = { REUSE_BUFFERS, };
085:
086: /** Feature defaults. */
087: protected static final Boolean[] FEATURE_DEFAULTS = { null, };
088:
089: //
090: // Data
091: //
092:
093: /** Event cache. */
094: protected XMLEvent[] fEventCache = new XMLEvent[10];
095:
096: /** The last event. */
097: protected XMLEvent fLastEvent;
098:
099: /** Underlying buffers are re-used by the creator of the XNI events. */
100: protected boolean fReuseBuffers = true;
101:
102: /** XNI document source. */
103: protected XMLDocumentSource fDocumentSource;
104:
105: /** Namespace context. */
106: protected NamespaceContext fNamespaceContext;
107:
108: // temp vars
109:
110: /** A qualified name. */
111: private final QName fQName = new QName();
112:
113: //
114: // EventQueue methods
115: //
116:
117: /** Removes an event from the queue. */
118: public XMLEvent dequeue() {
119: if (fLastEvent != null) {
120: dropEvent(fLastEvent);
121: }
122: return fLastEvent = super .dequeue();
123: } // dequeue():XMLEvent
124:
125: //
126: // XMLComponent methods
127: //
128:
129: /** Reset. */
130: public void reset(XMLComponentManager manager)
131: throws XMLConfigurationException {
132: clear();
133: fLastEvent = null;
134: // REVISIT: This functionality is not implemented in the Xerces2
135: // reference implementation of XNI, yet. -Ac
136: try {
137: fReuseBuffers = manager.getFeature(REUSE_BUFFERS);
138: } catch (Exception e) {
139: fReuseBuffers = true;
140: }
141: } // reset(XMLComponentManager)
142:
143: /** Returns recognized features. */
144: public String[] getRecognizedFeatures() {
145: return RECOGNIZED_FEATURES;
146: } // getRecognizedFeatures():String[]
147:
148: /** Set feature. */
149: public void setFeature(String featureId, boolean state)
150: throws XMLConfigurationException {
151: } // setFeature(String,boolean)
152:
153: /** Returns recognized properties. */
154: public String[] getRecognizedProperties() {
155: return null;
156: } // getRecognizedProperties():String[]
157:
158: /** Set property. */
159: public void setProperty(String propertyId, Object value)
160: throws XMLConfigurationException {
161: } // setProperty(String,Object)
162:
163: // since Xerces-J 2.2.0
164:
165: /** Returns feature default. */
166: public Boolean getFeatureDefault(String featureId) {
167: for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
168: if (RECOGNIZED_FEATURES[i].equals(featureId)) {
169: return FEATURE_DEFAULTS[i];
170: }
171: }
172: return null;
173: } // getFeatureDefault(String):Boolean
174:
175: /** Returns property default. */
176: public Object getPropertyDefault(String propertyId) {
177: return null;
178: } // getPropertyDefault(String):Object
179:
180: //
181: // XMLDocumentHandler methods
182: //
183:
184: // since Xerces-J 2.2.0
185:
186: /** Start document. */
187: public void startDocument(XMLLocator locator, String encoding,
188: NamespaceContext nscontext, Augmentations augs)
189: throws XNIException {
190: fNamespaceContext = nscontext;
191: DocumentEvent event = (DocumentEvent) getEvent(XMLEvent.DOCUMENT);
192: event.start = true;
193: event.locator = locator;
194: event.encoding = encoding;
195: event.augs = augs(augs);
196: enqueue(event);
197: } // startDocument(XMLLocator,String,NamespaceContext,Augmentations)
198:
199: // old methods
200:
201: /**
202: * The start of the document.
203: *
204: * @param locator The document locator, or null if the document
205: * location cannot be reported during the parsing
206: * of this document. However, it is <em>strongly</em>
207: * recommended that a locator be supplied that can
208: * at least report the system identifier of the
209: * document.
210: * @param encoding The auto-detected IANA encoding name of the entity
211: * stream. This value will be null in those situations
212: * where the entity encoding is not auto-detected (e.g.
213: * internal entities or a document entity that is
214: * parsed from a java.io.Reader).
215: * @param augs Additional information that may include infoset augmentations
216: * @exception XNIException
217: * Thrown by handler to signal an error.
218: */
219: public void startDocument(XMLLocator locator, String encoding,
220: Augmentations augs) throws XNIException {
221: startDocument(locator, encoding, null, augs);
222: } // startDocument(XMLLocator,String,Augmentations)
223:
224: /**
225: * Notifies of the presence of an XMLDecl line in the document. If
226: * present, this method will be called immediately following the
227: * startDocument call.
228: *
229: * @param version The XML version.
230: * @param encoding The IANA encoding name of the document, or null if
231: * not specified.
232: * @param standalone The standalone value, or null if not specified.
233: * @param augs Additional information that may include infoset augmentations
234: *
235: * @exception XNIException
236: * Thrown by handler to signal an error.
237: */
238: public void xmlDecl(String version, String encoding,
239: String standalone, Augmentations augs) throws XNIException {
240: TextDeclEvent event = (TextDeclEvent) getEvent(XMLEvent.TEXT_DECL);
241: event.xmldecl = true;
242: event.version = version;
243: event.encoding = encoding;
244: event.standalone = standalone;
245: event.augs = augs(augs);
246: enqueue(event);
247: } // xmlDecl(String,String,String,Augmentations)
248:
249: /**
250: * Notifies of the presence of the DOCTYPE line in the document.
251: *
252: * @param rootElement
253: * The name of the root element.
254: * @param publicId The public identifier if an external DTD or null
255: * if the external DTD is specified using SYSTEM.
256: * @param systemId The system identifier if an external DTD, null
257: * otherwise.
258: * @param augs Additional information that may include infoset augmentations
259: *
260: * @exception XNIException
261: * Thrown by handler to signal an error.
262: */
263: public void doctypeDecl(String rootElement, String publicId,
264: String systemId, Augmentations augs) throws XNIException {
265: DoctypeDeclEvent event = new DoctypeDeclEvent();
266: event.root = rootElement;
267: event.pubid = publicId;
268: event.sysid = systemId;
269: event.augs = augs(augs);
270: enqueue(event);
271: } // doctypeDecl(String,String,String,Augmentations)
272:
273: /**
274: * A comment.
275: *
276: * @param text The text in the comment.
277: * @param augs Additional information that may include infoset augmentations
278: *
279: * @exception XNIException
280: * Thrown by application to signal an error.
281: */
282: public void comment(XMLString text, Augmentations augs)
283: throws XNIException {
284: CommentEvent event = (CommentEvent) getEvent(XMLEvent.COMMENT);
285: event.text = string(text, false);
286: event.augs = augs(augs);
287: enqueue(event);
288: } // comment(XMLString,Augmentations)
289:
290: /**
291: * A processing instruction. Processing instructions consist of a
292: * target name and, optionally, text data. The data is only meaningful
293: * to the application.
294: * <p>
295: * Typically, a processing instruction's data will contain a series
296: * of pseudo-attributes. These pseudo-attributes follow the form of
297: * element attributes but are <strong>not</strong> parsed or presented
298: * to the application as anything other than text. The application is
299: * responsible for parsing the data.
300: *
301: * @param target The target.
302: * @param data The data or null if none specified.
303: * @param augs Additional information that may include infoset augmentations
304: *
305: * @exception XNIException
306: * Thrown by handler to signal an error.
307: */
308: public void processingInstruction(String target, XMLString data,
309: Augmentations augs) throws XNIException {
310: ProcessingInstructionEvent event = (ProcessingInstructionEvent) getEvent(XMLEvent.PROCESSING_INSTRUCTION);
311: event.target = target;
312: event.data = string(data, false);
313: event.augs = augs(augs);
314: enqueue(event);
315: } // processingInstruction(String,XMLString,Augmentations)
316:
317: /**
318: * The start of a namespace prefix mapping. This method will only be
319: * called when namespace processing is enabled.
320: *
321: * @param prefix The namespace prefix.
322: * @param uri The URI bound to the prefix.
323: * @param augs Additional information that may include infoset augmentations
324: *
325: * @exception XNIException
326: * Thrown by handler to signal an error.
327: */
328: public void startPrefixMapping(String prefix, String uri,
329: Augmentations augs) throws XNIException {
330: PrefixMappingEvent event = (PrefixMappingEvent) getEvent(XMLEvent.PREFIX_MAPPING);
331: event.start = true;
332: event.prefix = prefix;
333: event.uri = uri;
334: event.augs = augs(augs);
335: enqueue(event);
336: } // startPrefixMapping(String,String,Augmentations)
337:
338: /**
339: * The start of an element.
340: *
341: * @param element The name of the element.
342: * @param attributes The element attributes.
343: * @param augs Additional information that may include infoset augmentations
344: *
345: * @exception XNIException
346: * Thrown by handler to signal an error.
347: */
348: public void startElement(QName element, XMLAttributes attributes,
349: Augmentations augs) throws XNIException {
350: handleStartElement(element, attributes, augs, false);
351: } // startElement(QName,XMLAttributes,Augmentations)
352:
353: /**
354: * An empty element.
355: *
356: * @param element The name of the element.
357: * @param attributes The element attributes.
358: * @param augs Additional information that may include infoset augmentations
359: *
360: * @exception XNIException
361: * Thrown by handler to signal an error.
362: */
363: public void emptyElement(QName element, XMLAttributes attributes,
364: Augmentations augs) throws XNIException {
365: handleStartElement(element, attributes, augs, true);
366: handleEndElement(element, augs, true);
367: } // emptyElement(QName,XMLAttributes,Augmentations)
368:
369: /**
370: * This method notifies the start of a general entity.
371: * <p>
372: * <strong>Note:</strong> This method is not called for entity references
373: * appearing as part of attribute values.
374: *
375: * @param name The name of the general entity.
376: * @param identifier The resource identifier.
377: * @param encoding The auto-detected IANA encoding name of the entity
378: * stream. This value will be null in those situations
379: * where the entity encoding is not auto-detected (e.g.
380: * internal entities or a document entity that is
381: * parsed from a java.io.Reader).
382: * @param augs Additional information that may include infoset augmentations
383: *
384: * @exception XNIException Thrown by handler to signal an error.
385: */
386: public void startGeneralEntity(String name,
387: XMLResourceIdentifier identifier, String encoding,
388: Augmentations augs) throws XNIException {
389: GeneralEntityEvent event = (GeneralEntityEvent) getEvent(XMLEvent.GENERAL_ENTITY);
390: event.start = true;
391: event.name = name;
392: try {
393: Method method = event.getClass().getMethod("getNamespace",
394: null);
395: event.namespace = (String) method.invoke(identifier, null);
396: } catch (Exception e) {
397: // old version of Xerces -- ignore
398: }
399: if (identifier != null) {
400: event.publicId = identifier.getPublicId();
401: event.baseSystemId = identifier.getBaseSystemId();
402: event.literalSystemId = identifier.getLiteralSystemId();
403: event.expandedSystemId = identifier.getExpandedSystemId();
404: }
405: event.encoding = encoding;
406: event.augs = augs(augs);
407: enqueue(event);
408: } // startGeneralEntity(String,XMLResourceIdentifier,String,Augmentations)
409:
410: /**
411: * Notifies of the presence of a TextDecl line in an entity. If present,
412: * this method will be called immediately following the startEntity call.
413: * <p>
414: * <strong>Note:</strong> This method will never be called for the
415: * document entity; it is only called for external general entities
416: * referenced in document content.
417: * <p>
418: * <strong>Note:</strong> This method is not called for entity references
419: * appearing as part of attribute values.
420: *
421: * @param version The XML version, or null if not specified.
422: * @param encoding The IANA encoding name of the entity.
423: * @param augs Additional information that may include infoset augmentations
424: *
425: * @exception XNIException
426: * Thrown by handler to signal an error.
427: */
428: public void textDecl(String version, String encoding,
429: Augmentations augs) throws XNIException {
430: TextDeclEvent event = (TextDeclEvent) getEvent(XMLEvent.TEXT_DECL);
431: event.xmldecl = false;
432: event.version = version;
433: event.encoding = encoding;
434: event.augs = augs(augs);
435: enqueue(event);
436: } // textDecl(String,String,Augmentations)
437:
438: /**
439: * This method notifies the end of a general entity.
440: * <p>
441: * <strong>Note:</strong> This method is not called for entity references
442: * appearing as part of attribute values.
443: *
444: * @param name The name of the entity.
445: * @param augs Additional information that may include infoset augmentations
446: *
447: * @exception XNIException
448: * Thrown by handler to signal an error.
449: */
450: public void endGeneralEntity(String name, Augmentations augs)
451: throws XNIException {
452: GeneralEntityEvent event = (GeneralEntityEvent) getEvent(XMLEvent.GENERAL_ENTITY);
453: event.start = false;
454: event.name = name;
455: event.publicId = null;
456: event.baseSystemId = null;
457: event.literalSystemId = null;
458: event.expandedSystemId = null;
459: event.encoding = null;
460: event.augs = augs(augs);
461: enqueue(event);
462: } // endGeneralEntity(String,Augmentations)
463:
464: /**
465: * Character content.
466: *
467: * @param text The content.
468: * @param augs Additional information that may include infoset augmentations
469: *
470: * @exception XNIException
471: * Thrown by handler to signal an error.
472: */
473: public void characters(XMLString text, Augmentations augs)
474: throws XNIException {
475: CharactersEvent event = (CharactersEvent) getEvent(XMLEvent.CHARACTERS);
476: event.ignorable = false;
477: event.text = string(text, true);
478: event.augs = augs(augs);
479: enqueue(event);
480: } // characters(XMLString,Augmentations)
481:
482: /**
483: * Ignorable whitespace. For this method to be called, the document
484: * source must have some way of determining that the text containing
485: * only whitespace characters should be considered ignorable. For
486: * example, the validator can determine if a length of whitespace
487: * characters in the document are ignorable based on the element
488: * content model.
489: *
490: * @param text The ignorable whitespace.
491: * @param augs Additional information that may include infoset augmentations
492: *
493: * @exception XNIException
494: * Thrown by handler to signal an error.
495: */
496: public void ignorableWhitespace(XMLString text, Augmentations augs)
497: throws XNIException {
498: CharactersEvent event = (CharactersEvent) getEvent(XMLEvent.CHARACTERS);
499: event.ignorable = true;
500: event.text = string(text, true);
501: event.augs = augs(augs);
502: enqueue(event);
503: } // ignorableWhitespace(XMLString,Augmentations)
504:
505: /**
506: * The end of an element.
507: *
508: * @param element The name of the element.
509: * @param augs Additional information that may include infoset augmentations
510: *
511: * @exception XNIException
512: * Thrown by handler to signal an error.
513: */
514: public void endElement(QName element, Augmentations augs)
515: throws XNIException {
516: handleEndElement(element, augs, false);
517: } // endElement(QName,Augmentations)
518:
519: /**
520: * The end of a namespace prefix mapping. This method will only be
521: * called when namespace processing is enabled.
522: *
523: * @param prefix The namespace prefix.
524: * @param augs Additional information that may include infoset augmentations
525: *
526: * @exception XNIException
527: * Thrown by handler to signal an error.
528: */
529: public void endPrefixMapping(String prefix, Augmentations augs)
530: throws XNIException {
531: PrefixMappingEvent event = (PrefixMappingEvent) getEvent(XMLEvent.PREFIX_MAPPING);
532: event.start = false;
533: event.prefix = prefix;
534: event.uri = null;
535: event.augs = augs(augs);
536: enqueue(event);
537: } // endPrefixMapping(String,Augmentations)
538:
539: /**
540: * The start of a CDATA section.
541: *
542: * @param augs Additional information that may include infoset augmentations
543: *
544: * @exception XNIException
545: * Thrown by handler to signal an error.
546: */
547: public void startCDATA(Augmentations augs) throws XNIException {
548: CDATAEvent event = (CDATAEvent) getEvent(XMLEvent.CDATA);
549: event.start = true;
550: event.augs = augs(augs);
551: enqueue(event);
552: } // startCDATA(Augmentations)
553:
554: /**
555: * The end of a CDATA section.
556: *
557: * @param augs Additional information that may include infoset augmentations
558: *
559: * @exception XNIException
560: * Thrown by handler to signal an error.
561: */
562: public void endCDATA(Augmentations augs) throws XNIException {
563: CDATAEvent event = (CDATAEvent) getEvent(XMLEvent.CDATA);
564: event.start = false;
565: event.augs = augs(augs);
566: enqueue(event);
567: } // endCDATA(Augmentations)
568:
569: /**
570: * The end of the document.
571: *
572: * @param augs Additional information that may include infoset augmentations
573: *
574: * @exception XNIException
575: * Thrown by handler to signal an error.
576: */
577: public void endDocument(Augmentations augs) throws XNIException {
578: DocumentEvent event = (DocumentEvent) getEvent(XMLEvent.DOCUMENT);
579: event.start = false;
580: event.locator = null;
581: event.encoding = null;
582: event.augs = augs(augs);
583: enqueue(event);
584: } // endDocument(Augmentations)
585:
586: // @since Xerces 2.1.0
587:
588: /** Sets the document source. */
589: public void setDocumentSource(XMLDocumentSource source) {
590: fDocumentSource = source;
591: } // setDocumentSource(XMLDocumentSource)
592:
593: /** Returns the document source. */
594: public XMLDocumentSource getDocumentSource() {
595: return fDocumentSource;
596: } // getDocumentSource():XMLDocumentSource
597:
598: //
599: // Protected methods
600: //
601:
602: /** Handles a start element by copying the necessary data. */
603: protected void handleStartElement(QName element,
604: XMLAttributes attributes, Augmentations augs, boolean empty) {
605:
606: // handle namespace prefixes
607: if (fNamespaceContext != null) {
608: int count = fNamespaceContext.getDeclaredPrefixCount();
609: for (int i = 0; i < count; i++) {
610: String prefix = fNamespaceContext
611: .getDeclaredPrefixAt(i);
612: String uri = fNamespaceContext.getURI(prefix);
613: startPrefixMapping(prefix, uri, null);
614: }
615: }
616:
617: // enqueue start element event
618: ElementEvent event = (ElementEvent) getEvent(XMLEvent.ELEMENT);
619: event.start = true;
620: if (event.element == null) {
621: event.element = new QName();
622: }
623: event.element.setValues(element);
624: if (event.attributes == null) {
625: event.attributes = new XMLAttributesImpl();
626: }
627: attrs(attributes, event.attributes);
628: event.empty = empty;
629: event.augs = augs(augs);
630: enqueue(event);
631:
632: } // handleStartElement(QName,XMLAttributes,Augmentations,boolean)
633:
634: /** Handles an end element by copying the necessary data. */
635: protected void handleEndElement(QName element, Augmentations augs,
636: boolean empty) {
637:
638: // enqueue end element event
639: ElementEvent event = (ElementEvent) getEvent(XMLEvent.ELEMENT);
640: event.start = false;
641: if (event.element == null) {
642: event.element = new QName();
643: }
644: event.element.setValues(element);
645: /***
646: // REVISIT: [Q] What is the best way to handle this? Should I
647: // keep a list of unused attributes objects? -Ac
648: if (event.attributes != null) {
649: event.attributes.removeAllAttributes();
650: }
651: /***/
652: event.attributes = null;
653: /***/
654: event.empty = empty;
655: event.augs = augs(augs);
656: enqueue(event);
657:
658: // handle namespace prefixes
659: if (fNamespaceContext != null) {
660: int count = fNamespaceContext.getDeclaredPrefixCount();
661: for (int i = count - 1; i >= 0; i--) {
662: String prefix = fNamespaceContext
663: .getDeclaredPrefixAt(i);
664: endPrefixMapping(prefix, null);
665: }
666: }
667:
668: } // handleEndElement(QName,Augmentations,boolean)
669:
670: /** Returns a copy of the specified args. */
671: protected Augmentations augs(Augmentations augs) {
672: Augmentations newaugs = null;
673: if (augs != null) {
674: newaugs = new AugmentationsImpl();
675: Enumeration keys = augs.keys();
676: while (keys.hasMoreElements()) {
677: String key = (String) keys.nextElement();
678: newaugs.putItem(key, augs.getItem(key));
679: }
680: }
681: return newaugs;
682: } // augs(Augmentations):Augmentations
683:
684: /** Copies the source attributes into the specified destination. */
685: protected void attrs(XMLAttributes src, XMLAttributes dest) {
686: int attrCount = src != null ? src.getLength() : 0;
687: for (int i = 0; i < attrCount; i++) {
688: src.getName(i, fQName);
689: String atype = src.getType(i);
690: String avalue = src.getValue(i);
691: String anonvalue = src.getNonNormalizedValue(i);
692: boolean specified = src.isSpecified(i);
693: dest.addAttribute(fQName, atype, avalue);
694: dest.setNonNormalizedValue(i, anonvalue);
695: dest.setSpecified(i, specified);
696: }
697: } // attrs(XMLAttributes,XMLAttributes)
698:
699: /** Returns a copy of the specified string. */
700: protected XMLString string(XMLString text, boolean content) {
701: return fReuseBuffers ? new XMLStringBuffer(text) : text;
702: } // string(XMLString):XMLString
703:
704: /**
705: * Returns an event object for the given type. If an un-used event object
706: * of this type is on the event cache, it is returned. Otherwise, a new
707: * event object is created.
708: */
709: protected XMLEvent getEvent(short type) {
710: XMLEvent event = fEventCache[type];
711: if (event != null) {
712: fEventCache[type] = event.next;
713: event.next = null;
714: return event;
715: }
716: switch (type) {
717: case XMLEvent.ELEMENT:
718: return new ElementEvent();
719: case XMLEvent.CHARACTERS:
720: return new CharactersEvent();
721: case XMLEvent.PREFIX_MAPPING:
722: return new PrefixMappingEvent();
723: case XMLEvent.GENERAL_ENTITY:
724: return new GeneralEntityEvent();
725: case XMLEvent.DOCUMENT:
726: return new DocumentEvent();
727: case XMLEvent.COMMENT:
728: return new CommentEvent();
729: case XMLEvent.PROCESSING_INSTRUCTION:
730: return new ProcessingInstructionEvent();
731: case XMLEvent.CDATA:
732: return new CDATAEvent();
733: case XMLEvent.TEXT_DECL:
734: return new TextDeclEvent();
735: case XMLEvent.DOCTYPE_DECL:
736: return new DoctypeDeclEvent();
737: }
738: throw new RuntimeException("should not happen! getEvent("
739: + type + ')');
740: } // getEvent(short):Event
741:
742: /**
743: * Drops an event by putting it back on the event cache so that it
744: * can be re-used when needed.
745: */
746: protected void dropEvent(XMLEvent event) {
747: event.next = fEventCache[event.type];
748: fEventCache[event.type] = event;
749: if (event.type == XMLEvent.ELEMENT) {
750: ElementEvent elementEvent = (ElementEvent) event;
751: if (elementEvent.attributes != null) {
752: elementEvent.attributes.removeAllAttributes();
753: }
754: }
755: } // dropEvent(Event)
756:
757: } // class EventCollector
|