All Downloads are FREE. Search and download functionalities are using the official Maven repository.

es.rickyepoderi.wbxml.stream.WbXmlStreamReader Maven / Gradle / Ivy

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *    
 * Linking this library statically or dynamically with other modules 
 * is making a combined work based on this library. Thus, the terms and
 * conditions of the GNU General Public License cover the whole
 * combination.
 *    
 * As a special exception, the copyright holders of this library give 
 * you permission to link this library with independent modules to 
 * produce an executable, regardless of the license terms of these 
 * independent modules, and to copy and distribute the resulting 
 * executable under terms of your choice, provided that you also meet, 
 * for each linked independent module, the terms and conditions of the 
 * license of that module.  An independent module is a module which 
 * is not derived from or based on this library.  If you modify this 
 * library, you may extend this exception to your version of the 
 * library, but you are not obligated to do so.  If you do not wish 
 * to do so, delete this exception statement from your version.
 *
 * Project: github.com/rickyepoderi/wbxml-stream
 * 
 */
package es.rickyepoderi.wbxml.stream;

import es.rickyepoderi.wbxml.definition.WbXmlDefinition;
import es.rickyepoderi.wbxml.definition.WbXmlNamespaceDef;
import es.rickyepoderi.wbxml.document.WbXmlAttribute;
import es.rickyepoderi.wbxml.document.WbXmlContent;
import es.rickyepoderi.wbxml.document.WbXmlElement;
import es.rickyepoderi.wbxml.document.WbXmlParser;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

