alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (StAXDocumentParser.java)

This example Java source code file (StAXDocumentParser.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

cdata, characters, comment, end_document, end_element, fastinfosetexception, internal_state_void, ioexception, log, logging, object, processing_instruction, qualifiedname, start_element, string, util, xmlstreamexception

The StAXDocumentParser.java Java example source code

/*
 * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC.
 */

package com.sun.xml.internal.fastinfoset.stax;

import com.sun.xml.internal.fastinfoset.Decoder;
import com.sun.xml.internal.fastinfoset.DecoderStateTables;
import com.sun.xml.internal.fastinfoset.EncodingConstants;
import com.sun.xml.internal.fastinfoset.OctetBufferListener;
import com.sun.xml.internal.fastinfoset.QualifiedName;
import com.sun.xml.internal.fastinfoset.algorithm.BuiltInEncodingAlgorithmFactory;
import com.sun.xml.internal.fastinfoset.sax.AttributesHolder;
import com.sun.xml.internal.fastinfoset.util.CharArray;
import com.sun.xml.internal.fastinfoset.util.CharArrayString;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.NoSuchElementException;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithm;
import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmException;
import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmIndexes;
import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetException;
import com.sun.xml.internal.fastinfoset.CommonResourceBundle;
import com.sun.xml.internal.fastinfoset.org.apache.xerces.util.XMLChar;
import com.sun.xml.internal.fastinfoset.util.DuplicateAttributeVerifier;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.xml.internal.org.jvnet.fastinfoset.stax.FastInfosetStreamReader;

/**
 * The Fast Infoset StAX parser.
 * <p>
 * Instantiate this parser to parse a fast infoset document in accordance
 * with the StAX API.
 *
 * <p>
 * More than one fast infoset document may be decoded from the
 * {@link java.io.InputStream}.
 */
public class StAXDocumentParser extends Decoder
        implements XMLStreamReader, FastInfosetStreamReader, OctetBufferListener {
    private static final Logger logger = Logger.getLogger(StAXDocumentParser.class.getName());

    protected static final int INTERNAL_STATE_START_DOCUMENT = 0;
    protected static final int INTERNAL_STATE_START_ELEMENT_TERMINATE = 1;
    protected static final int INTERNAL_STATE_SINGLE_TERMINATE_ELEMENT_WITH_NAMESPACES = 2;
    protected static final int INTERNAL_STATE_DOUBLE_TERMINATE_ELEMENT = 3;
    protected static final int INTERNAL_STATE_END_DOCUMENT = 4;
    protected static final int INTERNAL_STATE_VOID = -1;

    protected int _internalState;

    /**
     * Current event
     */
    protected int _eventType;

    /**
     * Stack of qualified names and namespaces
     */
    protected QualifiedName[] _qNameStack = new QualifiedName[32];
    protected int[] _namespaceAIIsStartStack = new int[32];
    protected int[] _namespaceAIIsEndStack = new int[32];
    protected int _stackCount = -1;

    protected String[] _namespaceAIIsPrefix = new String[32];
    protected String[] _namespaceAIIsNamespaceName = new String[32];
    protected int[] _namespaceAIIsPrefixIndex = new int[32];
    protected int _namespaceAIIsIndex;

    /**
     * Namespaces associated with START_ELEMENT or END_ELEMENT
     */
    protected int _currentNamespaceAIIsStart;
    protected int _currentNamespaceAIIsEnd;

    /**
     * Qualified name associated with START_ELEMENT or END_ELEMENT.
     */
    protected QualifiedName _qualifiedName;

    /**
     * List of attributes
     */
    protected AttributesHolder _attributes = new AttributesHolder();

    protected boolean _clearAttributes = false;

    /**
     * Characters associated with event.
     */
    protected char[] _characters;
    protected int _charactersOffset;

    protected String _algorithmURI;
    protected int _algorithmId;
    protected boolean _isAlgorithmDataCloned;
    protected byte[] _algorithmData;
    protected int _algorithmDataOffset;
    protected int _algorithmDataLength;

    /**
     * State for processing instruction
     */
    protected String _piTarget;
    protected String _piData;

    protected NamespaceContextImpl _nsContext = new NamespaceContextImpl();

    protected String _characterEncodingScheme;

    protected StAXManager _manager;

    public StAXDocumentParser() {
        reset();
        _manager = new StAXManager(StAXManager.CONTEXT_READER);
    }

    public StAXDocumentParser(InputStream s) {
        this();
        setInputStream(s);
        _manager = new StAXManager(StAXManager.CONTEXT_READER);
    }

    public StAXDocumentParser(InputStream s, StAXManager manager) {
        this(s);
        _manager = manager;
    }

    @Override
    public void setInputStream(InputStream s) {
        super.setInputStream(s);
        reset();
    }

    @Override
    public void reset() {
        super.reset();
        if (_internalState != INTERNAL_STATE_START_DOCUMENT &&
                _internalState != INTERNAL_STATE_END_DOCUMENT) {

            for (int i = _namespaceAIIsIndex - 1; i >= 0; i--) {
                _prefixTable.popScopeWithPrefixEntry(_namespaceAIIsPrefixIndex[i]);
            }

            _stackCount = -1;

            _namespaceAIIsIndex = 0;
            _characters = null;
            _algorithmData = null;
        }

        _characterEncodingScheme = "UTF-8";
        _eventType = START_DOCUMENT;
        _internalState = INTERNAL_STATE_START_DOCUMENT;
    }

    protected void resetOnError() {
        super.reset();

        if (_v != null) {
            _prefixTable.clearCompletely();
        }
        _duplicateAttributeVerifier.clear();

        _stackCount = -1;

        _namespaceAIIsIndex = 0;
        _characters = null;
        _algorithmData = null;

        _eventType = START_DOCUMENT;
        _internalState = INTERNAL_STATE_START_DOCUMENT;
    }

    // -- XMLStreamReader Interface -------------------------------------------

    public Object getProperty(java.lang.String name)
    throws java.lang.IllegalArgumentException {
        if (_manager != null) {
            return _manager.getProperty(name);
        }
        return null;
    }

    public int next() throws XMLStreamException {
        try {
            if (_internalState != INTERNAL_STATE_VOID) {
                switch (_internalState) {
                    case INTERNAL_STATE_START_DOCUMENT:
                        decodeHeader();
                        processDII();

                        _internalState = INTERNAL_STATE_VOID;
                        break;
                    case INTERNAL_STATE_START_ELEMENT_TERMINATE:
                        if (_currentNamespaceAIIsEnd > 0) {
                            for (int i = _currentNamespaceAIIsEnd - 1; i >= _currentNamespaceAIIsStart; i--) {
                                _prefixTable.popScopeWithPrefixEntry(_namespaceAIIsPrefixIndex[i]);
                            }
                            _namespaceAIIsIndex = _currentNamespaceAIIsStart;
                        }

                        // Pop information off the stack
                        popStack();

                        _internalState = INTERNAL_STATE_VOID;
                        return _eventType = END_ELEMENT;
                    case INTERNAL_STATE_SINGLE_TERMINATE_ELEMENT_WITH_NAMESPACES:
                        // Undeclare namespaces
                        for (int i = _currentNamespaceAIIsEnd - 1; i >= _currentNamespaceAIIsStart; i--) {
                            _prefixTable.popScopeWithPrefixEntry(_namespaceAIIsPrefixIndex[i]);
                        }
                        _namespaceAIIsIndex = _currentNamespaceAIIsStart;
                        _internalState = INTERNAL_STATE_VOID;
                        break;
                    case INTERNAL_STATE_DOUBLE_TERMINATE_ELEMENT:
                        // Undeclare namespaces
                        if (_currentNamespaceAIIsEnd > 0) {
                            for (int i = _currentNamespaceAIIsEnd - 1; i >= _currentNamespaceAIIsStart; i--) {
                                _prefixTable.popScopeWithPrefixEntry(_namespaceAIIsPrefixIndex[i]);
                            }
                            _namespaceAIIsIndex = _currentNamespaceAIIsStart;
                        }

                        if (_stackCount == -1) {
                            _internalState = INTERNAL_STATE_END_DOCUMENT;
                            return _eventType = END_DOCUMENT;
                        }

                        // Pop information off the stack
                        popStack();

                        _internalState = (_currentNamespaceAIIsEnd > 0) ?
                            INTERNAL_STATE_SINGLE_TERMINATE_ELEMENT_WITH_NAMESPACES :
                            INTERNAL_STATE_VOID;
                        return _eventType = END_ELEMENT;
                    case INTERNAL_STATE_END_DOCUMENT:
                        throw new NoSuchElementException(CommonResourceBundle.getInstance().getString("message.noMoreEvents"));
                }
            }

            // Reset internal state
            _characters = null;
            _algorithmData = null;
            _currentNamespaceAIIsEnd = 0;

            // Process information item
            final int b = read();
            switch(DecoderStateTables.EII(b)) {
                case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
                    processEII(_elementNameTable._array[b], false);
                    return _eventType;
                case DecoderStateTables.EII_AIIS_INDEX_SMALL:
                    processEII(_elementNameTable._array[b & EncodingConstants.INTEGER_3RD_BIT_SMALL_MASK], true);
                    return _eventType;
                case DecoderStateTables.EII_INDEX_MEDIUM:
                    processEII(processEIIIndexMedium(b), (b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
                    return _eventType;
                case DecoderStateTables.EII_INDEX_LARGE:
                    processEII(processEIIIndexLarge(b), (b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
                    return _eventType;
                case DecoderStateTables.EII_LITERAL:
                {
                    final QualifiedName qn = processLiteralQualifiedName(
                            b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
                            _elementNameTable.getNext());
                    _elementNameTable.add(qn);
                    processEII(qn, (b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
                    return _eventType;
                }
                case DecoderStateTables.EII_NAMESPACES:
                    processEIIWithNamespaces((b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
                    return _eventType;
                case DecoderStateTables.CII_UTF8_SMALL_LENGTH:
                    _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK)
                    + 1;
                    processUtf8CharacterString(b);
                    return _eventType = CHARACTERS;
                case DecoderStateTables.CII_UTF8_MEDIUM_LENGTH:
                    _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
                    processUtf8CharacterString(b);
                    return _eventType = CHARACTERS;
                case DecoderStateTables.CII_UTF8_LARGE_LENGTH:
                    _octetBufferLength = ((read() << 24) |
                            (read() << 16) |
                            (read() << 8) |
                            read())
                            + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
                    processUtf8CharacterString(b);
                    return _eventType = CHARACTERS;
                case DecoderStateTables.CII_UTF16_SMALL_LENGTH:
                    _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK)
                    + 1;
                    processUtf16CharacterString(b);
                    return _eventType = CHARACTERS;
                case DecoderStateTables.CII_UTF16_MEDIUM_LENGTH:
                    _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
                    processUtf16CharacterString(b);
                    return _eventType = CHARACTERS;
                case DecoderStateTables.CII_UTF16_LARGE_LENGTH:
                    _octetBufferLength = ((read() << 24) |
                            (read() << 16) |
                            (read() << 8) |
                            read())
                            + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
                    processUtf16CharacterString(b);
                    return _eventType = CHARACTERS;
                case DecoderStateTables.CII_RA:
                {
                    final boolean addToTable = (b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0;

                    _identifier = (b & 0x02) << 6;
                    final int b2 = read();
                    _identifier |= (b2 & 0xFC) >> 2;

                    decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(b2);

                    decodeRestrictedAlphabetAsCharBuffer();

                    if (addToTable) {
                        _charactersOffset = _characterContentChunkTable.add(_charBuffer, _charBufferLength);
                        _characters = _characterContentChunkTable._array;
                    } else {
                        _characters = _charBuffer;
                        _charactersOffset = 0;
                    }
                    return _eventType = CHARACTERS;
                }
                case DecoderStateTables.CII_EA:
                {
                    final boolean addToTable = (b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0;
                    // Decode encoding algorithm integer
                    _algorithmId = (b & 0x02) << 6;
                    final int b2 = read();
                    _algorithmId |= (b2 & 0xFC) >> 2;

                    decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(b2);
                    processCIIEncodingAlgorithm(addToTable);

                    if (_algorithmId == EncodingAlgorithmIndexes.CDATA) {
                        return _eventType = CDATA;
                    }

                    return _eventType = CHARACTERS;
                }
                case DecoderStateTables.CII_INDEX_SMALL:
                {
                    final int index = b & EncodingConstants.INTEGER_4TH_BIT_SMALL_MASK;
                    _characterContentChunkTable._cachedIndex = index;

                    _characters = _characterContentChunkTable._array;
                    _charactersOffset = _characterContentChunkTable._offset[index];
                    _charBufferLength = _characterContentChunkTable._length[index];
                    return _eventType = CHARACTERS;
                }
                case DecoderStateTables.CII_INDEX_MEDIUM:
                {
                    final int index = (((b & EncodingConstants.INTEGER_4TH_BIT_MEDIUM_MASK) << 8) | read())
                    + EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT;
                    _characterContentChunkTable._cachedIndex = index;

                    _characters = _characterContentChunkTable._array;
                    _charactersOffset = _characterContentChunkTable._offset[index];
                    _charBufferLength = _characterContentChunkTable._length[index];
                    return _eventType = CHARACTERS;
                }
                case DecoderStateTables.CII_INDEX_LARGE:
                {
                    final int index = (((b & EncodingConstants.INTEGER_4TH_BIT_LARGE_MASK) << 16) |
                            (read() << 8) |
                            read())
                            + EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT;
                    _characterContentChunkTable._cachedIndex = index;

                    _characters = _characterContentChunkTable._array;
                    _charactersOffset = _characterContentChunkTable._offset[index];
                    _charBufferLength = _characterContentChunkTable._length[index];
                    return _eventType = CHARACTERS;
                }
                case DecoderStateTables.CII_INDEX_LARGE_LARGE:
                {
                    final int index = ((read() << 16) |
                            (read() << 8) |
                            read())
                            + EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT;
                    _characterContentChunkTable._cachedIndex = index;

                    _characters = _characterContentChunkTable._array;
                    _charactersOffset = _characterContentChunkTable._offset[index];
                    _charBufferLength = _characterContentChunkTable._length[index];
                    return _eventType = CHARACTERS;
                }
                case DecoderStateTables.COMMENT_II:
                    processCommentII();
                    return _eventType;
                case DecoderStateTables.PROCESSING_INSTRUCTION_II:
                    processProcessingII();
                    return _eventType;
                case DecoderStateTables.UNEXPANDED_ENTITY_REFERENCE_II:
                {
                    processUnexpandedEntityReference(b);
                    // Skip the reference
                    return next();
                }
                case DecoderStateTables.TERMINATOR_DOUBLE:
                    if (_stackCount != -1) {
                        // Pop information off the stack
                        popStack();

                        _internalState = INTERNAL_STATE_DOUBLE_TERMINATE_ELEMENT;
                        return _eventType = END_ELEMENT;
                    }

                    _internalState = INTERNAL_STATE_END_DOCUMENT;
                    return _eventType = END_DOCUMENT;
                case DecoderStateTables.TERMINATOR_SINGLE:
                    if (_stackCount != -1) {
                        // Pop information off the stack
                        popStack();

                        if (_currentNamespaceAIIsEnd > 0) {
                            _internalState = INTERNAL_STATE_SINGLE_TERMINATE_ELEMENT_WITH_NAMESPACES;
                        }
                        return _eventType = END_ELEMENT;
                    }

                    _internalState = INTERNAL_STATE_END_DOCUMENT;
                    return _eventType = END_DOCUMENT;
                default:
                    throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingEII"));
            }
        } catch (IOException e) {
            resetOnError();
            logger.log(Level.FINE, "next() exception", e);
            throw new XMLStreamException(e);
        } catch (FastInfosetException e) {
            resetOnError();
            logger.log(Level.FINE, "next() exception", e);
            throw new XMLStreamException(e);
        } catch (RuntimeException e) {
            resetOnError();
            logger.log(Level.FINE, "next() exception", e);
            throw e;
        }
    }

    private final void processUtf8CharacterString(final int b) throws IOException {
        if ((b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
            _characterContentChunkTable.ensureSize(_octetBufferLength);
            _characters = _characterContentChunkTable._array;
            _charactersOffset = _characterContentChunkTable._arrayIndex;
            decodeUtf8StringAsCharBuffer(_characterContentChunkTable._array, _charactersOffset);
            _characterContentChunkTable.add(_charBufferLength);
        } else {
            decodeUtf8StringAsCharBuffer();
            _characters = _charBuffer;
            _charactersOffset = 0;
        }
    }

    private final void processUtf16CharacterString(final int b) throws IOException {
        decodeUtf16StringAsCharBuffer();
        if ((b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
            _charactersOffset = _characterContentChunkTable.add(_charBuffer, _charBufferLength);
            _characters = _characterContentChunkTable._array;
        } else {
            _characters = _charBuffer;
            _charactersOffset = 0;
        }
    }

    private void popStack() {
        // Pop information off the stack
        _qualifiedName = _qNameStack[_stackCount];
        _currentNamespaceAIIsStart = _namespaceAIIsStartStack[_stackCount];
        _currentNamespaceAIIsEnd = _namespaceAIIsEndStack[_stackCount];
        _qNameStack[_stackCount--] = 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.
     * @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.
     */
    public final void require(int type, String namespaceURI, String localName)
    throws XMLStreamException {
        if( type != _eventType)
            throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.eventTypeNotMatch", new Object[]{getEventTypeString(type)}));
        if( namespaceURI != null && !namespaceURI.equals(getNamespaceURI()) )
            throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.namespaceURINotMatch", new Object[]{namespaceURI}));
        if(localName != null && !localName.equals(getLocalName()))
            throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.localNameNotMatch", new Object[]{localName}));
    }

    /** Reads the content of a text-only element. Precondition:
     * the current event is START_ELEMENT. Postcondition:
     * The current event is the corresponding END_ELEMENT.
     * @throws XMLStreamException if the current event is not a START_ELEMENT or if
     * a non text element is encountered
     */
    public final String getElementText() throws XMLStreamException {

        if(getEventType() != START_ELEMENT) {
            throw new XMLStreamException(
                    CommonResourceBundle.getInstance().getString("message.mustBeOnSTARTELEMENT"), getLocation());
        }
        //current is StartElement, move to the next
        next();
        return getElementText(true);
    }
    /**
     * @param startElementRead flag if start element has already been read
     */
    public final String getElementText(boolean startElementRead) throws XMLStreamException {
        if (!startElementRead) {
            throw new XMLStreamException(
                    CommonResourceBundle.getInstance().getString("message.mustBeOnSTARTELEMENT"), getLocation());
        }
        int eventType = getEventType();
        StringBuilder content = new StringBuilder();
        while(eventType != END_ELEMENT ) {
            if(eventType == CHARACTERS
                    || eventType == CDATA
                    || eventType == SPACE
                    || eventType == ENTITY_REFERENCE) {
                content.append(getText());
            } else if(eventType == PROCESSING_INSTRUCTION
                    || eventType == COMMENT) {
                // skipping
            } else if(eventType == END_DOCUMENT) {
                throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.unexpectedEOF"));
            } else if(eventType == START_ELEMENT) {
                throw new XMLStreamException(
                        CommonResourceBundle.getInstance().getString("message.getElementTextExpectTextOnly"), getLocation());
            } else {
                throw new XMLStreamException(
                        CommonResourceBundle.getInstance().getString("message.unexpectedEventType")+ getEventTypeString(eventType), getLocation());
            }
            eventType = next();
        }
        return content.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.
     * This method should
     * be used when processing element-only content because
     * the parser is not able to recognize ignorable whitespace if
     * then DTD is missing or not interpreted.
     * @return the event type of the element read
     * @throws XMLStreamException if the current event is not white space
     */
    public final int nextTag() throws XMLStreamException {
        next();
        return nextTag(true);
    }
    /** if the current tag has already read, such as in the case EventReader's
     * peek() has been called, the current cursor should not move before the loop
     */
    public final int nextTag(boolean currentTagRead) throws XMLStreamException {
        int eventType = getEventType();
        if (!currentTagRead) {
            eventType = next();
        }
        while((eventType == CHARACTERS && isWhiteSpace()) // skip whitespace
        || (eventType == CDATA && isWhiteSpace())
        || eventType == SPACE
                || eventType == PROCESSING_INSTRUCTION
                || eventType == COMMENT) {
            eventType = next();
        }
        if (eventType != START_ELEMENT && eventType != END_ELEMENT) {
            throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.expectedStartOrEnd"), getLocation());
        }
        return eventType;
    }

    public final boolean hasNext() throws XMLStreamException {
        return (_eventType != END_DOCUMENT);
    }

    public void close() throws XMLStreamException {
        try {
            super.closeIfRequired();
        } catch (IOException ex) {
        }
    }

    public final String getNamespaceURI(String prefix) {
        String namespace = getNamespaceDecl(prefix);
        if (namespace == null) {
            if (prefix == null) {
                throw new IllegalArgumentException(CommonResourceBundle.getInstance().getString("message.nullPrefix"));
            }
            return null;  // unbound
        }
        return namespace;
    }

    public final boolean isStartElement() {
        return (_eventType == START_ELEMENT);
    }

    public final boolean isEndElement() {
        return (_eventType == END_ELEMENT);
    }

    public final boolean isCharacters() {
        return (_eventType == CHARACTERS);
    }

    /**
     *  Returns true if the cursor points to a character data event that consists of all whitespace
     *  Application calling this method needs to cache the value and avoid calling this method again
     *  for the same event.
     * @return true if the cursor points to all whitespace, false otherwise
     */
    public final boolean isWhiteSpace() {
        if(isCharacters() || (_eventType == CDATA)){
            char [] ch = this.getTextCharacters();
            int start = this.getTextStart();
            int length = this.getTextLength();
            for (int i = start; i < start + length; i++){
                if(!XMLChar.isSpace(ch[i])){
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    public final String getAttributeValue(String namespaceURI, String localName) {
        if (_eventType != START_ELEMENT) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
        }

        if (localName == null)
            throw new IllegalArgumentException();

        // Search for the attributes in _attributes
        if (namespaceURI != null) {
            for (int i = 0; i < _attributes.getLength(); i++) {
                if (_attributes.getLocalName(i).equals(localName) &&
                        _attributes.getURI(i).equals(namespaceURI)) {
                    return _attributes.getValue(i);
                }
            }
        } else {
            for (int i = 0; i < _attributes.getLength(); i++) {
                if (_attributes.getLocalName(i).equals(localName)) {
                    return _attributes.getValue(i);
                }
            }
        }

        return null;
    }

    public final int getAttributeCount() {
        if (_eventType != START_ELEMENT) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
        }

        return _attributes.getLength();
    }

    public final javax.xml.namespace.QName getAttributeName(int index) {
        if (_eventType != START_ELEMENT) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
        }
        return _attributes.getQualifiedName(index).getQName();
    }

    public final String getAttributeNamespace(int index) {
        if (_eventType != START_ELEMENT) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
        }

        return _attributes.getURI(index);
    }

    public final String getAttributeLocalName(int index) {
        if (_eventType != START_ELEMENT) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
        }
        return _attributes.getLocalName(index);
    }

    public final String getAttributePrefix(int index) {
        if (_eventType != START_ELEMENT) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
        }
        return _attributes.getPrefix(index);
    }

    public final String getAttributeType(int index) {
        if (_eventType != START_ELEMENT) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
        }
        return _attributes.getType(index);
    }

    public final String getAttributeValue(int index) {
        if (_eventType != START_ELEMENT) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
        }
        return _attributes.getValue(index);
    }

    public final boolean isAttributeSpecified(int index) {
        return false;   // non-validating parser
    }

    public final int getNamespaceCount() {
        if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
            return (_currentNamespaceAIIsEnd > 0) ? (_currentNamespaceAIIsEnd - _currentNamespaceAIIsStart) : 0;
        } else {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetNamespaceCount"));
        }
    }

    public final String getNamespacePrefix(int index) {
        if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
            return _namespaceAIIsPrefix[_currentNamespaceAIIsStart + index];
        } else {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetNamespacePrefix"));
        }
    }

    public final String getNamespaceURI(int index) {
        if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
            return _namespaceAIIsNamespaceName[_currentNamespaceAIIsStart + index];
        } else {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetNamespacePrefix"));
        }
    }

    public final NamespaceContext getNamespaceContext() {
        return _nsContext;
    }

    public final int getEventType() {
        return _eventType;
    }

    public final String getText() {
        if (_characters == null) {
            checkTextState();
        }

        if (_characters == _characterContentChunkTable._array) {
            return _characterContentChunkTable.getString(_characterContentChunkTable._cachedIndex);
        } else {
            return new String(_characters, _charactersOffset, _charBufferLength);
        }
    }

    public final char[] getTextCharacters() {
        if (_characters == null) {
            checkTextState();
        }

        return _characters;
    }

    public final int getTextStart() {
        if (_characters == null) {
            checkTextState();
        }

        return _charactersOffset;
    }

    public final int getTextLength() {
        if (_characters == null) {
            checkTextState();
        }

        return _charBufferLength;
    }

    public final int getTextCharacters(int sourceStart, char[] target,
            int targetStart, int length) throws XMLStreamException {
        if (_characters == null) {
            checkTextState();
        }

        try {
            int bytesToCopy = Math.min(_charBufferLength, length);
            System.arraycopy(_characters, _charactersOffset + sourceStart,
                    target, targetStart, bytesToCopy);
            return bytesToCopy;
        } catch (IndexOutOfBoundsException e) {
            throw new XMLStreamException(e);
        }
    }

    protected final void checkTextState() {
        if (_algorithmData == null) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.InvalidStateForText"));
        }

        try {
            convertEncodingAlgorithmDataToCharacters();
        } catch (Exception e) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.InvalidStateForText"));
        }
    }

    public final String getEncoding() {
        return _characterEncodingScheme;
    }

    public final boolean hasText() {
        return (_characters != null);
    }

    public final Location getLocation() {
        //location should be created in next()
        //returns a nil location for now
        return EventLocation.getNilLocation();
    }

    public final QName getName() {
        if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
            return _qualifiedName.getQName();
        } else {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetName"));
        }
    }

    public final String getLocalName() {
        if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
            return _qualifiedName.localName;
        } else {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetLocalName"));
        }
    }

    public final boolean hasName() {
        return (_eventType == START_ELEMENT || _eventType == END_ELEMENT);
    }

    public final String getNamespaceURI() {
        if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
            return _qualifiedName.namespaceName;
        } else {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetNamespaceURI"));
        }
    }

    public final String getPrefix() {
        if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
            return _qualifiedName.prefix;
        } else {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetPrefix"));
        }
    }

    public final String getVersion() {
        return null;
    }

    public final boolean isStandalone() {
        return false;
    }

    public final boolean standaloneSet() {
        return false;
    }

    public final String getCharacterEncodingScheme() {
        return null;
    }

    public final String getPITarget() {
        if (_eventType != PROCESSING_INSTRUCTION) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetPITarget"));
        }

        return _piTarget;
    }

    public final String getPIData() {
        if (_eventType != PROCESSING_INSTRUCTION) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetPIData"));
        }

        return _piData;
    }




    public final String getNameString() {
        if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
            return _qualifiedName.getQNameString();
        } else {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetName"));
        }
    }

    public final String getAttributeNameString(int index) {
        if (_eventType != START_ELEMENT) {
            throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
        }
        return _attributes.getQualifiedName(index).getQNameString();
    }


    public final String getTextAlgorithmURI() {
        return _algorithmURI;
    }

    public final int getTextAlgorithmIndex() {
        return _algorithmId;
    }

    public final boolean hasTextAlgorithmBytes() {
        return _algorithmData != null;
    }


    /**
     * Returns the byte[], which represents text algorithms.
     * @deprecated was deprecated due to security reasons. Now the method return cloned byte[].
     *
     * @return
     */
    public final byte[] getTextAlgorithmBytes() {
        // Do not return the actual _algorithmData due to security reasons
//        return _algorithmData;
        if (_algorithmData == null) {
            return null;
        }

        final byte[] algorithmData = new byte[_algorithmData.length];
        System.arraycopy(_algorithmData, 0, algorithmData, 0, _algorithmData.length);
        return algorithmData;
    }

    public final byte[] getTextAlgorithmBytesClone() {
        if (_algorithmData == null) {
            return null;
        }

        byte[] algorithmData = new byte[_algorithmDataLength];
        System.arraycopy(_algorithmData, _algorithmDataOffset, algorithmData, 0, _algorithmDataLength);
        return algorithmData;
    }

    public final int getTextAlgorithmStart() {
        return _algorithmDataOffset;
    }

    public final int getTextAlgorithmLength() {
        return _algorithmDataLength;
    }

    public final int getTextAlgorithmBytes(int sourceStart, byte[] target,
            int targetStart, int length) throws XMLStreamException {
        try {
            System.arraycopy(_algorithmData, sourceStart, target,
                    targetStart, length);
            return length;
        } catch (IndexOutOfBoundsException e) {
            throw new XMLStreamException(e);
        }
    }

    // FastInfosetStreamReader impl

    public final int peekNext() throws XMLStreamException {
        try {
            switch(DecoderStateTables.EII(peek(this))) {
                case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
                case DecoderStateTables.EII_AIIS_INDEX_SMALL:
                case DecoderStateTables.EII_INDEX_MEDIUM:
                case DecoderStateTables.EII_INDEX_LARGE:
                case DecoderStateTables.EII_LITERAL:
                case DecoderStateTables.EII_NAMESPACES:
                    return START_ELEMENT;
                case DecoderStateTables.CII_UTF8_SMALL_LENGTH:
                case DecoderStateTables.CII_UTF8_MEDIUM_LENGTH:
                case DecoderStateTables.CII_UTF8_LARGE_LENGTH:
                case DecoderStateTables.CII_UTF16_SMALL_LENGTH:
                case DecoderStateTables.CII_UTF16_MEDIUM_LENGTH:
                case DecoderStateTables.CII_UTF16_LARGE_LENGTH:
                case DecoderStateTables.CII_RA:
                case DecoderStateTables.CII_EA:
                case DecoderStateTables.CII_INDEX_SMALL:
                case DecoderStateTables.CII_INDEX_MEDIUM:
                case DecoderStateTables.CII_INDEX_LARGE:
                case DecoderStateTables.CII_INDEX_LARGE_LARGE:
                    return CHARACTERS;
                case DecoderStateTables.COMMENT_II:
                    return COMMENT;
                case DecoderStateTables.PROCESSING_INSTRUCTION_II:
                    return PROCESSING_INSTRUCTION;
                case DecoderStateTables.UNEXPANDED_ENTITY_REFERENCE_II:
                    return ENTITY_REFERENCE;
                case DecoderStateTables.TERMINATOR_DOUBLE:
                case DecoderStateTables.TERMINATOR_SINGLE:
                    return (_stackCount != -1) ? END_ELEMENT : END_DOCUMENT;
                default:
                    throw new FastInfosetException(
                            CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingEII"));
            }
        } catch (IOException e) {
            throw new XMLStreamException(e);
        } catch (FastInfosetException e) {
            throw new XMLStreamException(e);
        }
    }

    public void onBeforeOctetBufferOverwrite() {
        if (_algorithmData != null) {
            _algorithmData = getTextAlgorithmBytesClone();
            _algorithmDataOffset = 0;
            _isAlgorithmDataCloned = true;
        }
    }

    // Faster access methods without checks

    public final int accessNamespaceCount() {
        return (_currentNamespaceAIIsEnd > 0) ? (_currentNamespaceAIIsEnd - _currentNamespaceAIIsStart) : 0;
    }

    public final String accessLocalName() {
        return _qualifiedName.localName;
    }

    public final String accessNamespaceURI() {
        return _qualifiedName.namespaceName;
    }

    public final String accessPrefix() {
        return _qualifiedName.prefix;
    }

    public final char[] accessTextCharacters() {
        if (_characters == null) return null;

        // we return a cloned version of _characters
        final char[] clonedCharacters = new char[_characters.length];
        System.arraycopy(_characters, 0, clonedCharacters, 0, _characters.length);
        return clonedCharacters;
    }

    public final int accessTextStart() {
        return _charactersOffset;
    }

    public final int accessTextLength() {
        return _charBufferLength;
    }

    //

    protected final void processDII() throws FastInfosetException, IOException {
        final int b = read();
        if (b > 0) {
            processDIIOptionalProperties(b);
        }
    }

    protected final void processDIIOptionalProperties(int b) throws FastInfosetException, IOException {
        // Optimize for the most common case
        if (b == EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) {
            decodeInitialVocabulary();
            return;
        }

        if ((b & EncodingConstants.DOCUMENT_ADDITIONAL_DATA_FLAG) > 0) {
            decodeAdditionalData();
            /*
             * TODO
             * how to report the additional data?
             */
        }

        if ((b & EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) > 0) {
            decodeInitialVocabulary();
        }

        if ((b & EncodingConstants.DOCUMENT_NOTATIONS_FLAG) > 0) {
            decodeNotations();
            /*
                try {
                    _dtdHandler.notationDecl(name, public_identifier, system_identifier);
                } catch (SAXException e) {
                    throw new IOException("NotationsDeclarationII");
                }
             */
        }

        if ((b & EncodingConstants.DOCUMENT_UNPARSED_ENTITIES_FLAG) > 0) {
            decodeUnparsedEntities();
            /*
                try {
                    _dtdHandler.unparsedEntityDecl(name, public_identifier, system_identifier, notation_name);
                } catch (SAXException e) {
                    throw new IOException("UnparsedEntitiesII");
                }
             */
        }

        if ((b & EncodingConstants.DOCUMENT_CHARACTER_ENCODING_SCHEME) > 0) {
            _characterEncodingScheme = decodeCharacterEncodingScheme();
        }

        if ((b & EncodingConstants.DOCUMENT_STANDALONE_FLAG) > 0) {
            boolean standalone = (read() > 0) ? true : false ;
            /*
             * TODO
             * how to report the standalone flag?
             */
        }

        if ((b & EncodingConstants.DOCUMENT_VERSION_FLAG) > 0) {
            decodeVersion();
            /*
             * TODO
             * how to report the standalone flag?
             */
        }
    }


    protected final void resizeNamespaceAIIs() {
        final String[] namespaceAIIsPrefix = new String[_namespaceAIIsIndex * 2];
        System.arraycopy(_namespaceAIIsPrefix, 0, namespaceAIIsPrefix, 0, _namespaceAIIsIndex);
        _namespaceAIIsPrefix = namespaceAIIsPrefix;

        final String[] namespaceAIIsNamespaceName = new String[_namespaceAIIsIndex * 2];
        System.arraycopy(_namespaceAIIsNamespaceName, 0, namespaceAIIsNamespaceName, 0, _namespaceAIIsIndex);
        _namespaceAIIsNamespaceName = namespaceAIIsNamespaceName;

        final int[] namespaceAIIsPrefixIndex = new int[_namespaceAIIsIndex * 2];
        System.arraycopy(_namespaceAIIsPrefixIndex, 0, namespaceAIIsPrefixIndex, 0, _namespaceAIIsIndex);
        _namespaceAIIsPrefixIndex = namespaceAIIsPrefixIndex;
    }

    protected final void processEIIWithNamespaces(boolean hasAttributes) throws FastInfosetException, IOException {
        if (++_prefixTable._declarationId == Integer.MAX_VALUE) {
            _prefixTable.clearDeclarationIds();
        }

        _currentNamespaceAIIsStart = _namespaceAIIsIndex;
        String prefix = "", namespaceName = "";
        int b = read();
        while ((b & EncodingConstants.NAMESPACE_ATTRIBUTE_MASK) == EncodingConstants.NAMESPACE_ATTRIBUTE) {
            if (_namespaceAIIsIndex == _namespaceAIIsPrefix.length) {
                resizeNamespaceAIIs();
            }

            switch (b & EncodingConstants.NAMESPACE_ATTRIBUTE_PREFIX_NAME_MASK) {
                // no prefix, no namespace
                // Undeclaration of default namespace
                case 0:
                    prefix = namespaceName =
                            _namespaceAIIsPrefix[_namespaceAIIsIndex] =
                            _namespaceAIIsNamespaceName[_namespaceAIIsIndex] = "";

                    _namespaceNameIndex = _prefixIndex = _namespaceAIIsPrefixIndex[_namespaceAIIsIndex++] = -1;
                    break;
                    // no prefix, namespace
                    // Declaration of default namespace
                case 1:
                    prefix = _namespaceAIIsPrefix[_namespaceAIIsIndex] = "";
                    namespaceName = _namespaceAIIsNamespaceName[_namespaceAIIsIndex] =
                            decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(false);

                    _prefixIndex = _namespaceAIIsPrefixIndex[_namespaceAIIsIndex++] = -1;
                    break;
                    // prefix, no namespace
                    // Undeclaration of namespace
                case 2:
                    prefix = _namespaceAIIsPrefix[_namespaceAIIsIndex] =
                            decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(false);
                    namespaceName = _namespaceAIIsNamespaceName[_namespaceAIIsIndex] = "";

                    _namespaceNameIndex = -1;
                    _namespaceAIIsPrefixIndex[_namespaceAIIsIndex++] = _prefixIndex;
                    break;
                    // prefix, namespace
                    // Declaration of prefixed namespace
                case 3:
                    prefix = _namespaceAIIsPrefix[_namespaceAIIsIndex] =
                            decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(true);
                    namespaceName = _namespaceAIIsNamespaceName[_namespaceAIIsIndex] =
                            decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(true);

                    _namespaceAIIsPrefixIndex[_namespaceAIIsIndex++] = _prefixIndex;
                    break;
            }

            // Push namespace declarations onto the stack
            _prefixTable.pushScopeWithPrefixEntry(prefix, namespaceName, _prefixIndex, _namespaceNameIndex);

            b = read();
        }
        if (b != EncodingConstants.TERMINATOR) {
            throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.EIInamespaceNameNotTerminatedCorrectly"));
        }
        _currentNamespaceAIIsEnd = _namespaceAIIsIndex;

        b = read();
        switch(DecoderStateTables.EII(b)) {
            case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
                processEII(_elementNameTable._array[b], hasAttributes);
                break;
            case DecoderStateTables.EII_INDEX_MEDIUM:
                processEII(processEIIIndexMedium(b), hasAttributes);
                break;
            case DecoderStateTables.EII_INDEX_LARGE:
                processEII(processEIIIndexLarge(b), hasAttributes);
                break;
            case DecoderStateTables.EII_LITERAL:
            {
                final QualifiedName qn = processLiteralQualifiedName(
                        b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
                        _elementNameTable.getNext());
                _elementNameTable.add(qn);
                processEII(qn, hasAttributes);
                break;
            }
            default:
                throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingEIIAfterAIIs"));
        }
    }

    protected final void processEII(QualifiedName name, boolean hasAttributes) throws FastInfosetException, IOException {
        if (_prefixTable._currentInScope[name.prefixIndex] != name.namespaceNameIndex) {
            throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.qnameOfEIINotInScope"));
        }

        _eventType = START_ELEMENT;
        _qualifiedName = name;

        if (_clearAttributes) {
            _attributes.clear();
            _clearAttributes = false;
        }

        if (hasAttributes) {
            processAIIs();
        }

        // Push element holder onto the stack
        _stackCount++;
        if (_stackCount == _qNameStack.length) {
            QualifiedName[] qNameStack = new QualifiedName[_qNameStack.length * 2];
            System.arraycopy(_qNameStack, 0, qNameStack, 0, _qNameStack.length);
            _qNameStack = qNameStack;

            int[] namespaceAIIsStartStack = new int[_namespaceAIIsStartStack.length * 2];
            System.arraycopy(_namespaceAIIsStartStack, 0, namespaceAIIsStartStack, 0, _namespaceAIIsStartStack.length);
            _namespaceAIIsStartStack = namespaceAIIsStartStack;

            int[] namespaceAIIsEndStack = new int[_namespaceAIIsEndStack.length * 2];
            System.arraycopy(_namespaceAIIsEndStack, 0, namespaceAIIsEndStack, 0, _namespaceAIIsEndStack.length);
            _namespaceAIIsEndStack = namespaceAIIsEndStack;
        }
        _qNameStack[_stackCount] = _qualifiedName;
        _namespaceAIIsStartStack[_stackCount] = _currentNamespaceAIIsStart;
        _namespaceAIIsEndStack[_stackCount] = _currentNamespaceAIIsEnd;
    }

    protected final void processAIIs() throws FastInfosetException, IOException {
        QualifiedName name;
        int b;
        String value;

        if (++_duplicateAttributeVerifier._currentIteration == Integer.MAX_VALUE) {
            _duplicateAttributeVerifier.clear();
        }

        _clearAttributes = true;
        boolean terminate = false;
        do {
            // AII qualified name
            b = read();
            switch (DecoderStateTables.AII(b)) {
                case DecoderStateTables.AII_INDEX_SMALL:
                    name = _attributeNameTable._array[b];
                    break;
                case DecoderStateTables.AII_INDEX_MEDIUM:
                {
                    final int i = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
                    + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
                    name = _attributeNameTable._array[i];
                    break;
                }
                case DecoderStateTables.AII_INDEX_LARGE:
                {
                    final int i = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
                    + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
                    name = _attributeNameTable._array[i];
                    break;
                }
                case DecoderStateTables.AII_LITERAL:
                    name = processLiteralQualifiedName(
                            b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
                            _attributeNameTable.getNext());
                    name.createAttributeValues(DuplicateAttributeVerifier.MAP_SIZE);
                    _attributeNameTable.add(name);
                    break;
                case DecoderStateTables.AII_TERMINATOR_DOUBLE:
                    _internalState = INTERNAL_STATE_START_ELEMENT_TERMINATE;
                case DecoderStateTables.AII_TERMINATOR_SINGLE:
                    terminate = true;
                    // AIIs have finished break out of loop
                    continue;
                default:
                    throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingAIIs"));
            }

            // [normalized value] of AII

            if (name.prefixIndex > 0 && _prefixTable._currentInScope[name.prefixIndex] != name.namespaceNameIndex) {
                throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.AIIqNameNotInScope"));
            }

            _duplicateAttributeVerifier.checkForDuplicateAttribute(name.attributeHash, name.attributeId);

            b = read();
            switch(DecoderStateTables.NISTRING(b)) {
                case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH:
                    _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
                    value = decodeUtf8StringAsString();
                    if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
                        _attributeValueTable.add(value);
                    }

                    _attributes.addAttribute(name, value);
                    break;
                case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH:
                    _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
                    value = decodeUtf8StringAsString();
                    if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
                        _attributeValueTable.add(value);
                    }

                    _attributes.addAttribute(name, value);
                    break;
                case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH:
                    _octetBufferLength = ((read() << 24) |
                            (read() << 16) |
                            (read() << 8) |
                            read())
                            + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
                    value = decodeUtf8StringAsString();
                    if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
                        _attributeValueTable.add(value);
                    }

                    _attributes.addAttribute(name, value);
                    break;
                case DecoderStateTables.NISTRING_UTF16_SMALL_LENGTH:
                    _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
                    value = decodeUtf16StringAsString();
                    if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
                        _attributeValueTable.add(value);
                    }

                    _attributes.addAttribute(name, value);
                    break;
                case DecoderStateTables.NISTRING_UTF16_MEDIUM_LENGTH:
                    _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
                    value = decodeUtf16StringAsString();
                    if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
                        _attributeValueTable.add(value);
                    }

                    _attributes.addAttribute(name, value);
                    break;
                case DecoderStateTables.NISTRING_UTF16_LARGE_LENGTH:
                    _octetBufferLength = ((read() << 24) |
                            (read() << 16) |
                            (read() << 8) |
                            read())
                            + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
                    value = decodeUtf16StringAsString();
                    if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
                        _attributeValueTable.add(value);
                    }

                    _attributes.addAttribute(name, value);
                    break;
                case DecoderStateTables.NISTRING_RA:
                {
                    final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
                    // Decode resitricted alphabet integer
                    _identifier = (b & 0x0F) << 4;
                    b = read();
                    _identifier |= (b & 0xF0) >> 4;

                    decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b);

                    value = decodeRestrictedAlphabetAsString();
                    if (addToTable) {
                        _attributeValueTable.add(value);
                    }

                    _attributes.addAttribute(name, value);
                    break;
                }
                case DecoderStateTables.NISTRING_EA:
                {
                    final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
                    // Decode encoding algorithm integer
                    _identifier = (b & 0x0F) << 4;
                    b = read();
                    _identifier |= (b & 0xF0) >> 4;

                    decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b);
                    processAIIEncodingAlgorithm(name, addToTable);
                    break;
                }
                case DecoderStateTables.NISTRING_INDEX_SMALL:
                    _attributes.addAttribute(name,
                            _attributeValueTable._array[b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK]);
                    break;
                case DecoderStateTables.NISTRING_INDEX_MEDIUM:
                {
                    final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
                    + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;

                    _attributes.addAttribute(name,
                            _attributeValueTable._array[index]);
                    break;
                }
                case DecoderStateTables.NISTRING_INDEX_LARGE:
                {
                    final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
                    + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;

                    _attributes.addAttribute(name,
                            _attributeValueTable._array[index]);
                    break;
                }
                case DecoderStateTables.NISTRING_EMPTY:
                    _attributes.addAttribute(name, "");
                    break;
                default:
                    throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingAIIValue"));
            }

        } while (!terminate);

        // Reset duplication attribute verfifier
        _duplicateAttributeVerifier._poolCurrent = _duplicateAttributeVerifier._poolHead;
    }

    protected final QualifiedName processEIIIndexMedium(int b) throws FastInfosetException, IOException {
        final int i = (((b & EncodingConstants.INTEGER_3RD_BIT_MEDIUM_MASK) << 8) | read())
        + EncodingConstants.INTEGER_3RD_BIT_SMALL_LIMIT;
        return _elementNameTable._array[i];
    }

    protected final QualifiedName processEIIIndexLarge(int b) throws FastInfosetException, IOException {
        int i;
        if ((b & EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_FLAG) == 0x20) {
            // EII large index
            i = (((b & EncodingConstants.INTEGER_3RD_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
            + EncodingConstants.INTEGER_3RD_BIT_MEDIUM_LIMIT;
        } else {
            // EII large large index
            i = (((read() & EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_MASK) << 16) | (read() << 8) | read())
            + EncodingConstants.INTEGER_3RD_BIT_LARGE_LIMIT;
        }
        return _elementNameTable._array[i];
    }

    protected final QualifiedName processLiteralQualifiedName(int state, QualifiedName q)
    throws FastInfosetException, IOException {
        if (q == null) q = new QualifiedName();

        switch (state) {
            // no prefix, no namespace
            case 0:
                return q.set(
                        "",
                        "",
                        decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
                        "",
                        0,
                        -1,
                        -1,
                        _identifier);
                // no prefix, namespace
            case 1:
                return q.set(
                        "",
                        decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(false),
                        decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
                        "",
                        0,
                        -1,
                        _namespaceNameIndex,
                        _identifier);
                // prefix, no namespace
            case 2:
                throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.qNameMissingNamespaceName"));
                // prefix, namespace
            case 3:
                return q.set(
                        decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(true),
                        decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(true),
                        decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
                        "",
                        0,
                        _prefixIndex,
                        _namespaceNameIndex,
                        _identifier);
            default:
                throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingEII"));
        }
    }

    protected final void processCommentII() throws FastInfosetException, IOException {
        _eventType = COMMENT;

        switch(decodeNonIdentifyingStringOnFirstBit()) {
            case NISTRING_STRING:
                if (_addToTable) {
                    _v.otherString.add(new CharArray(_charBuffer, 0, _charBufferLength, true));
                }

                _characters = _charBuffer;
                _charactersOffset = 0;
                break;
            case NISTRING_ENCODING_ALGORITHM:
                throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.commentIIAlgorithmNotSupported"));
            case NISTRING_INDEX:
                final CharArray ca = _v.otherString.get(_integer);

                _characters = ca.ch;
                _charactersOffset = ca.start;
                _charBufferLength = ca.length;
                break;
            case NISTRING_EMPTY_STRING:
                _characters = _charBuffer;
                _charactersOffset = 0;
                _charBufferLength = 0;
                break;
        }
    }

    protected final void processProcessingII() throws FastInfosetException, IOException {
        _eventType = PROCESSING_INSTRUCTION;

        _piTarget = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);

        switch(decodeNonIdentifyingStringOnFirstBit()) {
            case NISTRING_STRING:
                _piData = new String(_charBuffer, 0, _charBufferLength);
                if (_addToTable) {
                    _v.otherString.add(new CharArrayString(_piData));
                }
                break;
            case NISTRING_ENCODING_ALGORITHM:
                throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.processingIIWithEncodingAlgorithm"));
            case NISTRING_INDEX:
                _piData = _v.otherString.get(_integer).toString();
                break;
            case NISTRING_EMPTY_STRING:
                _piData = "";
                break;
        }
    }

    protected final void processUnexpandedEntityReference(final int b) throws FastInfosetException, IOException {
        _eventType = ENTITY_REFERENCE;

        /*
         * TODO
         * How does StAX report such events?
         */
        String entity_reference_name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);

        String system_identifier = ((b & EncodingConstants.UNEXPANDED_ENTITY_SYSTEM_IDENTIFIER_FLAG) > 0)
        ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
        String public_identifier = ((b & EncodingConstants.UNEXPANDED_ENTITY_PUBLIC_IDENTIFIER_FLAG) > 0)
        ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";

        if (logger.isLoggable(Level.FINEST)) {
            logger.log(Level.FINEST, "processUnexpandedEntityReference: entity_reference_name={0} system_identifier={1}public_identifier={2}",
                    new Object[]{entity_reference_name, system_identifier, public_identifier});
        }
    }

    protected final void processCIIEncodingAlgorithm(boolean addToTable) throws FastInfosetException, IOException {
        _algorithmData = _octetBuffer;
        _algorithmDataOffset = _octetBufferStart;
        _algorithmDataLength = _octetBufferLength;
        _isAlgorithmDataCloned = false;

        if (_algorithmId >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
            _algorithmURI = _v.encodingAlgorithm.get(_algorithmId - EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START);
            if (_algorithmURI == null) {
                throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.URINotPresent", new Object[]{Integer.valueOf(_identifier)}));
            }
        } else if (_algorithmId > EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
            // Reserved built-in algorithms for future use
            // TODO should use sax property to decide if event will be
            // reported, allows for support through handler if required.
            throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved"));
        }

        if (addToTable) {
            convertEncodingAlgorithmDataToCharacters();
            _characterContentChunkTable.add(_characters, _characters.length);
        }
    }

    protected final void processAIIEncodingAlgorithm(QualifiedName name, boolean addToTable) throws FastInfosetException, IOException {
        EncodingAlgorithm ea = null;
        String URI = null;
        if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
            URI = _v.encodingAlgorithm.get(_identifier - EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START);
            if (URI == null) {
                throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.URINotPresent", new Object[]{Integer.valueOf(_identifier)}));
            } else if (_registeredEncodingAlgorithms != null) {
                ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(URI);
            }
        } else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
            if (_identifier == EncodingAlgorithmIndexes.CDATA) {
                throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.CDATAAlgorithmNotSupported"));
            }

            // Reserved built-in algorithms for future use
            // TODO should use sax property to decide if event will be
            // reported, allows for support through handler if required.
            throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved"));
        } else {
            ea = BuiltInEncodingAlgorithmFactory.getAlgorithm(_identifier);
        }

        Object algorithmData;

        if (ea != null) {
            algorithmData = ea.decodeFromBytes(_octetBuffer, _octetBufferStart,
                    _octetBufferLength);
        } else {
            final byte[] data = new byte[_octetBufferLength];
            System.arraycopy(_octetBuffer, _octetBufferStart, data, 0,
                    _octetBufferLength);
            algorithmData = data;
        }

        _attributes.addAttributeWithAlgorithmData(name, URI, _identifier,
                algorithmData);
        if (addToTable) {
            _attributeValueTable.add(_attributes.getValue(_attributes.getIndex(name.qName)));
        }
    }

    protected final void convertEncodingAlgorithmDataToCharacters() throws FastInfosetException, IOException {
        StringBuffer buffer = new StringBuffer();
        if (_algorithmId == EncodingAlgorithmIndexes.BASE64) {
            convertBase64AlorithmDataToCharacters(buffer);
        } else if (_algorithmId < EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
            Object array = BuiltInEncodingAlgorithmFactory.getAlgorithm(_algorithmId).
                    decodeFromBytes(_algorithmData, _algorithmDataOffset, _algorithmDataLength);
            BuiltInEncodingAlgorithmFactory.getAlgorithm(_algorithmId).convertToCharacters(array,  buffer);
        } else if (_algorithmId == EncodingAlgorithmIndexes.CDATA) {
            _octetBufferOffset -= _octetBufferLength;
            decodeUtf8StringIntoCharBuffer();

            _characters = _charBuffer;
            _charactersOffset = 0;
            return;
        } else if (_algorithmId >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
            final EncodingAlgorithm ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(_algorithmURI);
            if (ea != null) {
                final Object data = ea.decodeFromBytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
                ea.convertToCharacters(data, buffer);
            } else {
                throw new EncodingAlgorithmException(
                        CommonResourceBundle.getInstance().getString("message.algorithmDataCannotBeReported"));
            }
        }

        _characters = new char[buffer.length()];
        buffer.getChars(0, buffer.length(), _characters, 0);
        _charactersOffset = 0;
        _charBufferLength = _characters.length;
    }

    /* If base64 data comes is chunks, bytes, which were cut to align 3,
     * from prev. base64 chunk are stored in this buffer */
    private byte[] base64TaleBytes = new byte[3];
    private int base64TaleLength;
    /*
     * Method converts _algorithmData to base64 encoded String
     * Counts with base64 data coming in chunks, aligning input chunks by 3,
     * avoiding double cloning, happening after possible peek, peek2 cloning by Base64 algorithm
     */
    protected void convertBase64AlorithmDataToCharacters(StringBuffer buffer) throws EncodingAlgorithmException, IOException {
        // How much new came data was serialized with prev. tale
        int afterTaleOffset = 0;

        if (base64TaleLength > 0) {
            // Serialize tale left from prev. chunk
            int bytesToCopy = Math.min(3 - base64TaleLength, _algorithmDataLength);
            System.arraycopy(_algorithmData, _algorithmDataOffset, base64TaleBytes, base64TaleLength, bytesToCopy);
            if (base64TaleLength + bytesToCopy == 3) {
                base64DecodeWithCloning(buffer, base64TaleBytes, 0, 3);
            } else if (!isBase64Follows()) {
                // End of text was read to temp array
                base64DecodeWithCloning(buffer, base64TaleBytes, 0, base64TaleLength + bytesToCopy);
                return;
            } else {
                // If the end of chunk fit to tmp array, but next chunk is expected
                base64TaleLength += bytesToCopy;
                return;
            }

            afterTaleOffset = bytesToCopy;
            base64TaleLength = 0;
        }

        int taleBytesRemaining = isBase64Follows() ? (_algorithmDataLength - afterTaleOffset) % 3 : 0;

        if (_isAlgorithmDataCloned) {
            base64DecodeWithoutCloning(buffer, _algorithmData, _algorithmDataOffset + afterTaleOffset,
                    _algorithmDataLength - afterTaleOffset - taleBytesRemaining);
        } else {
            base64DecodeWithCloning(buffer, _algorithmData, _algorithmDataOffset + afterTaleOffset,
                    _algorithmDataLength - afterTaleOffset - taleBytesRemaining);
        }

        if (taleBytesRemaining > 0) {
            System.arraycopy(_algorithmData, _algorithmDataOffset + _algorithmDataLength - taleBytesRemaining,
                    base64TaleBytes, 0, taleBytesRemaining);
            base64TaleLength = taleBytesRemaining;
        }
    }

    /*
     * Encodes incoming data to Base64 string.
     * Method performs additional input data cloning
     */
    private void base64DecodeWithCloning(StringBuffer dstBuffer, byte[] data, int offset, int length) throws EncodingAlgorithmException {
        Object array = BuiltInEncodingAlgorithmFactory.base64EncodingAlgorithm.
                decodeFromBytes(data, offset, length);
        BuiltInEncodingAlgorithmFactory.base64EncodingAlgorithm.convertToCharacters(array, dstBuffer);
    }

    /*
     * Encodes incoming data to Base64 string.
     * Avoids input data cloning
     */
    private void base64DecodeWithoutCloning(StringBuffer dstBuffer, byte[] data, int offset, int length) throws EncodingAlgorithmException {
        BuiltInEncodingAlgorithmFactory.base64EncodingAlgorithm.convertToCharacters(data, offset, length, dstBuffer);
    }


    /*
     * Looks ahead in InputStream, whether next data is Base64 chunk
     */
    public boolean isBase64Follows() throws IOException {
        // Process information item
        int b = peek(this);
        switch (DecoderStateTables.EII(b)) {
            case DecoderStateTables.CII_EA:
                int algorithmId = (b & 0x02) << 6;
                int b2 = peek2(this);
                algorithmId |= (b2 & 0xFC) >> 2;

                return algorithmId == EncodingAlgorithmIndexes.BASE64;
            default:
                return false;
        }
    }

    protected class NamespaceContextImpl implements NamespaceContext {
        public final String getNamespaceURI(String prefix) {
            return _prefixTable.getNamespaceFromPrefix(prefix);
        }

        public final String getPrefix(String namespaceURI) {
            return _prefixTable.getPrefixFromNamespace(namespaceURI);
        }

        public final Iterator getPrefixes(String namespaceURI) {
            return _prefixTable.getPrefixesFromNamespace(namespaceURI);
        }
    }

    public final String getNamespaceDecl(String prefix) {
        return _prefixTable.getNamespaceFromPrefix(prefix);
    }

    public final String getURI(String prefix) {
        return getNamespaceDecl(prefix);
    }

    public final Iterator getPrefixes() {
        return _prefixTable.getPrefixes();
    }

    public final AttributesHolder getAttributesHolder() {
        return _attributes;
    }

    public final void setManager(StAXManager manager) {
        _manager = manager;
    }

    final static String getEventTypeString(int eventType) {
        switch (eventType){
            case START_ELEMENT:
                return "START_ELEMENT";
            case END_ELEMENT:
                return "END_ELEMENT";
            case PROCESSING_INSTRUCTION:
                return "PROCESSING_INSTRUCTION";
            case CHARACTERS:
                return "CHARACTERS";
            case COMMENT:
                return "COMMENT";
            case START_DOCUMENT:
                return "START_DOCUMENT";
            case END_DOCUMENT:
                return "END_DOCUMENT";
            case ENTITY_REFERENCE:
                return "ENTITY_REFERENCE";
            case ATTRIBUTE:
                return "ATTRIBUTE";
            case DTD:
                return "DTD";
            case CDATA:
                return "CDATA";
        }
        return "UNKNOWN_EVENT_TYPE";
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java StAXDocumentParser.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.