/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.axiom.om.impl.common;

import java.io.IOException;
import java.io.Writer;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Stack;

import javax.activation.DataHandler;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.apache.axiom.ext.stax.CharacterDataReader;
import org.apache.axiom.ext.stax.datahandler.DataHandlerProvider;
import org.apache.axiom.ext.stax.datahandler.DataHandlerReader;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMComment;
import org.apache.axiom.om.OMContainer;
import org.apache.axiom.om.OMDataSource;
import org.apache.axiom.om.OMDocType;
import org.apache.axiom.om.OMDocument;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.OMProcessingInstruction;
import org.apache.axiom.om.OMSerializable;
import org.apache.axiom.om.OMSourcedElement;
import org.apache.axiom.om.OMText;
import org.apache.axiom.om.OMXMLParserWrapper;
import org.apache.axiom.om.impl.builder.StAXBuilder;
import org.apache.axiom.om.impl.exception.OMStreamingException;
import org.apache.axiom.util.namespace.MapBasedNamespaceContext;
import org.apache.axiom.util.stax.AbstractXMLStreamReader;
import org.apache.axiom.util.stax.DummyLocation;
import org.apache.axiom.util.stax.XMLStreamReaderUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Class used internally by {@link OMStAXWrapper}.
 */
class SwitchingWrapper extends AbstractXMLStreamReader
    implements DataHandlerReader, CharacterDataReader, XMLStreamConstants {
    
    private static final Log log = LogFactory.getLog(SwitchingWrapper.class);
    
    /** Field navigator */
    private OMNavigator navigator;

    /** Field builder */
    private OMXMLParserWrapper builder;

    /** Field parser */
    private XMLStreamReader parser;
    
    /**
     * The {@link DataHandlerReader} extension of the underlying parser, or <code>null</code>
     * if the parser doesn't support this extension.
     */
    private DataHandlerReader dataHandlerReader;
    
    private boolean _isClosed = false;              // Indicate if parser is closed
    private boolean _releaseParserOnClose = false;  // Defaults to legacy behavior, which is keep the reference

    /** Field rootNode */
    private OMContainer rootNode;

    /** Field isFirst */
    private boolean isFirst = true;

    // Navigable means the output should be taken from the navigator.
    // As soon as the navigator returns a null navigable will be reset
    // to false and the subsequent events will be taken from the builder
    // or the parser directly.

    /** Field NAVIGABLE */
    private static final short NAVIGABLE = 0;
    private static final short SWITCH_AT_NEXT = 1;
    private static final short COMPLETED = 2;
    private static final short SWITCHED = 3;
    private static final short DOCUMENT_COMPLETE = 4;

    /** Field state */
    private short state;

    /** Field currentEvent Default set to START_DOCUMENT */
    private int currentEvent = START_DOCUMENT;

    /**
     * Specifies whether the original document content is cached (i.e. whether the object model is
     * built) or can be consumed.
     */
    private final boolean cache;
    
    /**
     * Specifies whether additional namespace declarations should be generated to preserve the
     * namespace context. See {@link OMElement#getXMLStreamReader(boolean, boolean)} for more
     * information about the meaning of this attribute.
     */
    private final boolean preserveNamespaceContext;
    
    /** Field elementStack */
    private Stack nodeStack = null;

    // keeps the next event. The parser actually keeps one step ahead to
    // detect the end of navigation. (at the end of the stream the navigator
    // returns a null

    /** Field nextNode */
    private OMSerializable nextNode = null;

    // holder for the current node. Needs this to generate events from the
    // current node

    /** Field currentNode */
    private OMSerializable currentNode = null;

    // needs this to refer to the last known node

    /** Field lastNode */
    private OMSerializable lastNode = null;

    /** Track depth to ensure we stop generating events when we are done with the root node. */
    int depth = 0;

    // Cache attributes and namespaces. This avoids creating a new Iterator for every call
    // to getAttributeXXX and getNamespaceXXX. A value of -1 indicates that the
    // attributes or namespaces for the current element have not been loaded yet. The
    // two arrays are resized on demand.
    private int attributeCount = -1;
    private OMAttribute[] attributes = new OMAttribute[16];
    private int namespaceCount = -1;
    private OMNamespace[] namespaces = new OMNamespace[16];
    
    /**
     * Constructor.
     *
     * @param builder
     * @param startNode
     * @param cache
     * @param preserveNamespaceContext
     */
    public SwitchingWrapper(OMXMLParserWrapper builder, OMContainer startNode,
                            boolean cache, boolean preserveNamespaceContext) {

        // create a navigator
        this.navigator = new OMNavigator(startNode);
        this.builder = builder;
        this.rootNode = startNode;
        this.cache = cache;
        this.preserveNamespaceContext = preserveNamespaceContext;

        // initiate the next and current nodes
        // Note - navigator is written in such a way that it first
        // returns the starting node at the first call to it
        // Note - for OMSourcedElements, temporarily set caching
        // to get the initial navigator nodes
        boolean resetCache = false;
        try {
            if (startNode instanceof OMSourcedElement && 
                    !cache && builder != null) {
                if (!builder.isCache()) {
                    resetCache = true;
                }
                builder.setCache(true); // bootstrap the navigator
                
            }
        } catch(Throwable t) {}
        
        currentNode = navigator.getNext();
        updateNextNode(false);
        if (resetCache) {
            builder.setCache(cache); 
        }
        
        if (startNode instanceof OMDocument) {
            try {
                next();
            } catch (XMLStreamException ex) {
                throw new OMException(ex);
            }
        }
    }

    /**
     * @return Returns String.
     * @see javax.xml.stream.XMLStreamReader#getPrefix()
     */
    public String getPrefix() {
        if (parser != null && currentEvent != END_DOCUMENT) {
            return parser.getPrefix();
        } else {
            if ((currentEvent == START_ELEMENT)
                    || (currentEvent == END_ELEMENT)) {
                OMNamespace ns = ((OMElement) lastNode).getNamespace();
                if (ns == null) {
                    return null;
                } else {
                    String prefix = ns.getPrefix();
                    return prefix.length() == 0 ? null : prefix; 
                }
            } else {
                throw new IllegalStateException();
            }
        }
    }

    /**
     * @return Returns String.
     * @see javax.xml.stream.XMLStreamReader#getNamespaceURI()
     */
    public String getNamespaceURI() {
        String returnStr;
        if (parser != null && currentEvent != END_DOCUMENT) {
            returnStr = parser.getNamespaceURI();
        } else {
            if ((currentEvent == START_ELEMENT)
                    || (currentEvent == END_ELEMENT)) {
                OMNamespace ns = ((OMElement) lastNode).getNamespace();
                if (ns == null) {
                    returnStr = null;
                } else {
                    String namespaceURI = ns.getNamespaceURI();
                    returnStr = namespaceURI.length() == 0 ? null : namespaceURI;
                }
            } else {
                throw new IllegalStateException();
            }
        }
        return returnStr;
    }

    /**
     * @return Returns boolean.
     * @see javax.xml.stream.XMLStreamReader#hasName()
     */
    public boolean hasName() {
        if (parser != null && currentEvent != END_DOCUMENT) {
            return parser.hasName();
        } else {
            return ((currentEvent == START_ELEMENT)
                    || (currentEvent == END_ELEMENT));
        }
    }

    /**
     * @return Returns String.
     * @see javax.xml.stream.XMLStreamReader#getLocalName()
     */
    public String getLocalName() {
        if (parser != null && currentEvent != END_DOCUMENT) {
            return parser.getLocalName();
        } else {
            if ((currentEvent == START_ELEMENT)
                    || (currentEvent == END_ELEMENT)
                    || (currentEvent == ENTITY_REFERENCE)) {
                return ((OMElement) lastNode).getLocalName();
            } else {
                throw new IllegalStateException();
            }
        }
    }

    /**
     * @return Returns QName.
     * @see javax.xml.stream.XMLStreamReader#getName()
     */
    public QName getName() {
        if (parser != null && currentEvent != END_DOCUMENT) {
            return parser.getName();
        } else {
            if ((currentEvent == START_ELEMENT)
                    || (currentEvent == END_ELEMENT)) {
                return ((OMElement)lastNode).getQName();
            } else {
                throw new IllegalStateException();
            }
        }
    }

    /**
     * @return Returns int.
     * @see javax.xml.stream.XMLStreamReader#getTextLength()
     */
    public int getTextLength() {
        if (parser != null) {
            return parser.getTextLength();
        } else if (currentEvent == DTD) {
            // Not sure if that conforms to the StAX spec, but it is what Woodstox does
            throw new IllegalStateException();
        } else {
            return getTextFromNode().length();
        }
    }

    /**
     * @return Returns int.
     * @see javax.xml.stream.XMLStreamReader#getTextStart()
     */
    public int getTextStart() {
        if (parser != null) {
            return parser.getTextStart();
        } else {
            if (currentEvent == DTD) {
                // Not sure if that conforms to the StAX spec, but it is what Woodstox does
                throw new IllegalStateException();
            } else if (hasText()) {
                // getTextCharacters always returns a new char array and the start
                // index is therefore always 0
                return 0;
            } else {
                throw new IllegalStateException();
            }
        }
    }

    /**
     * @param sourceStart
     * @param target
     * @param targetStart
     * @param length
     * @return Returns int.
     * @throws XMLStreamException
     * @see javax.xml.stream.XMLStreamReader#getTextCharacters(int, char[], int, int)
     */
    public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length)
            throws XMLStreamException {
        if (parser != null) {
            try {
                return parser.getTextCharacters(sourceStart, target, targetStart, length);
            } catch (XMLStreamException e) {
                throw new OMStreamingException(e);
            }
        } else {
            if (currentEvent == DTD) {
                // Not sure if that conforms to the StAX spec, but it is what Woodstox does
                throw new IllegalStateException();
            } else {
                String text = getTextFromNode();
                int copied = Math.min(length, text.length()-sourceStart);
                text.getChars(sourceStart, sourceStart + copied, target, targetStart);
                return copied;
            }
        }
    }

    /**
     * @return Returns char[].
     * @see javax.xml.stream.XMLStreamReader#getTextCharacters()
     */
    public char[] getTextCharacters() {
        if (parser != null) {
            return parser.getTextCharacters();
        } else if (currentEvent == DTD) {
            // Not sure if that conforms to the StAX spec, but it is what Woodstox does
            throw new IllegalStateException();
        } else {
            return getTextFromNode().toCharArray();
        }
    }

    /**
     * @return Returns String.
     * @see javax.xml.stream.XMLStreamReader#getText()
     */
    public String getText() {
        if (parser != null) {
            return parser.getText();
        } else {
            return getTextFromNode();
        }
    }
    
    private String getTextFromNode() {
        switch (currentEvent) {
            case CHARACTERS:
            case CDATA:
            case SPACE:
                return ((OMText)lastNode).getText();
            case COMMENT:
                return ((OMComment)lastNode).getValue();
            case DTD:
                return ((OMDocType)lastNode).getValue();
            default:
                throw new IllegalStateException();
        }
    }

    public void writeTextTo(Writer writer) throws XMLStreamException, IOException {
        if (parser != null) {
            XMLStreamReaderUtils.writeTextTo(parser, writer);
        } else {
            switch (currentEvent) {
                case CHARACTERS:
                case CDATA:
                case SPACE:
                    OMText text = (OMText)lastNode;
                    if (text.isCharacters()) {
                        writer.write(text.getTextCharacters());
                    } else {
                        // TODO: we should cover the binary case in an optimized way
                        writer.write(text.getText());
                    }
                    break;
                case COMMENT:
                    writer.write(((OMComment)lastNode).getValue());
                    break;
                default:
                    throw new IllegalStateException();
            }
        }
    }

    /**
     * @return Returns int.
     * @see javax.xml.stream.XMLStreamReader#getEventType()
     */

    // todo this should be improved
    public int getEventType() {
        return currentEvent;
    }

    private void loadAttributes() {
        if (attributeCount == -1) {
            attributeCount = 0;
            for (Iterator it = ((OMElement)lastNode).getAllAttributes(); it.hasNext(); ) {
                OMAttribute attr = (OMAttribute)it.next();
                if (attributeCount == attributes.length) {
                    OMAttribute[] newAttributes = new OMAttribute[attributes.length*2];
                    System.arraycopy(attributes, 0, newAttributes, 0, attributes.length);
                    attributes = newAttributes;
                }
                attributes[attributeCount] = attr;
                attributeCount++;
            }
        }
    }
    
    private void loadNamespaces() {
        if (namespaceCount == -1) {
            namespaceCount = 0;
            for (Iterator it = ((OMElement)lastNode).getAllDeclaredNamespaces(); it.hasNext(); ) {
                addNamespace((OMNamespace)it.next());
            }
            if (preserveNamespaceContext && lastNode == rootNode) {
                OMElement element = (OMElement)lastNode;
                while (true) {
                    OMContainer container = element.getParent();
                    if (container instanceof OMElement) {
                        element = (OMElement)container;
                        decl: for (Iterator it = element.getAllDeclaredNamespaces(); it.hasNext(); ) {
                            OMNamespace ns = (OMNamespace)it.next();
                            String prefix = ns.getPrefix();
                            for (int i=0; i<namespaceCount; i++) {
                                if (namespaces[i].getPrefix().equals(prefix)) {
                                    continue decl;
                                }
                            }
                            addNamespace(ns);
                        }
                    } else {
                        break;
                    }
                }
            }
        }
    }
    
    private void addNamespace(OMNamespace ns) {
        // TODO: verify if this check is actually still necessary
        // Axiom internally creates an OMNamespace instance for the "xml" prefix, even
        // if it is not declared explicitly. Filter this instance out.
        if (!"xml".equals(ns.getPrefix())) {
            if (namespaceCount == namespaces.length) {
                OMNamespace[] newNamespaces = new OMNamespace[namespaces.length*2];
                System.arraycopy(namespaces, 0, newNamespaces, 0, namespaces.length);
                namespaces = newNamespaces;
            }
            namespaces[namespaceCount] = ns;
            namespaceCount++;
        }
    }
    
    /**
     * @param i
     * @return Returns String.
     * @see javax.xml.stream.XMLStreamReader#getNamespaceURI
     */
    public String getNamespaceURI(int i) {
        String returnString = null;
        if (parser != null) {
            returnString = parser.getNamespaceURI(i);
        } else {
            if (isStartElement() || isEndElement()) {
                loadNamespaces();
                returnString = namespaces[i].getNamespaceURI();
            }
        }

        /*
          The following line is necessary to overcome an issue where the empty
          namespace URI returning null rather than the empty string. Our resolution
          is to return "" if the return is actually null

          Note that this is not the case for  getNamespaceURI(prefix) method
          where the contract clearly specifies that the return may be null

        */
        if (returnString == null) returnString = "";

        return returnString;
    }

    /**
     * @param i
     * @return Returns String.
     * @see javax.xml.stream.XMLStreamReader#getNamespacePrefix
     */
    public String getNamespacePrefix(int i) {
        String returnString = null;
        if (parser != null) {
            returnString = parser.getNamespacePrefix(i);
        } else {
            if (isStartElement() || isEndElement()) {
                loadNamespaces();
                String prefix = namespaces[i].getPrefix();
                returnString = prefix.length() == 0 ? null : prefix; 
            }
        }
        return returnString;
    }

    /**
     * @return Returns int.
     * @see javax.xml.stream.XMLStreamReader#getNamespaceCount()
     */
    public int getNamespaceCount() {
        if (parser != null && currentEvent != END_DOCUMENT) {
            return parser.getNamespaceCount();
        } else {
            if (isStartElement() || isEndElement()) {
                loadNamespaces();
                return namespaceCount;
            } else {
                throw new IllegalStateException();
            }
        }
    }

    /**
     * @param i
     * @return Returns boolean.
     * @see javax.xml.stream.XMLStreamReader#isAttributeSpecified
     */
    public boolean isAttributeSpecified(int i) {
        if (parser != null) {
            return parser.isAttributeSpecified(i);
        } else {
            if (isStartElement()) {
                // The Axiom object model doesn't store this information,
                // but returning true is a reasonable default.
                return true;
            } else {
                throw new IllegalStateException(
                        "attribute type accessed in illegal event!");
            }
        }
    }

    /**
     * @param i
     * @return Returns String.
     * @see javax.xml.stream.XMLStreamReader#getAttributeValue
     */
    public String getAttributeValue(int i) {
        String returnString = null;
        if (parser != null) {
            returnString = parser.getAttributeValue(i);
        } else {
            if (isStartElement()) {
                loadAttributes();
                returnString = attributes[i].getAttributeValue();
            } else {
                throw new IllegalStateException(
                        "attribute type accessed in illegal event!");
            }
        }
        return returnString;
    }

    /**
     * @param i
     * @return Returns String.
     * @see javax.xml.stream.XMLStreamReader#getAttributeType
     */
    public String getAttributeType(int i) {
        String returnString = null;
        if (parser != null) {
            returnString = parser.getAttributeType(i);
        } else {
            if (isStartElement()) {
                loadAttributes();
                returnString = attributes[i].getAttributeType();
            } else {
                throw new IllegalStateException(
                        "attribute type accessed in illegal event!");
            }
        }
        return returnString;
    }

    /**
     * @param i
     * @return Returns String.
     * @see javax.xml.stream.XMLStreamReader#getAttributePrefix
     */
    public String getAttributePrefix(int i) {
        String returnString = null;
        if (parser != null) {
            returnString = parser.getAttributePrefix(i);
        } else {
            if (isStartElement()) {
                loadAttributes();
                OMAttribute attrib = attributes[i];
                if (attrib != null) {
                    OMNamespace nameSpace = attrib.getNamespace();
                    if (nameSpace != null) {
                        returnString = nameSpace.getPrefix();
                    }
                }
            } else {
                throw new IllegalStateException(
                        "attribute prefix accessed in illegal event!");
            }
        }
        return returnString;
    }

    /**
     * @param i
     * @return Returns String.
     * @see javax.xml.stream.XMLStreamReader#getAttributeLocalName
     */
    public String getAttributeLocalName(int i) {
        String returnString = null;
        if (parser != null) {
            returnString = parser.getAttributeLocalName(i);
        } else {
            if (isStartElement()) {
                loadAttributes();
                returnString = attributes[i].getLocalName();
            } else {
                throw new IllegalStateException(
                        "attribute localName accessed in illegal event!");
            }
        }
        return returnString;
    }

    /**
     * @param i
     * @return Returns String.
     * @see javax.xml.stream.XMLStreamReader#getAttributeNamespace
     */
    public String getAttributeNamespace(int i) {
        String returnString = null;
        if (parser != null) {
            returnString = parser.getAttributeNamespace(i);
        } else {
            if (isStartElement()) {
                loadAttributes();
                OMAttribute attrib = attributes[i];
                if (attrib != null) {
                    OMNamespace nameSpace = attrib.getNamespace();
                    if (nameSpace != null) {
                        returnString = nameSpace.getNamespaceURI();
                    }
                }
            } else {
                throw new IllegalStateException(
                        "attribute nameSpace accessed in illegal event!");
            }
        }
        return returnString;
    }

    /**
     * @param i
     * @return Returns QName.
     * @see javax.xml.stream.XMLStreamReader#getAttributeName
     */
    public QName getAttributeName(int i) {
        QName returnQName = null;
        if (parser != null) {
            returnQName = parser.getAttributeName(i);
        } else {
            if (isStartElement()) {
                loadAttributes();
                returnQName = attributes[i].getQName();
            } else {
                throw new IllegalStateException(
                        "attribute count accessed in illegal event!");
            }
        }
        return returnQName;
    }

    /**
     * @return Returns int.
     * @see javax.xml.stream.XMLStreamReader#getAttributeCount
     */
    public int getAttributeCount() {
        int returnCount = 0;
        if (parser != null) {
            returnCount = parser.getAttributeCount();
        } else {
            if (isStartElement()) {
                loadAttributes();
                returnCount = attributeCount;
            } else {
                throw new IllegalStateException(
                        "attribute count accessed in illegal event (" +
                                currentEvent + ")!");
            }
        }
        return returnCount;
    }

    // todo

    /**
     * Method getAttributeValue.
     *
     * @param s
     * @param s1
     * @return Returns String.
     */
    public String getAttributeValue(String s, String s1) {
        String returnString = null;
        if (parser != null) {
            returnString = parser.getAttributeValue(s, s1);
        } else {
            if (isStartElement()) {
                QName qname = new QName(s, s1);
                OMAttribute attrib = ((OMElement) lastNode).getAttribute(qname);
                if (attrib != null) {
                    returnString = attrib.getAttributeValue();
                }
            } else {
                throw new IllegalStateException(
                        "attribute type accessed in illegal event!");
            }
        }
        return returnString;
    }

    /**
     * Method isWhiteSpace.
     *
     * @return Returns boolean.
     */
    public boolean isWhiteSpace() {
        if (parser != null) {
            return parser.isWhiteSpace();
        } else {
            switch (currentEvent) {
                case SPACE:
                    return true;
                case CHARACTERS:
                    // XMLStreamReader Javadoc says that isWhiteSpace "returns true if the cursor
                    // points to a character data event that consists of all whitespace". This
                    // means that this method may return true for a CHARACTER event and we need
                    // to scan the text of the node.
                    String text = getTextFromNode();
                    for (int i=0; i<text.length(); i++) {
                        char c = text.charAt(i);
                        if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
                            return false;
                        }
                    }
                    return true;
                default:
                    return false;
            }
        }
    }

    /**
     * Method isCharacters.
     *
     * @return Returns boolean.
     */
    public boolean isCharacters() {
        boolean b;
        if (parser != null) {
            b = parser.isCharacters();
        } else {
            b = (currentEvent == CHARACTERS);
        }
        return b;
    }

    /**
     * Method isEndElement.
     *
     * @return Returns boolean.
     */
    public boolean isEndElement() {
        boolean b;
        if (parser != null && currentEvent != END_DOCUMENT) {
            b = parser.isEndElement();
        } else {
            b = (currentEvent == END_ELEMENT);
        }
        return b;
    }

    /**
     * Method isStartElement.
     *
     * @return Returns boolean.
     */
    public boolean isStartElement() {
        boolean b;
        if (parser != null) {
            b = parser.isStartElement();
        } else {
            b = (currentEvent == START_ELEMENT);
        }
        return b;
    }

    /**
     * Method getNamespaceURI.
     *
     * @param prefix
     * @return Returns String.
     */
    public String getNamespaceURI(String prefix) {
        String returnString = null;
        if (parser != null) {
            returnString = parser.getNamespaceURI(prefix);
        } else {
            if (isStartElement() || isEndElement()) {

                if (lastNode instanceof OMElement) {
                    OMNamespace namespaceURI =
                            ((OMElement) lastNode).findNamespaceURI(prefix);
                    return namespaceURI != null ? namespaceURI.getNamespaceURI() : null;
                }
            }
        }
        return returnString;
    }

    /**
     * Method close.
     *
     * @throws XMLStreamException
     */
    public void close() throws XMLStreamException {

        // If there is a builder, it controls its parser
        if (builder != null && builder instanceof StAXBuilder) {
            StAXBuilder staxBuilder = (StAXBuilder) builder;
            staxBuilder.close();
            setParser(null);
        } else {
            if (parser != null) {
                try {
                    if (!isClosed()) {
                        parser.close();
                    }
                } finally {
                    _isClosed = true;
                    // Release the parser so that it can be GC'd or reused.
                    if (_releaseParserOnClose) {
                        setParser(null);
                    }
                }
            }
        }
    }

    /**
     * Method hasNext.
     *
     * @return Returns boolean.
     * @throws XMLStreamException
     */
    public boolean hasNext() throws XMLStreamException {
        return currentEvent != END_DOCUMENT;
    }

    /**
     * @return Returns String.
     * @throws XMLStreamException
     * @see javax.xml.stream.XMLStreamReader#getElementText()
     */
    public String getElementText() throws XMLStreamException {
        if (parser != null) {
            try {
                String elementText = parser.getElementText();
                currentEvent = END_ELEMENT;
                return elementText;
            } catch (XMLStreamException e) {
                throw new OMStreamingException(e);
            }
        } else {
            ///////////////////////////////////////////////////////
            //// Code block directly from the API documentation ///
            if (getEventType() != XMLStreamConstants.START_ELEMENT) {
                throw new XMLStreamException(
                        "parser must be on START_ELEMENT to read next text", getLocation());
            }
            int eventType = next();
            StringBuffer content = new StringBuffer();
            while (eventType != XMLStreamConstants.END_ELEMENT) {
                if (eventType == XMLStreamConstants.CHARACTERS
                        || eventType == XMLStreamConstants.CDATA
                        || eventType == XMLStreamConstants.SPACE
                        || eventType == XMLStreamConstants.ENTITY_REFERENCE) {
                    content.append(getText());
                } else if (eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
                        || eventType == XMLStreamConstants.COMMENT) {
                    // skipping
                } else if (eventType == XMLStreamConstants.END_DOCUMENT) {
                    throw new XMLStreamException(
                            "unexpected end of document when reading element text content");
                } else if (eventType == XMLStreamConstants.START_ELEMENT) {
                    throw new XMLStreamException(
                            "element text content may not contain START_ELEMENT");
                } else {
                    throw new XMLStreamException(
                            "Unexpected event type " + eventType, getLocation());
                }
                eventType = next();
            }
            return content.toString();
            ///////////////////////////////////////////////////////////////
        }

    }

    /**
     * Method next.
     *
     * @return Returns int.
     * @throws XMLStreamException
     */
    public int next() throws XMLStreamException {
        switch (state) {
            case DOCUMENT_COMPLETE:
                throw new NoSuchElementException("End of the document reached");
            case COMPLETED:
                state = DOCUMENT_COMPLETE;
                currentEvent = END_DOCUMENT;
                break;
            case SWITCH_AT_NEXT:
                state = SWITCHED;

                // load the parser
                try {
                    setParser((XMLStreamReader) builder.getParser());
                } catch (Exception e) {
                    throw new XMLStreamException("problem accessing the parser. " + e.getMessage(),
                                                 e);
                }

                // We should throw an END_DOCUMENT
                if ((currentEvent == START_DOCUMENT)
                        && (currentEvent == parser.getEventType())) {
                    currentEvent = parser.next();
                } else {
                    currentEvent = parser.getEventType();
                }
                updateCompleteStatus();
                break;
            case NAVIGABLE:
                currentEvent = generateEvents(currentNode);
                updateCompleteStatus();
                updateLastNode();
                break;
            case SWITCHED:
                if (parser.hasNext()) {
                    currentEvent = parser.next();
                }
                updateCompleteStatus();
                break;
            default:
                throw new OMStreamingException("unsuppported state!");
        }
        return currentEvent;
    }

    /**
     * Method getProperty.
     *
     * @param s
     * @return Returns Object.
     * @throws IllegalArgumentException
     */
    public Object getProperty(String s) throws IllegalArgumentException {
        Object value = XMLStreamReaderUtils.processGetProperty(this, s);
        if (value != null) {
            return value;
        }
        if (CharacterDataReader.PROPERTY.equals(s)) {
            return this;
        }
        if (parser != null) {
            return parser.getProperty(s);
        }
        // Delegate to the builder's parser.
        if (builder != null && builder instanceof StAXBuilder) {
            StAXBuilder staxBuilder = (StAXBuilder) builder;
            if (!staxBuilder.isClosed()) {
                // If the parser was closed by something other
                // than the builder, an IllegalStateException is
                // thrown.  For now, return null as this is unexpected
                // by the caller.
                try {
                    return ((StAXBuilder) builder).getReaderProperty(s);
                } catch (IllegalStateException ise) {
                    return null;
                }
            }
        }
        return null;
    }

    /**
     * This is a very important method. It keeps the navigator one step ahead and pushes it one
     * event ahead. If the nextNode is null then navigable is set to false. At the same time the
     * parser and builder are set up for the upcoming event generation.
     *
     * @throws XMLStreamException
     */
    private void updateLastNode() throws XMLStreamException {
        lastNode = currentNode;
        attributeCount = -1;
        namespaceCount = -1;
        currentNode = nextNode;
        try {
            updateNextNode(!cache);
        } catch (Exception e) {
            throw new XMLStreamException(e);
        }
    }

    /** Method updateNextNode. */
    private void updateNextNode(boolean switchingAllowed) {
        if (navigator.isNavigable()) {
            nextNode = navigator.getNext();
        } else {
            if (!switchingAllowed) {
                if (navigator.isCompleted() || builder == null || builder.isCompleted()) {
                    nextNode = null;
                    if (log.isDebugEnabled()) {
                        if (builder == null || builder.isCompleted()) {
                            log.debug("Builder is complete.  Next node is set to null.");
                        }
                    }
                } else {
                    builder.next();
                    navigator.step();
                    nextNode = navigator.getNext();
                }
            } else {
                //at this point check whether the navigator is done
                //if the navigator is done then we are fine and can directly
                // jump to the complete state ?
                if (navigator.isCompleted()) {
                    nextNode = null;
                } else {
                    // reset caching (the default is ON so it was not needed in the
                    // earlier case!
                    if (builder != null) {
                        builder.setCache(false);
                    }
                    state = SWITCH_AT_NEXT;
                }
            }
        }
    }

    /** Method updateCompleteStatus. */
    private void updateCompleteStatus() {
        if (currentEvent == START_ELEMENT) {
            depth++;
        } else if (currentEvent == END_ELEMENT) {
            depth--;
        }
        if (state == NAVIGABLE) {
            if (rootNode == currentNode) {
                if (isFirst) {
                    isFirst = false;
                } else if (currentEvent == END_DOCUMENT) {
                    state = DOCUMENT_COMPLETE;
                } else {
                    state = COMPLETED;
                }
            }
        } else {
            if (state == SWITCHED && currentEvent == END_ELEMENT && depth == 0 && rootNode instanceof OMElement) {
                state = COMPLETED;
            }
            state = (currentEvent == END_DOCUMENT)
                    ? DOCUMENT_COMPLETE
                    : state;
        }
    }

    /**
     * Method getNamespaceContext.
     *
     * @return Returns NamespaceContext.
     */
    public NamespaceContext getNamespaceContext() {
        if (state==SWITCHED){
            return parser.getNamespaceContext();
        }
        return new MapBasedNamespaceContext(
                currentEvent == END_DOCUMENT ? Collections.EMPTY_MAP : getAllNamespaces(lastNode));
    }

    /**
     * Method getEncoding.
     *
     * @return Returns String.
     */
    public String getEncoding() {
        if (parser != null) {
            return parser.getEncoding();
        } else {
            if (currentEvent == START_DOCUMENT) {
                if (lastNode instanceof OMDocument) {
                    return ((OMDocument)lastNode).getCharsetEncoding();
                } else {
                    return null;
                }
            } else {
                throw new IllegalStateException();
            }
        }
    }

    /**
     * Method getLocation.
     *
     * @return Returns Location.
     */
    public Location getLocation() {
        return DummyLocation.INSTANCE;
    }

    /**
     * Method getVersion.
     *
     * @return Returns String.
     */
    public String getVersion() {
        return "1.0"; // todo put the constant
    }

    /**
     * Method isStandalone.
     *
     * @return Returns boolean.
     */
    public boolean isStandalone() {
        return true;
    }

    /**
     * Method standaloneSet.
     *
     * @return Returns boolean.
     */
    public boolean standaloneSet() {
        return false;
    }

    /**
     * Method getCharacterEncodingScheme.
     *
     * @return Returns String.
     */
    public String getCharacterEncodingScheme() {
        if (parser != null) {
            return parser.getCharacterEncodingScheme();
        } else {
            if (currentEvent == START_DOCUMENT) {
                if (lastNode instanceof OMDocument) {
                    return ((OMDocument)lastNode).getXMLEncoding();
                } else {
                    return null;
                }
            } else {
                throw new IllegalStateException();
            }
        }
    }

    /**
     * Method getPITarget.
     *
     * @return Returns String.
     */
    public String getPITarget() {
        if (parser != null) {
            return parser.getPITarget();
        } else {
            if (currentEvent == PROCESSING_INSTRUCTION) {
                return ((OMProcessingInstruction)lastNode).getTarget();
            } else {
                throw new IllegalStateException();
            }
        }
    }

    /**
     * Method getPIData.
     *
     * @return Returns String.
     */
    public String getPIData() {
        if (parser != null) {
            return parser.getPIData();
        } else {
            if (currentEvent == PROCESSING_INSTRUCTION) {
                return ((OMProcessingInstruction)lastNode).getValue();
            } else {
                throw new IllegalStateException();
            }
        }
    }

    /*
     *
     * ################################################################
     * DataHandlerReader extension methods
     * ################################################################
     *
     */

    public boolean isBinary() {
        if (parser != null) {
            if (dataHandlerReader != null) {
                return dataHandlerReader.isBinary();
            } else {
                return false;
            }
        } else {
            if (lastNode instanceof OMText) {
                return ((OMText)lastNode).isBinary();
            } else {
                return false;
            }
        }
    }

    public boolean isOptimized() {
        if (parser != null) {
            if (dataHandlerReader != null) {
                return dataHandlerReader.isOptimized();
            } else {
                throw new IllegalStateException();
            }
        } else {
            if (lastNode instanceof OMText) {
                return ((OMText)lastNode).isOptimized();
            } else {
                throw new IllegalStateException();
            }
        }
    }

    public boolean isDeferred() {
        if (parser != null) {
            if (dataHandlerReader != null) {
                return dataHandlerReader.isDeferred();
            } else {
                throw new IllegalStateException();
            }
        } else {
            if (lastNode instanceof OMText) {
                // TODO: we should support deferred building of the DataHandler
                return false;
            } else {
                throw new IllegalStateException();
            }
        }
    }

    public String getContentID() {
        if (parser != null) {
            if (dataHandlerReader != null) {
                return dataHandlerReader.getContentID();
            } else {
                throw new IllegalStateException();
            }
        } else {
            if (lastNode instanceof OMText) {
                return ((OMText)lastNode).getContentID();
            } else {
                throw new IllegalStateException();
            }
        }
    }

    public DataHandler getDataHandler() throws XMLStreamException {
        if (parser != null) {
            if (dataHandlerReader != null) {
                return dataHandlerReader.getDataHandler();
            } else {
                throw new IllegalStateException();
            }
        } else {
            if (lastNode instanceof OMText) {
                return (DataHandler)((OMText)lastNode).getDataHandler();
            } else {
                throw new IllegalStateException();
            }
        }
    }

    public DataHandlerProvider getDataHandlerProvider() {
        if (parser != null) {
            if (dataHandlerReader != null) {
                return dataHandlerReader.getDataHandlerProvider();
            } else {
                throw new IllegalStateException();
            }
        } else {
            throw new IllegalStateException();
        }
    }

    /*
     *
     * ################################################################
     * Generator methods for the OMNodes returned by the navigator
     * ################################################################
     *
     */

    /**
     * Method generateEvents.
     *
     * @param node
     * @return Returns int.
     */
    private int generateEvents(OMSerializable node) {
        if (node == null) {
            if (log.isDebugEnabled()) {
                log.debug("Node is null...returning END_DOCUMENT");
            }
            return END_DOCUMENT;
        }
        if (node instanceof OMDocument) {
            return generateContainerEvents((OMDocument)node, true);
        } else {
            int nodeType = ((OMNode)node).getType();
            if (nodeType == OMNode.ELEMENT_NODE) {
                return generateContainerEvents((OMElement)node, false);
            } else {
                return nodeType;
            }
        }
    }

    private int generateContainerEvents(OMContainer container, boolean isDocument) {
        if (nodeStack == null) {
            nodeStack = new Stack();
        }
        if (!nodeStack.isEmpty() && nodeStack.peek().equals(container)) {
            nodeStack.pop();
            return isDocument ? END_DOCUMENT : END_ELEMENT;
        } else {
            nodeStack.push(container);
            return isDocument ? START_DOCUMENT : START_ELEMENT;
        }
    }

    /*
     * ####################################################################
     * Other helper methods
     * ####################################################################
     */

    private void setParser(XMLStreamReader parser) {
        this.parser = parser;
        dataHandlerReader =
                parser == null ? null : XMLStreamReaderUtils.getDataHandlerReader(parser);
    }

    private Map getAllNamespaces(OMSerializable contextNode) {
        if (contextNode == null) {
            return Collections.EMPTY_MAP;
        }
        OMContainer context;
        if (contextNode instanceof OMContainer) {
            context = (OMContainer)contextNode;
        } else {
            context = ((OMNode)contextNode).getParent();
        }
        Map nsMap = new LinkedHashMap();
        while (context != null && !(context instanceof OMDocument)) {
            OMElement element = (OMElement) context;
            Iterator i = element.getAllDeclaredNamespaces();
            while (i != null && i.hasNext()) {
                addNamespaceToMap((OMNamespace) i.next(), nsMap);
            }
            if (element.getNamespace() != null) {
                addNamespaceToMap(element.getNamespace(), nsMap);
            }
            for (Iterator iter = element.getAllAttributes();
                 iter != null && iter.hasNext();) {
                OMAttribute attr = (OMAttribute) iter.next();
                if (attr.getNamespace() != null) {
                    addNamespaceToMap(attr.getNamespace(), nsMap);
                }
            }
            context = element.getParent();
        }
        return nsMap;
    }

    private void addNamespaceToMap(OMNamespace ns, Map map) {
        if (map.get(ns.getPrefix()) == null) {
            map.put(ns.getPrefix(), ns.getNamespaceURI());
        }
    }

    /**
     * @return if parser is closed
     */
    public boolean isClosed() {
        
        // If there is a builder, the builder owns the parser
        // and knows the isClosed status
        if (builder != null && builder instanceof StAXBuilder) {
           return ((StAXBuilder) builder).isClosed();
        } else {
            return _isClosed;
        }
    }
    
    /**
     * Indicate if the parser resource should be release when closed.
     * @param value boolean
     */
    public void releaseParserOnClose(boolean value) {
        // if there is a StAXBuilder, it owns the parser 
        // and controls the releaseOnClose status
        if (builder != null && builder instanceof StAXBuilder) {
            ((StAXBuilder) builder).releaseParserOnClose(value);
            if (isClosed() && value) {
                setParser(null);
            }
            return;
        } else {
            // Release parser if already closed
            if (isClosed() && value) {
                setParser(null);
            }
            _releaseParserOnClose = value;
        }
        
    }
    
    /**
     * @return OMDataSource associated with the current node or Null
     */
    public OMDataSource getDataSource() {
        if (getEventType() != XMLStreamReader.START_ELEMENT ||
                !(state == this.NAVIGABLE || 
                  state == this.SWITCH_AT_NEXT)) {
            return null;
        }
        OMDataSource ds = null;
        if (lastNode != null &&
            lastNode instanceof OMSourcedElement) {
            try {
                ds = ((OMSourcedElement) lastNode).getDataSource();
            } catch (UnsupportedOperationException e) {
                // Some implementations throw an UnsupportedOperationException.
                ds =null;
            }
            if (log.isDebugEnabled()) {
                if (ds != null) {
                    log.debug("OMSourcedElement exposed an OMDataSource." + ds);
                } else {
                    log.debug("OMSourcedElement does not have a OMDataSource.");
                }
            }
        }
        return ds;
    }
    
    /**
     * Enable if an OMSourcedElement with an OMDataSource should be treated as a
     * leaf node.  Disable (the default) if the OMDataSource should be parsed and
     * converted into events.
     * @param value boolean
     */
    public void enableDataSourceEvents(boolean value) {
        navigator.setDataSourceIsLeaf(value);
    }
}