/**
 * 

The XMLStreamReader interface allows forward, read-only access to XML. * It is designed to be the lowest level and most efficient way to read XML data * and the interface is explained in * Java SE javadoc.

* *

The implementation in WBXML always creates initially a WbXmlDocument * java object in memory (it can be said that first the java/memory representation * is created in the constructor part and then the java object reprsentation * is iterated. The parser is used to implement the XMLStreamReader.

* *

The iteration over the parser is maintained with a event (the current * event the reader is right now) and a little ElementIndex which is * just the current element the reader is parsing and an index (the index * marks the content inside the element we are treating). A queue of parent * elements is also maintained to iterate over all the elements in document * parsed.

* *

Implementing the WbXmlEventReader it was discovered that ATTRIBUTE * event type should be returned as many times as attributes are in the * element. Currently it is only returned once (it was thought that). Besides * it was discovered that underlaying implentations never use this event. They * when START_ELEMENT is received get all the attributes using getAttributeXXX * methods. For that ATTRIBUTE event type is never returned. Please use * START_ELEMENT instead.

* * @author ricky */ public class WbXmlStreamReader implements XMLStreamReader { /** * Logger of the class. */ protected static final Logger log = Logger.getLogger(WbXmlStreamReader.class.getName()); /** * Namespace context that is initialized with the context used for every * language definition used by the parser. */ private WbXmlNamespaceContext nsctx; /** * The event the reader is right now. */ private int event; /** * The parser resulted after the parsing of the stream. */ private WbXmlParser parser; /** * Queue of elements to ietarte over all childs. */ private Deque parents; /** * Current element index (current element and index of the content). */ private ElementIndex elementIndex; /** * The input stream which is parsed with the parser. */ private InputStream is; /** * Little class to maintain the position of the reader. The position is * the current element and the current index in the contents of that element. */ private class ElementIndex { WbXmlElement currentElement; Integer index; } /** * Constructor using the parser. This is used when the parser already has * parsed a stream. The constructor set the event type to START:DOCUMENT. * @param parser The parser which already has a parsed document inside */ public WbXmlStreamReader(WbXmlParser parser) { this.is = null; this.elementIndex = new ElementIndex(); this.parents = new ArrayDeque(); this.parser = parser; this.nsctx = new WbXmlNamespaceContext(); // add namespaces for (WbXmlNamespaceDef nsDef : parser.getDefinition().getNamespaces()) { nsctx.addPrefix(nsDef.getPrefix(), nsDef.getNamespace()); } for (WbXmlDefinition def: parser.getDefinition().getLinkedDefs()) { for (WbXmlNamespaceDef nsDef: def.getNamespaces()) { nsctx.addPrefix(nsDef.getPrefix(), nsDef.getNamespace()); } } event = START_DOCUMENT; } /** * Constructor using the input stream. The parser is created and the * stream is parsed inside the constructor. The constructor set the event * type to START:DOCUMENT. * @param is The input stream with the WBXML document * @param definition The fixed definition to use * @throws IOException Some error parsing the stream */ public WbXmlStreamReader(InputStream is, WbXmlDefinition definition) throws IOException { this.is = is; this.elementIndex = new ElementIndex(); this.parents = new ArrayDeque(); parser = new WbXmlParser(this.is); parser.parse(definition); this.nsctx = new WbXmlNamespaceContext(); // add namespaces for (WbXmlNamespaceDef nsDef : parser.getDefinition().getNamespaces()) { nsctx.addPrefix(nsDef.getPrefix(), nsDef.getNamespace()); } for (WbXmlDefinition def: parser.getDefinition().getLinkedDefs()) { for (WbXmlNamespaceDef nsDef: def.getNamespaces()) { nsctx.addPrefix(nsDef.getPrefix(), nsDef.getNamespace()); } } event = START_DOCUMENT; } /** * Constructor using the input stream. Created via input stream and * not specifying a fixed definition. * @param is The input stream with the WBXML document * @throws IOException Some error parsing the stream */ public WbXmlStreamReader(InputStream is) throws IOException { this(is, null); } /** * Getter the parser for event readers. * @return The parser used for reading */ public WbXmlParser getParser() { return parser; } /** * Getter for the current element being parsed * @return The current element being parsed */ public WbXmlElement getCurrentElement() { return this.elementIndex.currentElement; } /** * Getter for the namespace context * @return The namespace context created for the parsing */ public WbXmlNamespaceContext getContext() { return this.nsctx; } // // XMLStreamReader methods // /** * Returns true if the cursor points to a character data event. In the * WbXmlStreamReader only CHARACTERS, ENTITY_REFERENCE (no CDATA is managed). * @return true if the cursor points to character data, false otherwise */ @Override public boolean isCharacters() { log.log(Level.FINE, "isCharacters(): {0}", event == CHARACTERS); return event == CHARACTERS; } /** * Returns true if the cursor points to a start tag (otherwise false) * @return true if the cursor points to a start tag, false otherwise */ @Override public boolean isStartElement() { log.log(Level.FINE, "isStartElement(): {0}", event == START_ELEMENT); return event == START_ELEMENT; } /** * Returns true if the cursor points to an end tag (otherwise false) * @return true if the cursor points to an end tag, false otherwise */ @Override public boolean isEndElement() { log.log(Level.FINE, "isEndElement(): {0}", event == END_ELEMENT); return event == END_ELEMENT; } /** * Returns true if the cursor points to a character data event that consists of all whitespace. * NOTE: XMLChar.isSpace(char) is used which is a internal method. * @return true if the cursor points to all whitespace, false otherwise */ @Override public boolean isWhiteSpace() { log.log(Level.FINE, "isWhiteSpace():"); if (event == CHARACTERS) { char[] ch = getTextCharacters(); final int start = this.getTextStart(); final int end = start + this.getTextLength(); for (int i = start; i < end; i++) { if (!XMLChar.isSpace(ch[i])) { log.log(Level.FINE, "isWhiteSpace(): {0}", false); return false; } } log.log(Level.FINE, "isWhiteSpace(): {0}", true); return true; } else { throw new IllegalStateException("Not in CHARACTERS state"); } } /** * Returns a boolean which indicates if this attribute was created by default. * It returns true if current element has an attribute at this index * @param index the position of the attribute * @return true if this is a default attribute */ @Override public boolean isAttributeSpecified(int index) { log.log(Level.FINE, "isAttributeSpecified({0})", index); if (event != ATTRIBUTE && event != START_ELEMENT) { throw new IllegalStateException("isAttributeSpecified called in another state!"); } else { return elementIndex.currentElement.attributesSize() > index; } } /** * Private method that searches the next element inside the current element. * If the index is null we are right now in the start element and the next * event could be attributes of the first content. If the index is not null * we advance in the next content. That content could be a string, entity, * pi or another element. If the content is an element the parent is added * to the queue and start element is returned. If it is the other possibilities * just the correspondent event is treated. * * @param attributes boolean that marks if we want to read attributes or not * @return The next element following the commented process */ private int nextInElement(boolean attributes) { if (attributes && !elementIndex.currentElement.isAttributesEmpty()) { // attributes elementIndex.index = null; event = ATTRIBUTE; } else if (elementIndex.index != null && elementIndex.currentElement.contentsSize() > elementIndex.index) { // get the index content and guess event type WbXmlContent content = elementIndex.currentElement.getContent(elementIndex.index); if (content.isEntity()) { event = ENTITY_REFERENCE; } else if (content.isString()) { event = CHARACTERS; } else if (content.isPi()) { event = PROCESSING_INSTRUCTION; } else { parents.push(elementIndex); elementIndex = new ElementIndex(); elementIndex.currentElement = content.getElement(); elementIndex.index = null; event = START_ELEMENT; } } else { event = END_ELEMENT; } return event; } /** * Get next parsing event - a processor may return all contiguous character * data in a single chunk, or it may split it into several chunks. If the * property javax.xml.stream.isCoalescing is set to true element content * must be coalesced and only one CHARACTERS event must be returned for * contiguous element content or CDATA Sections. By default entity * references must be expanded and reported transparently to the application. * An exception will be thrown if an entity reference cannot be expanded. * If element content is empty (i.e. content is "") then no CHARACTERS * event will be reported. * *

This method marks the current element and index using the * elementIndex structure. Besides a queue of parents element index is * maintained to cross over all element hierarchy.

* *

The WbXMLStreamReader only manages the following states:

* *
    *
  • START_DOCUMENT
  • *
  • PROCESSING_INSTRUCTION
  • *
  • START_ELEMENT
  • *
  • ATTRIBUTE
  • *
  • CHARACTERS
  • *
  • END_ELEMENT
  • *
  • SPACE
  • *
  • END_DOCUMENT
  • *
  • ENTITY_REFERENCE
  • *
* *

Therefore the following element does no matter in this stream reader:

* *
    *
  • CDATA (CHARACTERS are used always).
  • *
  • COMMENT (no comments in WBXML).
  • *
  • DTD (no DTD section)
  • *
  • ENTITY_DECLARATION
  • *
  • NAMESPACE
  • *
  • NOTATION DECLARATION
  • *
* * @return the integer code corresponding to the current parse event * @throws XMLStreamException if there is an error processing the underlying XML source */ @Override public int next() throws XMLStreamException { log.fine("next()"); // possible states: START_DOCUMENT PROCESSING_INSTRUCTION // START_ELEMENT ATTRIBUTE CHARACTERS END_ELEMENT // SPACE END_DOCUMENT // ENTITY_REFERENCE if (event == START_DOCUMENT) { // point to the first element in the doc or pi event = START_ELEMENT; elementIndex.currentElement = parser.getDocument().getBody().getElement(); } else if (event == START_ELEMENT) { // the next can be END_ELEMENT, ATTRIBUTE, CAHARACTERS, PROCESSING_INSTRUCTION elementIndex.index = 0; // Never return ATTRIBUTE event = nextInElement(false); } else if (event == ATTRIBUTE) { // the nest event can be CHARACTERS PROCESSING_INSTRUCTION elementIndex.index = 0; event = nextInElement(false); } else if (event == CHARACTERS) { elementIndex.index++; event = nextInElement(false); } else if (event == SPACE) { elementIndex.index++; event = nextInElement(false); } else if (event == ENTITY_REFERENCE) { elementIndex.index++; event = nextInElement(false); } else if (event == PROCESSING_INSTRUCTION) { elementIndex.index++; event = nextInElement(false); } else if (event == END_ELEMENT) { // get the saved element in the queue if (parents.isEmpty()) { event = END_DOCUMENT; } else { elementIndex = parents.pop(); elementIndex.index++; event = nextInElement(false); } } else if (event == END_DOCUMENT) { throw new XMLStreamException("End of coument reached!"); } else { throw new XMLStreamException("Invalid event state!"); } log.log(Level.FINE, "next(): {0}", event); return event; } /** * Get the value of a feature/property from the underlying implementation. * NOTE: always returns null cos no properties defined til the moment * @param name The name of the property, may not be null * @return The value of the property * @throws IllegalArgumentException */ @Override public Object getProperty(String name) throws IllegalArgumentException { log.log(Level.FINE, "getProperty({0})", name); if (XMLInputFactory.IS_NAMESPACE_AWARE.equals(name)) { // is namespace aware if namespaces are defined return this.parser.getDefinition().getNamespaces().size() > 0; } else { return null; } } /** * 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. * If the namespaceURI is null it is not checked for equality, if the * localName is null it is not checked for equality. * * NOTE: Not implemented, it throws an exception * * @param type the event type * @param namespaceURI the uri of the event, may be null * @param localName the localName of the event, may be null * @throws XMLStreamException if the required values are not matched. */ @Override public void require(int type, String namespaceURI, String localName) throws XMLStreamException { throw new UnsupportedOperationException("Not supported yet."); } /**

* Reads the content of a text-only element, an exception is thrown if * this is not a text-only element. Regardless of value of * javax.xml.stream.isCoalescing this method always returns coalesced * content.

*

Precondition: the current event is START_ELEMENT.

*

Postcondition: the current event is the corresponding END_ELEMENT.

* * NOTE: It is just implemented like it is commented in the interface!!! * * @return The string of element texts * @throws XMLStreamException if the current event is not a START_ELEMENT or if a non text element is encountered */ @Override public String getElementText() throws XMLStreamException { log.log(Level.FINE, "getElementText()"); if (getEventType() != START_ELEMENT) { throw new XMLStreamException( "parser must be on START_ELEMENT to read next text"); } int eventType = next(); StringBuilder buf = new StringBuilder(); while (eventType != END_ELEMENT) { if (eventType == CHARACTERS || eventType == CDATA || eventType == SPACE || eventType == ENTITY_REFERENCE) { buf.append(getText()); } else if (eventType == PROCESSING_INSTRUCTION || eventType == COMMENT) { // skipping } else if (eventType == END_DOCUMENT) { throw new XMLStreamException( "unexpected end of document when reading element text content"); } else if (eventType == START_ELEMENT) { throw new XMLStreamException( "element text content may not contain START_ELEMENT"); } else { throw new XMLStreamException( "Unexpected event type " + eventType); } eventType = next(); } log.log(Level.FINE, "getElementText(): {0}", buf.toString()); return buf.toString(); } /** *

Skips any white space (isWhiteSpace() returns true), COMMENT, or * PROCESSING_INSTRUCTION, until a START_ELEMENT or END_ELEMENT is reached. * If other than white space characters, COMMENT, PROCESSING_INSTRUCTION, * START_ELEMENT, END_ELEMENT are encountered, an exception is thrown. * This method should be used when processing element-only content seperated * by white space.

*

Precondition: none

*

Postcondition: the current event is START_ELEMENT or END_ELEMENT and * cursor may have moved over any whitespace event.

* * NOTE: Implemented like commented in the interface * * @return the event type of the element read (START_ELEMENT or END_ELEMENT) * @throws XMLStreamException if the current event is not white space, * PROCESSING_INSTRUCTION, START_ELEMENT or END_ELEMENT */ @Override public int nextTag() throws XMLStreamException { log.log(Level.FINE, "nextTag()"); int eventType = next(); while ((eventType == CHARACTERS && isWhiteSpace()) // skip whitespace || (eventType == CDATA && isWhiteSpace()) // skip whitespace || eventType == SPACE || eventType == PROCESSING_INSTRUCTION || eventType == COMMENT) { eventType = next(); } if (eventType != START_ELEMENT && eventType != END_ELEMENT) { throw new XMLStreamException(String.format("expected start or end tag and found %d", eventType)); } log.log(Level.FINE, "nextTag(): {0}", eventType); return eventType; } /** * Returns true if there are more parsing events and false if there are no * more events. This method will return false if the current state of the * XMLStreamReader is END_DOCUMENT * @return true if there are more events, false otherwise * @throws XMLStreamException if there is a fatal error detecting the next state */ @Override public boolean hasNext() throws XMLStreamException { log.log(Level.FINE, "hasNext(): {0}", event != END_DOCUMENT); return event != END_DOCUMENT; } /** * Frees any resources associated with this Reader. This method does not * close the underlying input source. * @throws XMLStreamException if there are errors freeing associated resources */ @Override public void close() throws XMLStreamException { this.parser = null; //try { // if (is != null) { // is.close(); // } //} catch (IOException e) { // throw new XMLStreamException(e); //} } /** * Return the uri for the given prefix. The uri returned depends on the * current state of the processor. In this stream reader * implementation all the prefixes for the languages used in the * parser are added into the NamespaceContext property. * *

NOTE:The 'xml' prefix is bound as defined in Namespaces in XML * specification to "http://www.w3.org/XML/1998/namespace"

*

NOTE: The 'xmlns' prefix must be resolved to following namespace * http://www.w3.org/2000/xmlns/

* @param prefix The prefix to lookup, may not be null */ @Override public String getNamespaceURI(String prefix) { String namespaceURI = nsctx.getNamespaceURI(prefix); log.log(Level.FINE, "getNamespaceURI(): {0}", namespaceURI); return namespaceURI; } /** * Returns the normalized attribute value of the attribute with the * namespace and localName If the namespaceURI is null the namespace is * not checked for equality. * * @param namespaceURI the namespace of the attribute * @param localName the local name of the attribute, cannot be null * @return returns the value of the attribute , returns null if not found */ @Override public String getAttributeValue(String namespaceURI, String localName) { log.log(Level.FINE, "getAttributeValue({0}, {1})", new Object[]{namespaceURI, localName}); if (event != START_ELEMENT && event != ATTRIBUTE) { throw new IllegalStateException("Not in START_ELEMENT or ATTRIBUTE"); } // locate the prefix if used if (namespaceURI != null && !namespaceURI.isEmpty()) { String prefix = parser.getDefinition().getPrefixWithLinked(namespaceURI); localName = new StringBuilder(prefix).append(":").append(localName).toString(); } // get the atrribute WbXmlAttribute attr = elementIndex.currentElement.getAttribute(localName); String result = null; if (attr != null) { result = attr.getValue(); } log.log(Level.FINE, "getAttributeValue(): {0}", result); return result; } /** * Returns the count of attributes on this START_ELEMENT, this method is * only valid on a START_ELEMENT or ATTRIBUTE. This count excludes namespace * definitions. Attribute indices are zero-based. * * @return returns the number of attributes */ @Override public int getAttributeCount() { log.log(Level.FINE, "getAttributeCount()"); if (event != START_ELEMENT && event != ATTRIBUTE) { throw new IllegalStateException("Not in START_ELEMENT or ATTRIBUTE"); } log.log(Level.FINE, "getAttributeCount(): {0}", elementIndex.currentElement.attributesSize()); return elementIndex.currentElement.attributesSize(); } /** * Returns the qname of the attribute at the provided index. * @param i the position of the attribute * @return QName of the attribute */ @Override public QName getAttributeName(int i) { log.log(Level.FINE, "getAttributeName({0})", i); if (event != START_ELEMENT && event != ATTRIBUTE) { throw new IllegalStateException("Not in START_ELEMENT or ATTRIBUTE"); } WbXmlAttribute attr = elementIndex.currentElement.getAttribute(i); QName result = null; if (attr != null) { if (attr.isPrefixed()) { // get the prefix and the namespace String prefix = attr.getNamePrefix(); String namespaceURI = parser.getDefinition().getPrefixWithLinked(prefix); result = new QName(namespaceURI, attr.getNameWithoutPrefix(), prefix); } else { result = new QName(attr.getName()); } } log.log(Level.FINE, "getAttributeName(): {0}", result); return result; } /** * Returns the namespace of the attribute at the provided index. * @param i the position of the attribute * @return the namespace URI (can be null) */ @Override public String getAttributeNamespace(int i) { log.log(Level.FINE, "getAttributeNamespace({0})", i); if (event != START_ELEMENT && event != ATTRIBUTE) { throw new IllegalStateException("Not in START_ELEMENT or ATTRIBUTE"); } WbXmlAttribute attr = elementIndex.currentElement.getAttribute(i); String result = null; if (attr != null) { if (attr.isPrefixed()) { // it has a prefix result = parser.getDefinition().getNamespaceURIWithLinked(attr.getNamePrefix()); } else { result = XMLConstants.NULL_NS_URI; } } log.log(Level.FINE, "getAttributeNamespace(): {0}", result); return result; } /** * Returns the localName of the attribute at the provided index * @param i the position of the attribute * @return the localName of the attribute */ @Override public String getAttributeLocalName(int i) { log.log(Level.FINE, "getAttributeLocalName({0})", i); if (event != START_ELEMENT && event != ATTRIBUTE) { throw new IllegalStateException("Not in START_ELEMENT or ATTRIBUTE"); } WbXmlAttribute attr = elementIndex.currentElement.getAttribute(i); String result = null; if (attr != null) { result = attr.getNameWithoutPrefix(); } log.log(Level.FINE, "getAttributeLocalName(): {0}", result); return result; } /** * Returns the prefix of this attribute at the provided index. * @param i the position of the attribute * @return the prefix of the attribute */ @Override public String getAttributePrefix(int i) { log.log(Level.FINE, "getAttributePrefix({0})", i); if (event != START_ELEMENT && event != ATTRIBUTE) { throw new IllegalStateException("Not in START_ELEMENT or ATTRIBUTE"); } WbXmlAttribute attr = elementIndex.currentElement.getAttribute(i); String result = null; if (attr != null) { if (attr.isPrefixed()) { // it has a prefix result = attr.getNamePrefix(); } else { result = XMLConstants.DEFAULT_NS_PREFIX; } } log.log(Level.FINE, "getAttributePrefix(): {0}", result); return result; } /** * Returns the XML type of the attribute at the provided index * NOTE. Always returns the "" empty type * @param i the position of the attribute * @return the XML type of the attribute */ @Override public String getAttributeType(int i) { log.log(Level.FINE, "getAttributeType({0}): ", i); // TODO what here return ""; } /** * Returns the value of the attribute at the index * @param i the position of the attribute * @return the attribute value */ @Override public String getAttributeValue(int i) { log.log(Level.FINE, "getAttributeValue({0})", i); if (event != START_ELEMENT && event != ATTRIBUTE) { throw new IllegalStateException("Not in START_ELEMENT or ATTRIBUTE"); } WbXmlAttribute attr = elementIndex.currentElement.getAttribute(i); String result = null; if (attr != null) { result = attr.getValue(); } log.log(Level.FINE, "getAttributeValue(): {0}", result); return result; } /** *

Returns the count of namespaces declared on this START_ELEMENT or * END_ELEMENT, this method is only valid on a START_ELEMENT, END_ELEMENT * or NAMESPACE. Always return 0

* *

This implementation just returns the namespaces for the root * elements in each namespace used. The idea is the root element defines * all the elements in the language definition.

* * @return returns the number of namespace declarations on this specific element */ @Override public int getNamespaceCount() { log.fine("getNamespaceCount()"); int result = 0; log.log(Level.FINE, "getNamespaceCount(): {0}", result); return result; } /** * Returns the prefix for the namespace declared at the index. Returns null * if this is the default namespace declaration. As it is said only root * language definition element has namespaces. Always return null. * * @param i the position of the namespace declaration * @return returns the namespace uri */ @Override public String getNamespacePrefix(int i) { log.log(Level.FINE, "getNamespacePrefix({0})", i); String result = null; log.log(Level.FINE, "getNamespaceCount(): {0}", result); return result; } /** * Returns the uri for the namespace declared at the index. As it is said * only root elements of the language definitions used by the parser * has the namespaces defined. Always return null. * * @param i the position of the namespace declaration * @return returns the namespace uri */ @Override public String getNamespaceURI(int i) { log.log(Level.FINE, "getNamespaceURI({0})", i); String result = null; log.log(Level.FINE, "getNamespaceCount(): {0}", result); return result; } /** * Returns a read only namespace context for the current position. * The context is transient and only valid until a call to next() changes * the state of the reader. * @return return a namespace context */ @Override public NamespaceContext getNamespaceContext() { log.fine("getNamespaceContext()"); return nsctx; } /** * Returns an integer code that indicates the type of the event the cursor is pointing to. * @return The current event type */ @Override public int getEventType() { return event; } /** *

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.

* * @return the current text or null */ @Override public String getText() { log.log(Level.FINE, "getText()"); if (event != CHARACTERS && event != SPACE && event != ENTITY_REFERENCE) { throw new IllegalStateException("Not in text event"); } log.log(Level.FINE, "getText(): {0}", elementIndex.currentElement.getContent(elementIndex.index).getString()); return elementIndex.currentElement.getContent(elementIndex.index).getString(); } /** * Returns an array which contains the characters from this event. This * array should be treated as read-only and transient. I.e. the array will * contain the text characters until the XMLStreamReader moves on to the * next event. Attempts to hold onto the character array beyond that time * or modify the contents of the array are breaches of the contract for * this interface. * @return the current text or an empty array */ @Override public char[] getTextCharacters() { String result = getText(); return (result != null)? result.toCharArray(): new char[0]; } /** * Gets the the text associated with a CHARACTERS, SPACE or CDATA event. * Text starting a "sourceStart" is copied into "target" starting at * "targetStart". Up to "length" characters are copied. The number of * characters actually copied is returned. The "sourceStart" argument must * be greater or equal to 0 and less than or equal to the number of * characters associated with the event. Usually, one requests text * starting at a "sourceStart" of 0. If the number of characters actually * copied is less than the "length", then there is no more text. Otherwise, * subsequent calls need to be made until all text has been retrieved. * For example: int length = 1024; char[] myBuffer = new char[ length ]; * for ( int sourceStart = 0 ; ; sourceStart += length ) { int nCopied = * stream.getTextCharacters( sourceStart, myBuffer, 0, length ); if * (nCopied < length) break; } XMLStreamException may be thrown if there * are any XML errors in the underlying source. The "targetStart" argument * must be greater than or equal to 0 and less than the length of "target", * Length must be greater than 0 and "targetStart + length" must be less * than or equal to length of "target". * * @param sourceStart the index of the first character in the source array to copy * @param target the destination array * @param targetStart the start offset in the target array * @param length the number of characters to copy * @return the number of characters actually copied * @throws XMLStreamException if the underlying XML source is not well-formed */ @Override public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) throws XMLStreamException { getText().getChars(sourceStart,sourceStart+length,target,targetStart); return length; } /** * Returns the offset into the text character array where the first character (of this text event) is stored. * @return Always 0 */ @Override public int getTextStart() { return 0; } /** * Returns the length of the sequence of characters for this Text event within the text character array * @return The length of the text */ @Override public int getTextLength() { return getText().length(); } /** * Return input encoding if known or null if unknown * @return The encoding of the WBXML document */ @Override public String getEncoding() { log.log(Level.FINE, "getEncoding()"); return parser.getCharset().name(); } /** * Return true if the current event has text, false otherwise The following * events have text: CHARACTERS,DTD ,ENTITY_REFERENCE, COMMENT, SPACE * @return true if current event is CHARACTERS or ENTITY_REFERENCE (only available text events in WBXML reader) */ @Override public boolean hasText() { log.log(Level.FINE, "hasText()"); return event == CHARACTERS || event == ENTITY_REFERENCE; } /** * Return the current location of the processor. If the Location is unknown * the processor should return an implementation of Location that * returns -1 for the location and null for the publicId and systemId. * The location information is only valid until next() is called * @return An empty location (not implemented) */ @Override public Location getLocation() { log.log(Level.FINE, "getLocation()"); return new Location() { @Override public int getCharacterOffset() { return 0; } @Override public int getColumnNumber() { return 0; } @Override public int getLineNumber() { return -1; } @Override public String getPublicId() { return null; } @Override public String getSystemId() { return null; } }; } /** * Returns a QName for the current START_ELEMENT or END_ELEMENT event * @return the QName for the current START_ELEMENT or END_ELEMENT event */ @Override public QName getName() { log.log(Level.FINE, "getName()"); QName qname; if (event == START_ELEMENT || event == END_ELEMENT) { log.log(Level.FINE, "tag={0}", elementIndex.currentElement.getTag()); if (elementIndex.currentElement.isPrefixed()) { String prefix = elementIndex.currentElement.getTagPrefix(); String namespaceURI = parser.getDefinition().getNamespaceURIWithLinked(prefix); qname = new QName(namespaceURI, elementIndex.currentElement.getTagWithoutPrefix(), prefix); } else { qname = new QName(elementIndex.currentElement.getTag()); } } else { throw new IllegalStateException("Not in START_ELEMENT, END_ELEMENT"); } log.log(Level.FINE, "getName(): {0}", qname); return qname; } /** * Returns the (local) name of the current event. For START_ELEMENT or * END_ELEMENT returns the (local) name of the current element. For * ENTITY_REFERENCE it returns entity name. The current event must be * START_ELEMENT or END_ELEMENT, or ENTITY_REFERENCE * @return the localName */ @Override public String getLocalName() { log.log(Level.FINE, "getLocalName()"); String localName; if (event == START_ELEMENT || event == END_ELEMENT) { localName = elementIndex.currentElement.getTagWithoutPrefix(); } else if (event == ENTITY_REFERENCE) { localName = elementIndex.currentElement.getContent(elementIndex.index).getString(); } else { throw new IllegalStateException("Not in START_ELEMENT, END_ELEMENT or ENTITY_REFERENCE"); } log.log(Level.FINE, "getLocalName(): {0}", localName); return localName; } /** * returns true if the current event has a name (is a START_ELEMENT or END_ELEMENT) returns false otherwise * @return true if current event is a START_ELEMENT or END_ELEMENT */ @Override public boolean hasName() { log.log(Level.FINE, "hasName(): {0}", event == START_ELEMENT || event == END_ELEMENT); return event == START_ELEMENT || event == END_ELEMENT; } /** * the current event is a START_ELEMENT or END_ELEMENT this method returns * the URI of the prefix or the default namespace. Returns null if the event * does not have a prefix. * @return the URI bound to this elements prefix, the default namespace, or null */ @Override public String getNamespaceURI() { log.log(Level.FINE, "getNamespaceURI()"); String namespace = XMLConstants.DEFAULT_NS_PREFIX; if (event == START_ELEMENT || event == END_ELEMENT) { if (elementIndex.currentElement.isPrefixed()) { String prefix = elementIndex.currentElement.getTagPrefix(); namespace = parser.getDefinition().getNamespaceURIWithLinked(prefix); } else { namespace = XMLConstants.NULL_NS_URI; } } log.log(Level.FINE, "getNamespaceURI(): {0}", namespace); return namespace; } /** * Returns the prefix of the current event or null if the event does not have a prefix * @return the prefix or null */ @Override public String getPrefix() { log.log(Level.FINE, "getPrefix()"); String prefix = null; if (event == START_ELEMENT || event == END_ELEMENT) { if (elementIndex.currentElement.isPrefixed()) { prefix = elementIndex.currentElement.getTagPrefix(); } else { prefix = XMLConstants.DEFAULT_NS_PREFIX; } } log.log(Level.FINE, "getPrefix(): {0}", prefix); return prefix; } /** * Get the xml version declared on the xml declaration Returns null if none was declared. * NOTE: Always returns 1.0 * @return the XML version or null */ @Override public String getVersion() { log.log(Level.FINE, "getVersion(): 1.0"); return "1.0"; } /** * Get the standalone declaration from the xml declaration. * It always return false. * @return true if standalone was set in the document, or false otherwise */ @Override public boolean isStandalone() { return false; } /** * Checks if standalone was set in the document. * It always return false. * @return true if standalone was set in the document, or false otherwise */ @Override public boolean standaloneSet() { return false; } /** * Returns the character encoding declared on the xml declaration Returns null if none was declared * @return the encoding declared in the document or null */ @Override public String getCharacterEncodingScheme() { log.fine("getCharacterEncodingScheme()"); return parser.getCharset().name(); } /** * Get the target of a processing instruction. * NOTE: Unsupported, it throws and exception * @return the target or null */ @Override public String getPITarget() { throw new UnsupportedOperationException("Not supported yet."); } /** * Get the data section of a processing instruction * @return the data or null */ @Override public String getPIData() { throw new UnsupportedOperationException("Not supported yet."); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy