0001: /*
0002: * $Id: XMLReaderImpl.java,v 1.12 2007/03/02 21:29:48 spericas Exp $
0003: */
0004:
0005: /*
0006: * The contents of this file are subject to the terms
0007: * of the Common Development and Distribution License
0008: * (the License). You may not use this file except in
0009: * compliance with the License.
0010: *
0011: * You can obtain a copy of the license at
0012: * https://glassfish.dev.java.net/public/CDDLv1.0.html.
0013: * See the License for the specific language governing
0014: * permissions and limitations under the License.
0015: *
0016: * When distributing Covered Code, include this CDDL
0017: * Header Notice in each file and include the License file
0018: * at https://glassfish.dev.java.net/public/CDDLv1.0.html.
0019: * If applicable, add the following below the CDDL Header,
0020: * with the fields enclosed by brackets [] replaced by
0021: * you own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * [Name of File] [ver.__] [Date]
0025: *
0026: * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
0027: */
0028:
0029: package com.sun.xml.stream;
0030:
0031: import com.sun.xml.stream.events.EntityDeclarationImpl;
0032: import com.sun.xml.stream.events.NotationDeclarationImpl;
0033: import java.io.BufferedInputStream;
0034: import java.io.BufferedReader;
0035: import java.io.ByteArrayInputStream;
0036: import java.io.CharArrayReader;
0037: import java.io.IOException;
0038: import java.io.InputStream;
0039: import java.io.Reader;
0040: import java.io.StringReader;
0041: import javax.xml.namespace.NamespaceContext;
0042: import com.sun.xml.stream.xerces.xni.XNIException;
0043: import com.sun.xml.stream.xerces.xni.parser.XMLInputSource;
0044: import javax.xml.namespace.QName;
0045: import javax.xml.stream.Location;
0046: import javax.xml.stream.events.XMLEvent;
0047: import com.sun.xml.stream.xerces.util.NamespaceContextWrapper;
0048: import com.sun.xml.stream.xerces.util.SymbolTable;
0049: import com.sun.xml.stream.dtd.nonvalidating.XMLNotationDecl;
0050: import com.sun.xml.stream.dtd.nonvalidating.DTDGrammar;
0051: import java.util.ArrayList;
0052: import java.util.Enumeration;
0053: import java.util.Hashtable;
0054: import java.util.Iterator;
0055: import java.util.List;
0056: import javax.xml.stream.XMLInputFactory;
0057: import javax.xml.stream.XMLStreamConstants;
0058: import javax.xml.stream.XMLStreamException;
0059: import com.sun.xml.stream.xerces.impl.msg.XMLMessageFormatter;
0060: import com.sun.xml.stream.xerces.util.XMLChar;
0061: import com.sun.xml.stream.xerces.util.XMLStringBuffer;
0062: import org.xml.sax.InputSource;
0063: import javax.xml.XMLConstants;
0064:
0065: /** This class implements javax.xml.stream.XMLStreamReader. It makes use of XML*Scanner classes to
0066: * derive most of its functionality. If desired, Application can reuse this instance by calling
0067: * reset() and setInputSource().
0068: *
0069: * @author Neeraj Bajaj Sun Microsystems,Inc.
0070: * @author K.Venugopal Sun Microsystems,Inc.
0071: */
0072: public class XMLReaderImpl implements javax.xml.stream.XMLStreamReader {
0073:
0074: /** Property identifier: entity manager. */
0075: protected static final String ENTITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX
0076: + Constants.ENTITY_MANAGER_PROPERTY;
0077:
0078: /** Property identifier: Error Reporter. */
0079: protected static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX
0080: + Constants.ERROR_REPORTER_PROPERTY;
0081:
0082: /** Property identifier: Symbol table. */
0083: protected static final String SYMBOL_TABLE = Constants.XERCES_PROPERTY_PREFIX
0084: + Constants.SYMBOL_TABLE_PROPERTY;
0085:
0086: private SymbolTable fSymbolTable = new SymbolTable();
0087:
0088: /** Document scanner. */
0089: protected XMLNSDocumentScannerImpl fScanner = new XMLNSDocumentScannerImpl();
0090:
0091: //make Global NamespaceContextWrapper object, fScanner.getNamespaceContext() is dynamic object and ita value changes
0092: //as per the state of the parser.
0093: protected NamespaceContextWrapper fNamespaceContextWrapper = new NamespaceContextWrapper(
0094: fScanner.getNamespaceContext());
0095: protected XMLEntityManager fEntityManager = new XMLEntityManager();
0096: protected StaxErrorReporter fErrorReporter = new StaxErrorReporter();
0097:
0098: /** Entity scanner, this alwasy works on last entity that was opened. */
0099: protected XMLEntityReaderImpl fEntityScanner = null;
0100:
0101: /** Input Source */
0102: protected XMLInputSource fInputSource = null;
0103: /** Store properties*/
0104: protected PropertyManager fPropertyManager = null;
0105:
0106: /** current event type */
0107: private int fEventType;
0108: /** debug flag*/
0109: static final boolean DEBUG = false;
0110: /** more to scan */
0111: private boolean fReuse = true;
0112: private boolean fBindNamespaces = true;
0113: private String fDTDDecl = null;
0114:
0115: /**
0116: * @param inputStream
0117: * @param props
0118: * @throws XMLStreamException
0119: */
0120: public XMLReaderImpl(InputStream inputStream, PropertyManager props)
0121: throws XMLStreamException {
0122: init(props);
0123: //publicId, systemid, baseSystemId, inputStream, enocding
0124: XMLInputSource inputSource = new XMLInputSource(null, null,
0125: null, inputStream, null);
0126: //pass the input source to document scanner impl.
0127: setInputSource(inputSource);
0128: }
0129:
0130: /**
0131: * @param systemid
0132: * @param props
0133: * @throws XMLStreamException
0134: */
0135: public XMLReaderImpl(String systemid, PropertyManager props)
0136: throws XMLStreamException {
0137: init(props);
0138: //publicId, systemid, baseSystemId, inputStream, enocding
0139: XMLInputSource inputSource = new XMLInputSource(null, systemid,
0140: null);
0141: //pass the input source to document scanner impl.
0142: setInputSource(inputSource);
0143: }
0144:
0145: /**
0146: * @param inputStream
0147: * @param encoding
0148: * @param props
0149: * @throws XMLStreamException
0150: */
0151: public XMLReaderImpl(InputStream inputStream, String encoding,
0152: PropertyManager props) throws XMLStreamException {
0153: init(props);
0154: //publicId, systemid, baseSystemId, inputStream, enocding
0155: XMLInputSource inputSource = new XMLInputSource(null, null,
0156: null, new BufferedInputStream(inputStream), encoding);
0157: //pass the input source to document scanner impl.
0158: setInputSource(inputSource);
0159: }
0160:
0161: /**
0162: * @param reader
0163: * @param props
0164: * @throws XMLStreamException
0165: */
0166: public XMLReaderImpl(Reader reader, PropertyManager props)
0167: throws XMLStreamException {
0168: init(props);
0169: //publicId, systemid, baseSystemId, inputStream, enocding
0170: //xxx: Using buffered reader
0171: XMLInputSource inputSource = new XMLInputSource(null, null,
0172: null, new BufferedReader(reader), null);
0173: //pass the input source to document scanner impl.
0174: setInputSource(inputSource);
0175: }
0176:
0177: /**
0178: * @param inputSource
0179: * @param props
0180: * @throws XMLStreamException
0181: */
0182: public XMLReaderImpl(XMLInputSource inputSource,
0183: PropertyManager props) throws XMLStreamException {
0184: init(props);
0185: //pass the input source to document scanner impl.
0186: setInputSource(inputSource);
0187: }
0188:
0189: /**
0190: * @param inputSource
0191: * @throws XMLStreamException
0192: */
0193: public void setInputSource(XMLInputSource inputSource)
0194: throws XMLStreamException {
0195: //once setInputSource() is called this instance is busy parsing the inputsource supplied
0196: //this instances is free for reuse if application has explicitly called close()
0197: fReuse = false;
0198:
0199: try {
0200:
0201: fScanner.setInputSource(inputSource);
0202: fEventType = fScanner.next();
0203: } catch (java.io.IOException ex) {
0204: throw new XMLStreamException(ex);
0205: }
0206: }//setInputSource
0207:
0208: /** Set the InputSource on this instance.
0209: *
0210: * @param InputSource InputSource encapsulating information about XML Source.
0211: * @throws XMLStreamException Throws XMLStreamException if there is a problem setting InputSource
0212: */
0213: public void setInputSource(InputSource inputSource)
0214: throws XMLStreamException {
0215: setInputSource(convertSAXInputSource2XMLInputSource(inputSource));
0216: }
0217:
0218: /** Convert SAX InputSource to XMLInputSource.
0219: *
0220: * @return XMLInputSource XNI XMLInputSource.
0221: */
0222: XMLInputSource convertSAXInputSource2XMLInputSource(
0223: InputSource inputSource) {
0224: XMLInputSource xmlInputSource = new XMLInputSource(inputSource
0225: .getPublicId(), inputSource.getSystemId(), null);
0226: InputStream inputStream = inputSource.getByteStream();
0227: // If necessary, buffer input stream
0228: if (inputStream != null
0229: && inputStream instanceof ByteArrayInputStream == false
0230: && inputStream instanceof BufferedInputStream == false) {
0231: inputStream = new BufferedInputStream(inputStream);
0232: }
0233: xmlInputSource.setByteStream(inputStream);
0234: Reader reader = inputSource.getCharacterStream();
0235: // If necessary, buffer reader
0236: if (reader != null && reader instanceof BufferedReader == false
0237: && reader instanceof CharArrayReader == false
0238: && reader instanceof StringReader == false) {
0239: reader = new BufferedReader(reader);
0240: }
0241: xmlInputSource.setCharacterStream(reader);
0242: xmlInputSource.setEncoding(inputSource.getEncoding());
0243:
0244: return xmlInputSource;
0245: }
0246:
0247: void init(PropertyManager propertyManager)
0248: throws XMLStreamException {
0249: fPropertyManager = propertyManager;
0250: //set zephyr internal properties -- Note that these instances are being created in XMLReaderImpl.
0251: //1.SymbolTable
0252: //2.XMLMessageFormatter
0253: //3.XMLEntityManager
0254: //4. call reset()
0255: //1.
0256: propertyManager.setProperty(SYMBOL_TABLE, fSymbolTable);
0257: //2.
0258: propertyManager.setProperty(ERROR_REPORTER, fErrorReporter);
0259: //3.
0260: propertyManager.setProperty(ENTITY_MANAGER, fEntityManager);
0261: //4.
0262: reset();
0263: }
0264:
0265: /** This function tells if this instances is available for reuse.
0266: * One must call reset() and setInputSource() to be able to reuse
0267: * this instance.
0268: */
0269: public boolean canReuse() {
0270: if (DEBUG) {
0271: System.out.println("fReuse = " + fReuse);
0272: System.out.println("fEventType = "
0273: + getEventTypeString(fEventType));
0274: }
0275: //when parsing begins, fReuse is set to false
0276: //fReuse is set to 'true' when application calls close()
0277: return fReuse;
0278: }
0279:
0280: /**
0281: * Resets this instance so that this instance is ready for reuse.
0282: */
0283: public void reset() {
0284: fReuse = true;
0285: fEventType = 0;
0286: //reset entity manager
0287: fEntityManager.reset(fPropertyManager);
0288: //reset the scanner
0289: fScanner.reset(fPropertyManager);
0290: //REVISIT:this is too ugly -- we are getting XMLEntityManager and XMLEntityReader from
0291: //property manager, it should be only XMLEntityManager
0292: fDTDDecl = null;
0293: fEntityScanner = (XMLEntityReaderImpl) fEntityManager
0294: .getEntityReader();
0295: //default value for this property is true. However, this should be false when using XMLEventReader... Ugh..
0296: //because XMLEventReader should not have defined state.
0297: fBindNamespaces = ((Boolean) fPropertyManager
0298: .getProperty(XMLInputFactory.IS_NAMESPACE_AWARE))
0299: .booleanValue();
0300: }
0301:
0302: /** Frees any resources associated with this Reader. This method does not close the underlying input source.
0303: * @throws XMLStreamException if there are errors freeing associated resources
0304: */
0305: public void close() throws XMLStreamException {
0306: //xxx: Check what this function is intended to do.
0307: //reset();
0308: fReuse = true;
0309: }
0310:
0311: /** Returns the character encoding declared on the xml declaration Returns null if none was declared
0312: * @return the encoding declared in the document or null
0313: */
0314: public String getCharacterEncodingScheme() {
0315: return fScanner.getCharacterEncodingScheme();
0316:
0317: }
0318:
0319: /**
0320: * @return
0321: */
0322: public int getColumnNumber() {
0323: return fEntityScanner.getColumnNumber();
0324: }//getColumnNumber
0325:
0326: /** Return input encoding if known or null if unknown.
0327: * @return the encoding of this instance or null
0328: */
0329: public String getEncoding() {
0330: return fEntityScanner.getEncoding();
0331: }//getEncoding
0332:
0333: /** Returns the current value of the parse event as a string, this returns the string value of a CHARACTERS event, returns the value of a COMMENT, the replacement value for an ENTITY_REFERENCE, the string value of a CDATA section, the string value for a SPACE event, or the String value of the internal subset of the DTD. If an ENTITY_REFERENCE has been resolved, any character data will be reported as CHARACTERS events.
0334: * @return the current text or null
0335: */
0336: public int getEventType() {
0337: return fEventType;
0338: }//getEventType
0339:
0340: /**
0341: * @return
0342: */
0343: public int getLineNumber() {
0344: return fEntityScanner.getLineNumber();
0345: }//getLineNumber
0346:
0347: public String getLocalName() {
0348: if (fEventType == XMLEvent.START_ELEMENT
0349: || fEventType == XMLEvent.END_ELEMENT) {
0350: //xxx check whats the value of fCurrentElement
0351: return fScanner.getElementQName().localpart;
0352: } else if (fEventType == XMLEvent.ENTITY_REFERENCE) {
0353: return fScanner.getEntityName();
0354: }
0355: throw new IllegalStateException(
0356: "Method getLocalName() cannot be called for "
0357: + getEventTypeString(fEventType) + " event.");
0358: }//getLocalName()
0359:
0360: /**
0361: * @return
0362: */
0363: public String getNamespaceURI() {
0364: //doesn't take care of Attribute as separte event
0365: if (fEventType == XMLEvent.START_ELEMENT
0366: || fEventType == XMLEvent.END_ELEMENT) {
0367: return fScanner.getElementQName().uri;
0368: }
0369: return null;
0370: }//getNamespaceURI
0371:
0372: /** Get the data section of a processing instruction
0373: * @return the data or null
0374: */
0375:
0376: public String getPIData() {
0377: if (fEventType == XMLEvent.PROCESSING_INSTRUCTION) {
0378: return fScanner.getPIData().toString();
0379: } else
0380: throw new java.lang.IllegalStateException(
0381: "Current state of the parser is "
0382: + getEventTypeString(fEventType)
0383: + " But expected state is "
0384: + getEventTypeString(XMLEvent.PROCESSING_INSTRUCTION));
0385: }//getPIData
0386:
0387: /** Get the target of a processing instruction
0388: * @return the target or null
0389: */
0390: public String getPITarget() {
0391: if (fEventType == XMLEvent.PROCESSING_INSTRUCTION) {
0392: return fScanner.getPITarget();
0393: } else
0394: throw new java.lang.IllegalStateException(
0395: "Current state of the parser is "
0396: + getEventTypeString(fEventType)
0397: + " But expected state is "
0398: + getEventTypeString(XMLEvent.PROCESSING_INSTRUCTION));
0399:
0400: }//getPITarget
0401:
0402: /**
0403: * Returns the prefix of the current event, or null if the event does
0404: * not have a prefix. For START_ELEMENT and END_ELEMENT, return
0405: * XMLConstants.DEFAULT_NS_PREFIX when no prefix is available.
0406: */
0407: public String getPrefix() {
0408: if (fEventType == XMLEvent.START_ELEMENT
0409: || fEventType == XMLEvent.END_ELEMENT) {
0410: String prefix = fScanner.getElementQName().prefix;
0411: return prefix == null ? XMLConstants.DEFAULT_NS_PREFIX
0412: : prefix;
0413: }
0414: return null;
0415: }//getPrefix()
0416:
0417: /**
0418: * @return
0419: */
0420: public char[] getTextCharacters() {
0421: if (fEventType == XMLEvent.CHARACTERS
0422: || fEventType == XMLEvent.COMMENT
0423: || fEventType == XMLEvent.CDATA
0424: || fEventType == XMLEvent.SPACE) {
0425: return fScanner.getCharacterData().ch;
0426: } else {
0427: throw new IllegalStateException("Current state = "
0428: + getEventTypeString(fEventType)
0429: + " is not among the states "
0430: + getEventTypeString(XMLEvent.CHARACTERS) + " , "
0431: + getEventTypeString(XMLEvent.COMMENT) + " , "
0432: + getEventTypeString(XMLEvent.CDATA) + " , "
0433: + getEventTypeString(XMLEvent.SPACE)
0434: + " valid for getTextCharacters() ");
0435: }
0436: }
0437:
0438: /**
0439: * @return
0440: */
0441: public int getTextLength() {
0442: if (fEventType == XMLEvent.CHARACTERS
0443: || fEventType == XMLEvent.COMMENT
0444: || fEventType == XMLEvent.CDATA
0445: || fEventType == XMLEvent.SPACE) {
0446: return fScanner.getCharacterData().length;
0447: } else {
0448: throw new IllegalStateException("Current state = "
0449: + getEventTypeString(fEventType)
0450: + " is not among the states "
0451: + getEventTypeString(XMLEvent.CHARACTERS) + " , "
0452: + getEventTypeString(XMLEvent.COMMENT) + " , "
0453: + getEventTypeString(XMLEvent.CDATA) + " , "
0454: + getEventTypeString(XMLEvent.SPACE)
0455: + " valid for getTextLength() ");
0456: }
0457: }
0458:
0459: /**
0460: * @return
0461: */
0462: public int getTextStart() {
0463: if (fEventType == XMLEvent.CHARACTERS
0464: || fEventType == XMLEvent.COMMENT
0465: || fEventType == XMLEvent.CDATA
0466: || fEventType == XMLEvent.SPACE) {
0467: return fScanner.getCharacterData().offset;
0468: } else {
0469: throw new IllegalStateException("Current state = "
0470: + getEventTypeString(fEventType)
0471: + " is not among the states "
0472: + getEventTypeString(XMLEvent.CHARACTERS) + " , "
0473: + getEventTypeString(XMLEvent.COMMENT) + " , "
0474: + getEventTypeString(XMLEvent.CDATA) + " , "
0475: + getEventTypeString(XMLEvent.SPACE)
0476: + " valid for getTextStart() ");
0477: }
0478: }
0479:
0480: /**
0481: * @return
0482: */
0483: public String getValue() {
0484: if (fEventType == XMLEvent.PROCESSING_INSTRUCTION) {
0485: return fScanner.getPIData().toString();
0486: } else if (fEventType == XMLEvent.COMMENT) {
0487: return fScanner.getComment();
0488: } else if (fEventType == XMLEvent.START_ELEMENT
0489: || fEventType == XMLEvent.END_ELEMENT) {
0490: return fScanner.getElementQName().localpart;
0491: } else if (fEventType == XMLEvent.CHARACTERS) {
0492: return fScanner.getCharacterData().toString();
0493: }
0494: return null;
0495: }//getValue()
0496:
0497: /** Get the XML language version of the current document being parsed */
0498: public String getVersion() {
0499: return fEntityScanner.getVersion();
0500: }
0501:
0502: /**
0503: * @return
0504: */
0505: public boolean hasAttributes() {
0506: return fScanner.getAttributeIterator().getLength() > 0 ? true
0507: : false;
0508: }
0509:
0510: /** this Funtion returns true if the current event has name */
0511: public boolean hasName() {
0512: if (fEventType == XMLEvent.START_ELEMENT
0513: || fEventType == XMLEvent.END_ELEMENT
0514: || fEventType == XMLEvent.ENTITY_REFERENCE) {
0515: return true;
0516: } else {
0517: return false;
0518: }
0519: }//hasName()
0520:
0521: /**
0522: * @throws XMLStreamException
0523: * @return
0524: */
0525: public boolean hasNext() throws XMLStreamException {
0526: //we can check in scanners if the scanner state is not set to
0527: //terminating, we still have more events.
0528: return fEventType != XMLEvent.END_DOCUMENT;
0529: }
0530:
0531: /**
0532: * @return
0533: */
0534: public boolean hasValue() {
0535: if (fEventType == XMLEvent.START_ELEMENT
0536: || fEventType == XMLEvent.END_ELEMENT
0537: || fEventType == XMLEvent.ENTITY_REFERENCE
0538: || fEventType == XMLEvent.PROCESSING_INSTRUCTION
0539: || fEventType == XMLEvent.COMMENT
0540: || fEventType == XMLEvent.CHARACTERS) {
0541: return true;
0542: } else {
0543: return false;
0544: }
0545:
0546: }
0547:
0548: /**
0549: * @return
0550: */
0551: public boolean isEndElement() {
0552: return fEventType == XMLEvent.END_ELEMENT;
0553: }
0554:
0555: /**
0556: * @return
0557: */
0558: public boolean isStandalone() {
0559: return fScanner.isStandAlone();
0560: }
0561:
0562: /**
0563: * @return
0564: */
0565: public boolean isStartElement() {
0566: return fEventType == XMLEvent.START_ELEMENT;
0567: }
0568:
0569: /**
0570: * Returns true if the cursor points to a character data event that consists of all whitespace
0571: * Application calling this method needs to cache the value and avoid calling this method again
0572: * for the same event.
0573: * @return
0574: */
0575: public boolean isWhiteSpace() {
0576: if (isCharacters() || (fEventType == XMLStreamConstants.CDATA)) {
0577: char[] ch = this .getTextCharacters();
0578: int start = this .getTextStart();
0579: int end = start + this .getTextLength();
0580: for (int i = start; i < end; i++) {
0581: if (!XMLChar.isSpace(ch[i])) {
0582: return false;
0583: }
0584: }
0585: return true;
0586: }
0587: return false;
0588: }
0589:
0590: /**
0591: * @throws XMLStreamException
0592: * @return
0593: */
0594: public int next() throws XMLStreamException {
0595: if (!hasNext()) {
0596: throw new java.util.NoSuchElementException(
0597: "END_DOCUMENT reached: no more elements on the stream.");
0598: }
0599: try {
0600: return fEventType = fScanner.next();
0601: } catch (IOException ex) {
0602: //ex.printStackTrace();
0603: throw new XMLStreamException(ex.getMessage(),
0604: getLocation(), ex);
0605: } catch (XNIException ex) {
0606: //ex.printStackTrace();
0607: throw new XMLStreamException(ex.getMessage(),
0608: getLocation(), ex.getException());
0609: }
0610:
0611: }//next()
0612:
0613: final static String getEventTypeString(int eventType) {
0614: switch (eventType) {
0615: case XMLEvent.START_ELEMENT:
0616: return "START_ELEMENT";
0617: case XMLEvent.END_ELEMENT:
0618: return "END_ELEMENT";
0619: case XMLEvent.PROCESSING_INSTRUCTION:
0620: return "PROCESSING_INSTRUCTION";
0621: case XMLEvent.CHARACTERS:
0622: return "CHARACTERS";
0623: case XMLEvent.COMMENT:
0624: return "COMMENT";
0625: case XMLEvent.START_DOCUMENT:
0626: return "START_DOCUMENT";
0627: case XMLEvent.END_DOCUMENT:
0628: return "END_DOCUMENT";
0629: case XMLEvent.ENTITY_REFERENCE:
0630: return "ENTITY_REFERENCE";
0631: case XMLEvent.ATTRIBUTE:
0632: return "ATTRIBUTE";
0633: case XMLEvent.DTD:
0634: return "DTD";
0635: case XMLEvent.CDATA:
0636: return "CDATA";
0637: case XMLEvent.SPACE:
0638: return "SPACE";
0639: }
0640: return "UNKNOWN_EVENT_TYPE , " + String.valueOf(eventType);
0641: }
0642:
0643: /** Returns the count of attributes on this START_ELEMENT,
0644: * this method is only valid on a START_ELEMENT or ATTRIBUTE. This
0645: * count excludes namespace definitions. Attribute indices are
0646: * zero-based.
0647: * @return returns the number of attributes
0648: * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE
0649: */
0650: public int getAttributeCount() {
0651: //xxx: recognize SAX properties namespace, namespace-prefix to get XML Namespace declarations
0652: //does length includes namespace declarations ?
0653:
0654: //State should be either START_ELEMENT or ATTRIBUTE
0655: if (fEventType == XMLEvent.START_ELEMENT
0656: || fEventType == XMLEvent.ATTRIBUTE) {
0657: return fScanner.getAttributeIterator().getLength();
0658: } else {
0659: throw new java.lang.IllegalStateException(
0660: "Current state is not among the states "
0661: + getEventTypeString(XMLEvent.START_ELEMENT)
0662: + " , "
0663: + getEventTypeString(XMLEvent.ATTRIBUTE)
0664: + "valid for getAttributeCount()");
0665: }
0666: }//getAttributeCount
0667:
0668: /** Returns the localName of the attribute at the provided
0669: * index
0670: * @param index the position of the attribute
0671: * @return the localName of the attribute
0672: * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE
0673: */
0674: public QName getAttributeName(int index) {
0675: //State should be either START_ELEMENT or ATTRIBUTE
0676: if (fEventType == XMLEvent.START_ELEMENT
0677: || fEventType == XMLEvent.ATTRIBUTE) {
0678: return convertXNIQNametoJavaxQName(fScanner
0679: .getAttributeIterator().getQualifiedName(index));
0680: } else {
0681: throw new java.lang.IllegalStateException(
0682: "Current state is not among the states "
0683: + getEventTypeString(XMLEvent.START_ELEMENT)
0684: + " , "
0685: + getEventTypeString(XMLEvent.ATTRIBUTE)
0686: + "valid for getAttributeName()");
0687: }
0688: }//getAttributeName
0689:
0690: /**
0691: * @param index
0692: * @return
0693: */
0694: public String getAttributeLocalName(int index) {
0695: //State should be either START_ELEMENT or ATTRIBUTE
0696: if (fEventType == XMLEvent.START_ELEMENT
0697: || fEventType == XMLEvent.ATTRIBUTE) {
0698: return fScanner.getAttributeIterator().getLocalName(index);
0699: } else {
0700: throw new java.lang.IllegalStateException(
0701: "Current state is not among the states "
0702: + getEventTypeString(XMLEvent.START_ELEMENT)
0703: + " , "
0704: + getEventTypeString(XMLEvent.ATTRIBUTE)
0705: + "valid for getAttributeLocalName()");
0706: }
0707: }//getAttributeName
0708:
0709: /** Returns the namespace of the attribute at the provided
0710: * index
0711: * @param index the position of the attribute
0712: * @return the namespace URI (can be null)
0713: * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE
0714: */
0715: public String getAttributeNamespace(int index) {
0716: //State should be either START_ELEMENT or ATTRIBUTE
0717: if (fEventType == XMLEvent.START_ELEMENT
0718: || fEventType == XMLEvent.ATTRIBUTE) {
0719: return fScanner.getAttributeIterator().getURI(index);
0720: } else {
0721: throw new java.lang.IllegalStateException(
0722: "Current state is not among the states "
0723: + getEventTypeString(XMLEvent.START_ELEMENT)
0724: + " , "
0725: + getEventTypeString(XMLEvent.ATTRIBUTE)
0726: + "valid for getAttributeNamespace()");
0727: }
0728:
0729: }//getAttributeNamespace
0730:
0731: /** Returns the prefix of this attribute at the
0732: * provided index
0733: * @param index the position of the attribute
0734: * @return the prefix of the attribute
0735: * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE
0736: */
0737: public String getAttributePrefix(int index) {
0738: //State should be either START_ELEMENT or ATTRIBUTE
0739: if (fEventType == XMLEvent.START_ELEMENT
0740: || fEventType == XMLEvent.ATTRIBUTE) {
0741: return fScanner.getAttributeIterator().getPrefix(index);
0742: } else {
0743: throw new java.lang.IllegalStateException(
0744: "Current state is not among the states "
0745: + getEventTypeString(XMLEvent.START_ELEMENT)
0746: + " , "
0747: + getEventTypeString(XMLEvent.ATTRIBUTE)
0748: + "valid for getAttributePrefix()");
0749: }
0750: }//getAttributePrefix
0751:
0752: /** Returns the qname of the attribute at the provided index
0753: *
0754: * @param index the position of the attribute
0755: * @return the QName of the attribute
0756: * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE
0757: */
0758: public javax.xml.namespace.QName getAttributeQName(int index) {
0759: //State should be either START_ELEMENT or ATTRIBUTE
0760: if (fEventType == XMLEvent.START_ELEMENT
0761: || fEventType == XMLEvent.ATTRIBUTE) {
0762: // create new object at runtime..
0763: String localName = fScanner.getAttributeIterator()
0764: .getLocalName(index);
0765: String uri = fScanner.getAttributeIterator().getURI(index);
0766: return new javax.xml.namespace.QName(uri, localName);
0767: } else {
0768: throw new java.lang.IllegalStateException(
0769: "Current state is not among the states "
0770: + getEventTypeString(XMLEvent.START_ELEMENT)
0771: + " , "
0772: + getEventTypeString(XMLEvent.ATTRIBUTE)
0773: + "valid for getAttributeQName()");
0774: }
0775: }//getAttributeQName
0776:
0777: /** Returns the XML type of the attribute at the provided
0778: * index
0779: * @param index the position of the attribute
0780: * @return the XML type of the attribute
0781: * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE
0782: */
0783: public String getAttributeType(int index) {
0784: //State should be either START_ELEMENT or ATTRIBUTE
0785: if (fEventType == XMLEvent.START_ELEMENT
0786: || fEventType == XMLEvent.ATTRIBUTE) {
0787: return fScanner.getAttributeIterator().getType(index);
0788: } else {
0789: throw new java.lang.IllegalStateException(
0790: "Current state is not among the states "
0791: + getEventTypeString(XMLEvent.START_ELEMENT)
0792: + " , "
0793: + getEventTypeString(XMLEvent.ATTRIBUTE)
0794: + "valid for getAttributeType()");
0795: }
0796:
0797: }//getAttributeType
0798:
0799: /** Returns the value of the attribute at the
0800: * index
0801: * @param index the position of the attribute
0802: * @return the attribute value
0803: * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE
0804: */
0805: public String getAttributeValue(int index) {
0806: //State should be either START_ELEMENT or ATTRIBUTE
0807: if (fEventType == XMLEvent.START_ELEMENT
0808: || fEventType == XMLEvent.ATTRIBUTE) {
0809: return fScanner.getAttributeIterator().getValue(index);
0810: } else {
0811: throw new java.lang.IllegalStateException(
0812: "Current state is not among the states "
0813: + getEventTypeString(XMLEvent.START_ELEMENT)
0814: + " , "
0815: + getEventTypeString(XMLEvent.ATTRIBUTE)
0816: + "valid for getAttributeValue()");
0817: }
0818:
0819: }//getAttributeValue
0820:
0821: /**
0822: * @param namespaceURI
0823: * @param localName
0824: * @return
0825: */
0826: public String getAttributeValue(String namespaceURI,
0827: String localName) {
0828: //State should be either START_ELEMENT or ATTRIBUTE
0829: if (fEventType == XMLEvent.START_ELEMENT
0830: || fEventType == XMLEvent.ATTRIBUTE) {
0831: return fScanner.getAttributeIterator().getValue(
0832: namespaceURI, localName);
0833: } else {
0834: throw new java.lang.IllegalStateException(
0835: "Current state is not among the states "
0836: + getEventTypeString(XMLEvent.START_ELEMENT)
0837: + " , "
0838: + getEventTypeString(XMLEvent.ATTRIBUTE)
0839: + "valid for getAttributeValue()");
0840: }
0841:
0842: }
0843:
0844: /** Reads the content of a text-only element. Precondition:
0845: * the current event is START_ELEMENT. Postcondition:
0846: * The current event is the corresponding END_ELEMENT.
0847: * @throws XMLStreamException if the current event is not a START_ELEMENT or if
0848: * a non text element is encountered
0849: */
0850: public String getElementText() throws XMLStreamException {
0851: if (getEventType() != XMLStreamConstants.START_ELEMENT) {
0852: throw new XMLStreamException(
0853: "parser must be on START_ELEMENT to read next text",
0854: getLocation());
0855: }
0856: int eventType = next();
0857: StringBuffer content = new StringBuffer();
0858: while (eventType != XMLStreamConstants.END_ELEMENT) {
0859: if (eventType == XMLStreamConstants.CHARACTERS
0860: || eventType == XMLStreamConstants.CDATA
0861: || eventType == XMLStreamConstants.SPACE
0862: || eventType == XMLStreamConstants.ENTITY_REFERENCE) {
0863: content.append(getText());
0864: } else if (eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
0865: || eventType == XMLStreamConstants.COMMENT) {
0866: // skipping
0867: } else if (eventType == XMLStreamConstants.END_DOCUMENT) {
0868: throw new XMLStreamException(
0869: "unexpected end of document when reading element text content");
0870: } else if (eventType == XMLStreamConstants.START_ELEMENT) {
0871: throw new XMLStreamException(
0872: "elementGetText() function expects text only elment but START_ELEMENT was encountered.",
0873: getLocation());
0874: } else {
0875: throw new XMLStreamException("Unexpected event type "
0876: + eventType, getLocation());
0877: }
0878: eventType = next();
0879: }
0880: return content.toString();
0881: }
0882:
0883: /** Return the current location of the processor.
0884: * If the Location is unknown the processor should return
0885: * an implementation of Location that returns -1 for the
0886: * location and null for the publicId and systemId.
0887: * The location information is only valid until next() is
0888: * called.
0889: */
0890: public Location getLocation() {
0891: return new Location() {
0892:
0893: public String getLocationURI() {
0894: return fEntityScanner.getExpandedSystemId();
0895: }
0896:
0897: public int getCharacterOffset() {
0898: return fEntityScanner.getCharacterOffset();
0899: }
0900:
0901: public int getColumnNumber() {
0902: return fEntityScanner.getColumnNumber();
0903: }
0904:
0905: public int getLineNumber() {
0906: return fEntityScanner.getLineNumber();
0907: }
0908:
0909: public String getPublicId() {
0910: return fEntityScanner.getPublicId();
0911: }
0912:
0913: public String getSystemId() {
0914: return fEntityScanner.getExpandedSystemId();
0915: }
0916:
0917: public String toString() {
0918: StringBuffer sbuffer = new StringBuffer();
0919: sbuffer.append("Line number = " + getLineNumber());
0920: sbuffer.append("\n");
0921: sbuffer.append("Column number = " + getColumnNumber());
0922: sbuffer.append("\n");
0923: sbuffer.append("System Id = " + getSystemId());
0924: sbuffer.append("\n");
0925: sbuffer.append("Public Id = " + getPublicId());
0926: sbuffer.append("\n");
0927: sbuffer.append("Location Uri= " + getLocationURI());
0928: sbuffer.append("\n");
0929: sbuffer.append("CharacterOffset = "
0930: + getCharacterOffset());
0931: sbuffer.append("\n");
0932: return sbuffer.toString();
0933: }
0934: };
0935:
0936: }
0937:
0938: /** Returns a QName for the current START_ELEMENT or END_ELEMENT event
0939: * @return the QName for the current START_ELEMENT or END_ELEMENT event
0940: */
0941: public javax.xml.namespace.QName getName() {
0942: if (fEventType == XMLEvent.START_ELEMENT
0943: || fEventType == XMLEvent.END_ELEMENT)
0944: return convertXNIQNametoJavaxQName(fScanner
0945: .getElementQName());
0946: else
0947: throw new java.lang.IllegalArgumentException(
0948: "Illegal to call getName() "
0949: + "when event type is "
0950: + getEventTypeString(fEventType)
0951: + "."
0952: + " Valid states are "
0953: + getEventTypeString(XMLEvent.START_ELEMENT)
0954: + ", "
0955: + getEventTypeString(XMLEvent.END_ELEMENT));
0956: }
0957:
0958: /** Returns a read only namespace context for the current
0959: * position. The context is transient and only valid until
0960: * a call to next() changes the state of the reader.
0961: * @return return a namespace context
0962: */
0963: public NamespaceContext getNamespaceContext() {
0964: return fNamespaceContextWrapper;
0965: }
0966:
0967: /** Returns the count of namespaces declared on this START_ELEMENT or END_ELEMENT,
0968: * this method is only valid on a START_ELEMENT, END_ELEMENT or NAMESPACE. On
0969: * an END_ELEMENT the count is of the namespaces that are about to go
0970: * out of scope. This is the equivalent of the information reported
0971: * by SAX callback for an end element event.
0972: * @return returns the number of namespace declarations on this specific element
0973: * @throws IllegalStateException if this is not a START_ELEMENT, END_ELEMENT or NAMESPACE
0974: */
0975: public int getNamespaceCount() {
0976: //namespaceContext is dynamic object.
0977: //REVISIT: check if it specifies all conditions mentioned in the javadoc
0978: if (fEventType == XMLEvent.START_ELEMENT
0979: || fEventType == XMLEvent.END_ELEMENT
0980: || fEventType == XMLEvent.NAMESPACE) {
0981: return fScanner.getNamespaceContext()
0982: .getDeclaredPrefixCount();
0983: } else {
0984: throw new IllegalStateException("Current state "
0985: + getEventTypeString(fEventType)
0986: + " is not among the states "
0987: + getEventTypeString(XMLEvent.START_ELEMENT) + ", "
0988: + getEventTypeString(XMLEvent.END_ELEMENT) + ", "
0989: + getEventTypeString(XMLEvent.NAMESPACE)
0990: + " valid for getNamespaceCount().");
0991: }
0992: }
0993:
0994: /** Returns the prefix for the namespace declared at the
0995: * index. Returns null if this is the default namespace
0996: * declaration
0997: *
0998: * @param index the position of the namespace declaration
0999: * @return returns the namespace prefix
1000: * @throws IllegalStateException if this is not a START_ELEMENT, END_ELEMENT or NAMESPACE
1001: */
1002: public String getNamespacePrefix(int index) {
1003: if (fEventType == XMLEvent.START_ELEMENT
1004: || fEventType == XMLEvent.END_ELEMENT
1005: || fEventType == XMLEvent.NAMESPACE) {
1006: //namespaceContext is dynamic object.
1007: String prefix = fScanner.getNamespaceContext()
1008: .getDeclaredPrefixAt(index);
1009: return prefix.equals("") ? null : prefix;
1010: } else {
1011: throw new IllegalStateException("Current state "
1012: + getEventTypeString(fEventType)
1013: + " is not among the states "
1014: + getEventTypeString(XMLEvent.START_ELEMENT) + ", "
1015: + getEventTypeString(XMLEvent.END_ELEMENT) + ", "
1016: + getEventTypeString(XMLEvent.NAMESPACE)
1017: + " valid for getNamespacePrefix().");
1018: }
1019: }
1020:
1021: /** Returns the uri for the namespace declared at the
1022: * index.
1023: *
1024: * @param index the position of the namespace declaration
1025: * @return returns the namespace uri
1026: * @throws IllegalStateException if this is not a START_ELEMENT, END_ELEMENT or NAMESPACE
1027: */
1028: public String getNamespaceURI(int index) {
1029: if (fEventType == XMLEvent.START_ELEMENT
1030: || fEventType == XMLEvent.END_ELEMENT
1031: || fEventType == XMLEvent.NAMESPACE) {
1032: //namespaceContext is dynamic object.
1033: return fScanner.getNamespaceContext().getURI(
1034: fScanner.getNamespaceContext().getDeclaredPrefixAt(
1035: index));
1036: } else {
1037: throw new IllegalStateException("Current state "
1038: + getEventTypeString(fEventType)
1039: + " is not among the states "
1040: + getEventTypeString(XMLEvent.START_ELEMENT) + ", "
1041: + getEventTypeString(XMLEvent.END_ELEMENT) + ", "
1042: + getEventTypeString(XMLEvent.NAMESPACE)
1043: + " valid for getNamespaceURI().");
1044: }
1045:
1046: }
1047:
1048: /** Get the value of a feature/property from the underlying implementation
1049: * @param name The name of the property, may not be null
1050: * @return The value of the property
1051: * @throws IllegalArgumentException if name is null
1052: */
1053: public Object getProperty(java.lang.String name)
1054: throws java.lang.IllegalArgumentException {
1055: if (name == null)
1056: throw new java.lang.IllegalArgumentException();
1057: if (fPropertyManager != null) {
1058: if (name.equals(fPropertyManager.STAX_NOTATIONS)) {
1059: return getNotationDecls();
1060: } else if (name.equals(fPropertyManager.STAX_ENTITIES)) {
1061: return getEntityDecls();
1062: } else
1063: return fPropertyManager.getProperty(name);
1064: }
1065: return null;
1066: }
1067:
1068: /** Returns the current value of the parse event as a string,
1069: * this returns the string value of a CHARACTERS event,
1070: * returns the value of a COMMENT, the replacement value
1071: * for an ENTITY_REFERENCE,
1072: * or the String value of the DTD
1073: * @return the current text or null
1074: * @throws java.lang.IllegalStateException if this state is not
1075: * a valid text state.
1076: */
1077: public String getText() {
1078: if (fEventType == XMLEvent.CHARACTERS
1079: || fEventType == XMLEvent.COMMENT
1080: || fEventType == XMLEvent.CDATA
1081: || fEventType == XMLEvent.SPACE) {
1082: //this requires creation of new string
1083: //fEventType == XMLEvent.ENTITY_REFERENCE
1084: return fScanner.getCharacterData().toString();
1085: } else if (fEventType == XMLEvent.ENTITY_REFERENCE) {
1086: String name = fScanner.getEntityName();
1087: if (name != null) {
1088: if (fScanner.foundBuiltInRefs)
1089: return fScanner.getCharacterData().toString();
1090:
1091: XMLEntityStorage entityStore = fEntityManager
1092: .getEntityStore();
1093: Hashtable ht = entityStore.getDeclaredEntities();
1094: Entity en = (Entity) ht.get(name);
1095: if (en == null)
1096: return null;
1097: if (en.isExternal())
1098: return ((Entity.ExternalEntity) en).entityLocation
1099: .getExpandedSystemId();
1100: else
1101: return ((Entity.InternalEntity) en).text;
1102: } else
1103: return null;
1104: } else if (fEventType == XMLEvent.DTD) {
1105: if (fDTDDecl != null) {
1106: return fDTDDecl;
1107: }
1108: XMLStringBuffer tmpBuffer = fScanner.getDTDDecl();
1109: fDTDDecl = tmpBuffer.toString();
1110: return fDTDDecl;
1111: } else {
1112: throw new IllegalStateException("Current state "
1113: + getEventTypeString(fEventType)
1114: + " is not among the states"
1115: + getEventTypeString(XMLEvent.CHARACTERS) + ", "
1116: + getEventTypeString(XMLEvent.COMMENT) + ", "
1117: + getEventTypeString(XMLEvent.CDATA) + ", "
1118: + getEventTypeString(XMLEvent.SPACE) + ", "
1119: + getEventTypeString(XMLEvent.ENTITY_REFERENCE)
1120: + ", " + getEventTypeString(XMLEvent.DTD)
1121: + " valid for getText() ");
1122: }
1123: }//getText
1124:
1125: /** Test if the current event is of the given type and if the namespace and name match the current namespace and name of the current event.
1126: * If the namespaceURI is null it is not checked for equality, if the localName is null it is not checked for equality.
1127: * @param type the event type
1128: * @param namespaceURI the uri of the event, may be null
1129: * @param localName the localName of the event, may be null
1130: * @throws XMLStreamException if the required values are not matched.
1131: */
1132: public void require(int type, String namespaceURI, String localName)
1133: throws XMLStreamException {
1134: if (type != fEventType)
1135: throw new XMLStreamException("Event type "
1136: + getEventTypeString(type) + " specified did "
1137: + "not match with current parser event "
1138: + getEventTypeString(fEventType));
1139: if (namespaceURI != null
1140: && !namespaceURI.equals(getNamespaceURI()))
1141: throw new XMLStreamException("Namespace URI "
1142: + namespaceURI + " specified did not match "
1143: + "with current namespace URI");
1144: if (localName != null && !localName.equals(getLocalName()))
1145: throw new XMLStreamException("LocalName " + localName
1146: + " specified did not match with "
1147: + "current local name");
1148:
1149: return;
1150: }
1151:
1152: /** Gets the the text associated with a CHARACTERS, SPACE or CDATA event.
1153: * Text starting a "sourceStart" is copied into "destination" starting at "targetStart".
1154: * Up to "length" characters are copied. The number of characters actually copied is returned.
1155: *
1156: * The "sourceStart" argument must be greater or equal to 0 and less than or equal to
1157: * the number of characters associated with the event. Usually, one requests text starting at a "sourceStart" of 0.
1158: * If the number of characters actually copied is less than the "length", then there is no more text.
1159: * Otherwise, subsequent calls need to be made until all text has been retrieved. For example:
1160: *
1161: * <code>
1162: * int length = 1024;
1163: * char[] myBuffer = new char[ length ];
1164: *
1165: * for ( int sourceStart = 0 ; ; sourceStart += length )
1166: * {
1167: * int nCopied = stream.getTextCharacters( sourceStart, myBuffer, 0, length );
1168: *
1169: * if (nCopied < length)
1170: * break;
1171: * }
1172: * </code>
1173: * XMLStreamException may be thrown if there are any XML errors in the underlying source.
1174: * The "targetStart" argument must be greater than or equal to 0 and less than the length of "target",
1175: * Length must be greater than 0 and "targetStart + length" must be less than or equal to length of "target".
1176: *
1177: * @param sourceStart the index of the first character in the source array to copy
1178: * @param target the destination array
1179: * @param targetStart the start offset in the target array
1180: * @param length the number of characters to copy
1181: * @return the number of characters actually copied
1182: * @throws XMLStreamException if the underlying XML source is not well-formed
1183: * @throws IndexOutOfBoundsException if targetStart < 0 or > than the length of target
1184: * @throws IndexOutOfBoundwhile(isCharacters()) ;sException if length < 0 or targetStart + length > length of target
1185: * @throws UnsupportedOperationException if this method is not supported
1186: * @throws NullPointerException is if target is null
1187: */
1188: public int getTextCharacters(int sourceStart, char[] target,
1189: int targetStart, int length) throws XMLStreamException {
1190:
1191: if (target == null) {
1192: throw new NullPointerException(
1193: "target char array can't be null");
1194: }
1195:
1196: if (targetStart < 0 || length < 0 || sourceStart < 0
1197: || targetStart >= target.length
1198: || (targetStart + length) > target.length) {
1199: throw new IndexOutOfBoundsException();
1200: }
1201:
1202: //getTextStart() + sourceStart should not be greater than the lenght of number of characters
1203: //present
1204: int copiedLength = 0;
1205: //int presentDataLen = getTextLength() - (getTextStart()+sourceStart);
1206: int available = getTextLength() - sourceStart;
1207: if (available < 0) {
1208: throw new IndexOutOfBoundsException(
1209: "sourceStart is greater than"
1210: + "number of characters associated with this event");
1211: }
1212: if (available < length) {
1213: copiedLength = available;
1214: } else {
1215: copiedLength = length;
1216: }
1217:
1218: System.arraycopy(getTextCharacters(), getTextStart()
1219: + sourceStart, target, targetStart, copiedLength);
1220: return copiedLength;
1221: }
1222:
1223: /** Return true if the current event has text, false otherwise
1224: * The following events have text:
1225: * CHARACTERS,DTD ,ENTITY_REFERENCE, COMMENT
1226: */
1227: public boolean hasText() {
1228: if (DEBUG)
1229: pr("XMLReaderImpl#EVENT TYPE = " + fEventType);
1230: if (fEventType == XMLEvent.CHARACTERS
1231: || fEventType == XMLEvent.COMMENT
1232: || fEventType == XMLEvent.CDATA) {
1233: return fScanner.getCharacterData().length > 0 ? true
1234: : false;
1235: } else if (fEventType == XMLEvent.ENTITY_REFERENCE) {
1236: String name = fScanner.getEntityName();
1237: if (name != null) {
1238: if (fScanner.foundBuiltInRefs)
1239: return true;
1240:
1241: XMLEntityStorage entityStore = fEntityManager
1242: .getEntityStore();
1243: Hashtable ht = entityStore.getDeclaredEntities();
1244: Entity en = (Entity) ht.get(name);
1245: if (en == null)
1246: return false;
1247: if (en.isExternal()) {
1248: return ((Entity.ExternalEntity) en).entityLocation
1249: .getExpandedSystemId() != null ? true
1250: : false;
1251: } else {
1252: return ((Entity.InternalEntity) en).text != null ? true
1253: : false;
1254: }
1255: } else
1256: return false;
1257: } else {
1258: if (fEventType == XMLEvent.DTD)
1259: return fScanner.fSeenDoctypeDecl;
1260: }
1261: return false;
1262: }
1263:
1264: /** Returns a boolean which indicates if this
1265: * attribute was created by default
1266: * @param index the position of the attribute
1267: * @return true if this is a default attribute
1268: * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE
1269: */
1270: public boolean isAttributeSpecified(int index) {
1271: //check that current state should be either START_ELEMENT or ATTRIBUTE
1272: if ((fEventType == XMLEvent.START_ELEMENT)
1273: || (fEventType == XMLEvent.ATTRIBUTE)) {
1274: return fScanner.getAttributeIterator().isSpecified(index);
1275: } else {
1276: throw new IllegalStateException(
1277: "Current state is not among the states "
1278: + getEventTypeString(XMLEvent.START_ELEMENT)
1279: + " , "
1280: + getEventTypeString(XMLEvent.ATTRIBUTE)
1281: + "valid for isAttributeSpecified()");
1282: }
1283: }
1284:
1285: /** Returns true if the cursor points to a character data event
1286: * @return true if the cursor points to character data, false otherwise
1287: */
1288: public boolean isCharacters() {
1289: return fEventType == XMLEvent.CHARACTERS;
1290: }
1291:
1292: /** Skips any insignificant events (COMMENT and PROCESSING_INSTRUCTION)
1293: * until a START_ELEMENT or
1294: * END_ELEMENT is reached. If other than space characters are
1295: * encountered, an exception is thrown. This method should
1296: * be used when processing element-only content because
1297: * the parser is not able to recognize ignorable whitespace if
1298: * then DTD is missing or not interpreted.
1299: * @return the event type of the element read
1300: * @throws XMLStreamException if the current event is not white space
1301: */
1302: public int nextTag() throws XMLStreamException {
1303:
1304: int eventType = next();
1305: while ((eventType == XMLStreamConstants.CHARACTERS && isWhiteSpace()) // skip whitespace
1306: || (eventType == XMLStreamConstants.CDATA && isWhiteSpace())
1307: // skip whitespace
1308: || eventType == XMLStreamConstants.SPACE
1309: || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
1310: || eventType == XMLStreamConstants.COMMENT) {
1311: eventType = next();
1312: }
1313: if (eventType != XMLStreamConstants.START_ELEMENT
1314: && eventType != XMLStreamConstants.END_ELEMENT) {
1315: throw new XMLStreamException("expected start or end tag",
1316: getLocation());
1317: }
1318: return eventType;
1319:
1320: }
1321:
1322: /** Checks if standalone was set in the document
1323: * @return true if standalone was set in the document, or false otherwise
1324: */
1325: public boolean standaloneSet() {
1326: //xxx: it requires if the standalone was set in the document ? This is different that if the document
1327: // is standalone
1328: return fScanner.isStandAlone();
1329: }
1330:
1331: /**
1332: * @param qname
1333: * @return
1334: */
1335: public javax.xml.namespace.QName convertXNIQNametoJavaxQName(
1336: com.sun.xml.stream.xerces.xni.QName qname) {
1337: if (qname == null)
1338: return null;
1339: //xxx: prefix definition ?
1340: if (qname.prefix == null) {
1341: return new javax.xml.namespace.QName(qname.uri,
1342: qname.localpart);
1343: } else {
1344: return new javax.xml.namespace.QName(qname.uri,
1345: qname.localpart, qname.prefix);
1346: }
1347: }
1348:
1349: /** Return the uri for the given prefix.
1350: * The uri returned depends on the current state of the processor.
1351: *
1352: * <p><strong>NOTE:</strong>The 'xml' prefix is bound as defined in
1353: * <a href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in XML</a>
1354: * specification to "http://www.w3.org/XML/1998/namespace".
1355: *
1356: * <p><strong>NOTE:</strong> The 'xmlns' prefix must be resolved to following namespace
1357: * <a href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a>
1358: * @return the uri bound to the given prefix or null if it is not bound
1359: * @param prefix The prefix to lookup, may not be null
1360: * @throws IllegalStateException if the prefix is null
1361: */
1362: public String getNamespaceURI(String prefix) {
1363: if (prefix == null)
1364: throw new java.lang.IllegalArgumentException(
1365: "getNamespaceURI(String prefix) is called with a null prefix.");
1366:
1367: //first add the string to symbol table.. since internally identity comparisons are done.
1368: return fScanner.getNamespaceContext().getURI(
1369: fSymbolTable.addSymbol(prefix));
1370: }
1371:
1372: //xxx: this function is not being used.
1373: protected void setPropertyManager(PropertyManager propertyManager) {
1374: fPropertyManager = propertyManager;
1375: //REVISIT: we were supplying hashmap ealier
1376: fScanner.setProperty("stax-properties", propertyManager);
1377: fScanner.setPropertyManager(propertyManager);
1378: }
1379:
1380: /**
1381: * @return returns the reference to property manager.
1382: */
1383: protected PropertyManager getPropertyManager() {
1384: return fPropertyManager;
1385: }
1386:
1387: static void pr(String str) {
1388: System.out.println(str);
1389: }
1390:
1391: protected List getEntityDecls() {
1392: if (fEventType == XMLStreamConstants.DTD) {
1393: XMLEntityStorage entityStore = fEntityManager
1394: .getEntityStore();
1395: Hashtable ht = entityStore.getDeclaredEntities();
1396: ArrayList list = null;
1397: if (ht != null) {
1398: EntityDeclarationImpl decl = null;
1399: list = new ArrayList(ht.size());
1400: Enumeration enu = ht.keys();
1401: while (enu.hasMoreElements()) {
1402: String key = (String) enu.nextElement();
1403: Entity en = (Entity) ht.get(key);
1404: decl = new EntityDeclarationImpl();
1405: decl.setEntityName(key);
1406: if (en.isExternal()) {
1407: decl
1408: .setXMLResourceIdentifier(((Entity.ExternalEntity) en).entityLocation);
1409: decl
1410: .setNotationName(((Entity.ExternalEntity) en).notation);
1411: } else
1412: decl
1413: .setEntityReplacementText(((Entity.InternalEntity) en).text);
1414: list.add(decl);
1415: }
1416: }
1417: return list;
1418: }
1419: return null;
1420: }
1421:
1422: protected List getNotationDecls() {
1423: if (fEventType == XMLStreamConstants.DTD) {
1424: if (fScanner.fDTDScanner == null)
1425: return null;
1426: DTDGrammar grammar = ((XMLDTDScannerImpl) (fScanner.fDTDScanner))
1427: .getGrammar();
1428: if (grammar == null)
1429: return null;
1430: List notations = grammar.getNotationDecls();
1431:
1432: Iterator it = notations.iterator();
1433: ArrayList list = new ArrayList();
1434: while (it.hasNext()) {
1435: XMLNotationDecl ni = (XMLNotationDecl) it.next();
1436: if (ni != null) {
1437: list.add(new NotationDeclarationImpl(ni));
1438: }
1439: }
1440: return list;
1441: }
1442: return null;
1443: }
1444:
1445: }//XMLReaderImpl
|