/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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.xmlbeans.impl.validator;

import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlError;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.impl.common.ValidatorListener;
import org.apache.xmlbeans.impl.common.XmlWhitespace;
import org.apache.xmlbeans.impl.common.QNameHelper;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.Location;
import javax.xml.stream.events.XMLEvent;
import javax.xml.stream.util.StreamReaderDelegate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * This class is a wrapper over a generic XMLStreamReader that provides validation.
 * There are 3 cases:
 * <br/> 1) the XMLStreamReader represents a document, it contains only one element document
 *          - in this case the user schema type should be null or it should be a document SchemaType
 * <br/> 2) the XMLStreamReader represents an xml-fragment (content only) - must have at least one user type or xsi:type
 * <br/>     a) it has an xsi:type - if user schema type is available it has to be a base type of xsi:type
 * <br/>     b) it doesn't have xsi:type - user must provide a schema type
 *         otherwise will error and will not do validation
 * <br/> 3) the XMLStreamReader represents a global attribute - i.e. user schema type is null and only one attribute
 * <br/>
 *
 * @author Cezar Andrei (cezar.andrei at bea.com)
 * Date: Feb 13, 2004
 */
public class ValidatingXMLStreamReader
    extends StreamReaderDelegate
    implements XMLStreamReader
{
    public static final String OPTION_ATTTRIBUTE_VALIDATION_COMPAT_MODE = "OPTION_ATTTRIBUTE_VALIDATION_COMPAT_MODE";

    private static final String URI_XSI = "http://www.w3.org/2001/XMLSchema-instance";
    private static final QName XSI_TYPE = new QName(URI_XSI, "type");
    private static final QName XSI_NIL  = new QName(URI_XSI, "nil");
    private static final QName XSI_SL   = new QName(URI_XSI, "schemaLocation");
    private static final QName XSI_NSL  = new QName(URI_XSI, "noNamespaceSchemaLocation");

    private SchemaType _contentType;
    private SchemaTypeLoader _stl;
    private XmlOptions _options;
    private Collection _errorListener;
    protected Validator _validator;
    private final ElementEventImpl _elemEvent;
    private final AttributeEventImpl _attEvent;
    private final SimpleEventImpl _simpleEvent;
    private PackTextXmlStreamReader _packTextXmlStreamReader;

    private int _state;
    private final int STATE_FIRSTEVENT = 0;
    private final int STATE_VALIDATING = 1;
    private final int STATE_ATTBUFFERING = 2;
    private final int STATE_ERROR = 3;

    private List _attNamesList;
    private List _attValuesList;
    private SchemaType _xsiType;

    private int _depth;

    /**
     * Default constructor. Use init(...) to set the params.
     * See {@link #init}
     */
    public ValidatingXMLStreamReader()
    {
        super();
        _elemEvent = new ElementEventImpl();
        _attEvent = new AttributeEventImpl();
        _simpleEvent = new SimpleEventImpl();
        _packTextXmlStreamReader = new PackTextXmlStreamReader();
    }

    /**
     * Used in case of reusing the same ValidatinXMLStreamReader object
     * @param xsr The stream to be validated
     * @param startWithCurrentEvent Validation will start if true with the current event or if false with the next event in the stream
     * @param contentType The schemaType of the content. This can be null for document and global Att validation
     * @param stl SchemaTypeLoader context of validation
     * @param options Validator options
     * @param errorListener Errors and warnings listener
     */
    public void init(XMLStreamReader xsr, boolean startWithCurrentEvent, SchemaType contentType,
                     SchemaTypeLoader stl, XmlOptions options, Collection errorListener)
    {
        _packTextXmlStreamReader.init(xsr);

//        setParent(xsr);
        setParent(_packTextXmlStreamReader);
        _contentType = contentType;
        _stl = stl;
        _options = options;
        _errorListener = errorListener;
//        _elemEvent.setXMLStreamReader(xsr);
//        _attEvent.setXMLStreamReader(xsr);
//        _simpleEvent.setXMLStreamReader(xsr);
        _elemEvent.setXMLStreamReader(_packTextXmlStreamReader);
        _attEvent.setXMLStreamReader(_packTextXmlStreamReader);
        _simpleEvent.setXMLStreamReader(_packTextXmlStreamReader);
        _validator = null;
        _state = STATE_FIRSTEVENT;
        if (_attNamesList!=null)
        {
            _attNamesList.clear();
            _attValuesList.clear();
        }
        _xsiType = null;
        _depth = 0;

        if (startWithCurrentEvent)
        {
            int evType = getEventType();
            validate_event(evType);
        }
    }

    private static class PackTextXmlStreamReader
        extends StreamReaderDelegate
        implements XMLStreamReader
    {
        private boolean _hasBufferedText;
        private StringBuilder _buffer = new StringBuilder();
        private int _textEventType;

        void init(XMLStreamReader xmlstream)
        {
            setParent(xmlstream);
            _hasBufferedText = false;
            _buffer.delete(0, _buffer.length());
        }

        public int next()
            throws XMLStreamException
        {
            if (_hasBufferedText)
            {
                clearBuffer();
                return super.getEventType();
            }

            int evType = super.next();

            if (evType == XMLEvent.CHARACTERS || evType == XMLEvent.CDATA || evType == XMLEvent.SPACE)
            {
                _textEventType = evType;
                bufferText();
            }

            return evType;
        }

        private void clearBuffer()
        {
            _buffer.delete(0, _buffer.length());
            _hasBufferedText = false;
        }

        private void bufferText()
            throws XMLStreamException
        {
            if (super.hasText())
                _buffer.append( super.getText());

            _hasBufferedText = true;

            while (hasNext())
            {
                int evType = super.next();

                switch (evType)
                {
                case XMLEvent.CHARACTERS:
                case XMLEvent.CDATA:
                case XMLEvent.SPACE:
                    if (super.hasText())
                        _buffer.append(super.getText());

                case XMLEvent.COMMENT:
                    //ignore
                    continue;
                default:
                    return;
                }
            }
        }

        public String getText()
        {
            assert _hasBufferedText;
            return _buffer.toString();
        }

        public int getTextLength()
        {
            assert _hasBufferedText;
            return _buffer.length();
        }

        public int getTextStart()
        {
            assert _hasBufferedText;
            return 0;
        }

        public char[] getTextCharacters()
        {
            assert _hasBufferedText;
            return _buffer.toString().toCharArray();
        }

        public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length)
        {
            assert _hasBufferedText;
            _buffer.getChars(sourceStart, sourceStart + length, target, targetStart);
            return length;
        }

        public boolean isWhiteSpace()
        {
            assert _hasBufferedText;
            return XmlWhitespace.isAllSpace(_buffer);
        }

        public boolean hasText()
        {
            if (_hasBufferedText)
                return true;
            else
                return super.hasText();
        }

        public int getEventType()
        {
            if (_hasBufferedText)
                return _textEventType;
            else
                return super.getEventType();
        }
    }

    private static class ElementEventImpl
        implements ValidatorListener.Event
    {
        private static final int BUF_LENGTH = 1024;
        private char[] _buf = new char[BUF_LENGTH];
        private int _length;
        private boolean _supportForGetTextCharacters = true;

        private XMLStreamReader _xmlStream;

        private void setXMLStreamReader(XMLStreamReader xsr)
        {
            _xmlStream = xsr;
        }

        // can return null, used only to locate errors
        public XmlCursor getLocationAsCursor()
        {
            return null;
        }

        public javax.xml.stream.Location getLocation()
        {
            return _xmlStream.getLocation();
        }

        // fill up chars with the xsi:type attribute value if there is one othervise return false
        public String getXsiType() // BEGIN xsi:type
        {
            return _xmlStream.getAttributeValue(URI_XSI, "type");
        }

        // fill up chars with xsi:nill attribute value if any
        public String getXsiNil() // BEGIN xsi:nil
        {
            return _xmlStream.getAttributeValue(URI_XSI, "nil");
        }

        // not used curently
        public String getXsiLoc() // BEGIN xsi:schemaLocation
        {
            return _xmlStream.getAttributeValue(URI_XSI, "schemaLocation");
        }

        // not used curently
        public String getXsiNoLoc() // BEGIN xsi:noNamespaceSchemaLocation
        {
            return _xmlStream.getAttributeValue(URI_XSI, "noNamespaceSchemaLocation");
        }

        // On START and ATTR
        public QName getName()
        {
            // avoid construction of a new QName object after the bug in getName() is fixed.
            if (_xmlStream.hasName())
                return new QName(_xmlStream.getNamespaceURI(), _xmlStream.getLocalName());
            else
                return null;
        }

        // On TEXT and ATTR
        public String getText()
        {
            _length = 0;
            addTextToBuffer();
            return new String( _buf, 0, _length );
//            return _xmlStream.getText();
        }

        public String getText(int wsr)
        {
            return XmlWhitespace.collapse( _xmlStream.getText(), wsr );
        }

        public boolean textIsWhitespace()
        {
            return _xmlStream.isWhiteSpace();
        }

        public String getNamespaceForPrefix(String prefix)
        {
            return _xmlStream.getNamespaceURI(prefix);
        }

        private void addTextToBuffer()
        {
            int textLength = _xmlStream.getTextLength();
            ensureBufferLength(textLength);

            if (_supportForGetTextCharacters)
                try
                {
                    _length = _xmlStream.getTextCharacters(0, _buf, _length, textLength);
                }
                catch(Exception e)
                {
                    _supportForGetTextCharacters = false;
                }

            if(!_supportForGetTextCharacters)
            {
                System.arraycopy(_xmlStream.getTextCharacters(), _xmlStream.getTextStart(), _buf, _length, textLength);
                _length = _length + textLength;
            }
        }

        private void ensureBufferLength(int lengthToAdd)
        {
            if (_length + lengthToAdd>_buf.length)
            {
                char[] newBuf = new char[_length + lengthToAdd];
                if (_length>0)
                    System.arraycopy(_buf, 0, newBuf, 0, _length);
                _buf = newBuf;
            }
        }
    }

    private static final class AttributeEventImpl
        implements ValidatorListener.Event
    {
        private int _attIndex;
        private XMLStreamReader _xmlStream;

        private void setXMLStreamReader(XMLStreamReader xsr)
        {
            _xmlStream = xsr;
        }

        // can return null, used only to locate errors
        public XmlCursor getLocationAsCursor()
        {
            return null;
        }

        public javax.xml.stream.Location getLocation()
        {
            return _xmlStream.getLocation();
        }

        // fill up chars with the xsi:type attribute value if there is one othervise return false
        public String getXsiType() // BEGIN xsi:type
        {
            throw new IllegalStateException();
        }

        // fill up chars with xsi:nill attribute value if any
        public String getXsiNil() // BEGIN xsi:nil
        {
            throw new IllegalStateException();
        }

        // not used curently
        public String getXsiLoc() // BEGIN xsi:schemaLocation
        {
            throw new IllegalStateException();
        }

        // not used curently
        public String getXsiNoLoc() // BEGIN xsi:noNamespaceSchemaLocation
        {
            throw new IllegalStateException();
        }

        // On START and ATTR
        public QName getName()
        {
            assert _xmlStream.isStartElement() : "Not on Start Element.";
            String uri = _xmlStream.getAttributeNamespace(_attIndex);
            QName qn = new QName(uri==null ? "" : uri, _xmlStream.getAttributeLocalName(_attIndex));
            //System.out.println("    Att QName: " + qn);
            return qn;
        }

        // On TEXT and ATTR
        public String getText()
        {
            assert _xmlStream.isStartElement() : "Not on Start Element.";
            return _xmlStream.getAttributeValue(_attIndex);
        }

        public String getText(int wsr)
        {
            assert _xmlStream.isStartElement() : "Not on Start Element.";
            return XmlWhitespace.collapse( _xmlStream.getAttributeValue(_attIndex), wsr );
        }

        public boolean textIsWhitespace()
        {
            throw new IllegalStateException();
        }

        public String getNamespaceForPrefix(String prefix)
        {
            assert _xmlStream.isStartElement() : "Not on Start Element.";
            return _xmlStream.getNamespaceURI(prefix);
        }

        private void setAttributeIndex(int attIndex)
        {
            _attIndex = attIndex;
        }
    }

    /**
     * This is used as implementation of Event for validating global attributes
     * and for pushing the buffered attributes
     */
    private static final class SimpleEventImpl
        implements ValidatorListener.Event
    {
        private String _text;
        private QName  _qname;
        private XMLStreamReader _xmlStream;

        private void setXMLStreamReader(XMLStreamReader xsr)
        {
            _xmlStream = xsr;
        }

        // should return null, getLocation will be used, used only to locate errors
        public XmlCursor getLocationAsCursor()
        { return null; }

        public javax.xml.stream.Location getLocation()
        {
            return _xmlStream.getLocation();
        }

        // fill up chars with the xsi:type attribute value if there is one othervise return false
        public String getXsiType() // BEGIN xsi:type
        { return null; }

        // fill up chars with xsi:nill attribute value if any
        public String getXsiNil() // BEGIN xsi:nil
        { return null; }

        // not used curently
        public String getXsiLoc() // BEGIN xsi:schemaLocation
        { return null; }

        // not used curently
        public String getXsiNoLoc() // BEGIN xsi:noNamespaceSchemaLocation
        { return null; }

        // On START and ATTR
        public QName getName()
        { return _qname; }

        // On TEXT and ATTR
        public String getText()
        {
            return _text;
        }

        public String getText(int wsr)
        {
            return XmlWhitespace.collapse( _text, wsr );
        }

        public boolean textIsWhitespace()
        { return false; }

        public String getNamespaceForPrefix(String prefix)
        {
            return _xmlStream.getNamespaceURI(prefix);
        }
    }

    /* public methods in XMLStreamReader */

    public Object getProperty(String s) throws IllegalArgumentException
    {
        return super.getProperty(s);
    }

    public int next() throws XMLStreamException
    {
        int evType = super.next();
        //debugEvent(evType);

        validate_event(evType);

        return evType;
    }

    private void validate_event(int evType)
    {
        if (_state==STATE_ERROR)
            return;

        if (_depth<0)
            throw new IllegalArgumentException("ValidatingXMLStreamReader cannot go further than the subtree is was initialized on.");

        switch(evType)
        {
        case XMLEvent.START_ELEMENT:
            _depth++;
            if (_state == STATE_ATTBUFFERING)
                pushBufferedAttributes();

            if (_validator==null)
            {
                // avoid construction of a new QName object after the bug in getName() is fixed.
                QName qname = new QName(getNamespaceURI(), getLocalName());

                if (_contentType==null)
                    _contentType = typeForGlobalElement(qname);

                if (_state==STATE_ERROR)
                    break;

                initValidator(_contentType);
                _validator.nextEvent(Validator.BEGIN, _elemEvent);
            }

            _validator.nextEvent(Validator.BEGIN, _elemEvent);

            int attCount = getAttributeCount();
            validate_attributes(attCount);

            break;

        case XMLEvent.ATTRIBUTE:
            if (getAttributeCount()==0)
                break;

            if (_state == STATE_FIRSTEVENT || _state == STATE_ATTBUFFERING)
            {
                // buffer all Attributes
                for (int i=0; i<getAttributeCount(); i++)
                {
                    // avoid construction of a new QName object after the bug in getName() is fixed.
                    QName qname = new QName(getAttributeNamespace(i), getAttributeLocalName(i));

                    if (qname.equals(XSI_TYPE))
                    {
                        String xsiTypeValue = getAttributeValue(i);
                        String uri = super.getNamespaceURI(QNameHelper.getPrefixPart(xsiTypeValue));
                        QName xsiTypeQname = new QName(uri, QNameHelper.getLocalPart(xsiTypeValue));
                        _xsiType = _stl.findType(xsiTypeQname);
                    }

                    if (_attNamesList==null)
                    {
                        _attNamesList = new ArrayList();
                        _attValuesList = new ArrayList();
                    }
                    // skip xsi:type xsi:nil xsi:schemaLocation xsi:noNamespaceSchemaLocation
                    if (isSpecialAttribute(qname))
                        continue;

                    _attNamesList.add(qname);
                    _attValuesList.add(getAttributeValue(i));
                }
                _state = STATE_ATTBUFFERING;
            }
            else
                throw new IllegalStateException("ATT event must be only at the beggining of the stream.");

            break;

        case XMLEvent.END_ELEMENT:
        case XMLEvent.END_DOCUMENT:
            _depth--;
            if (_state == STATE_ATTBUFFERING)
                pushBufferedAttributes();

            _validator.nextEvent(Validator.END, _elemEvent);
            break;

        case XMLEvent.CDATA:
        case XMLEvent.CHARACTERS:
            if (_state == STATE_ATTBUFFERING)
                pushBufferedAttributes();

            if (_validator==null)
            {
                if (_contentType==null)
                {
                    if (isWhiteSpace()) // hack/workaround for avoiding errors for parsers that do not generate XMLEvent.SPACE
                        break;

                    addError("No content type provided for validation of a content model.");
                    _state = STATE_ERROR;
                    break;
                }
                initValidator(_contentType);
                _validator.nextEvent(Validator.BEGIN, _simpleEvent);
            }

            _validator.nextEvent(Validator.TEXT, _elemEvent);
            break;

        case XMLEvent.START_DOCUMENT:
            _depth++;
            break;

        case XMLEvent.COMMENT:
        case XMLEvent.DTD:
        case XMLEvent.ENTITY_DECLARATION:
        case XMLEvent.ENTITY_REFERENCE:
        case XMLEvent.NAMESPACE:
        case XMLEvent.NOTATION_DECLARATION:
        case XMLEvent.PROCESSING_INSTRUCTION:
        case XMLEvent.SPACE:
            //ignore
            break;

        default:
            throw new IllegalStateException("Unknown event type.");
        }
    }

    private void pushBufferedAttributes()
    {
        SchemaType validationType = null;

        if (_xsiType!=null)
        {
            if (_contentType==null)
            {
                validationType = _xsiType;
            }
            else
            {
                // we have both _xsiType and _contentType
                if (_contentType.isAssignableFrom(_xsiType))
                {
                    validationType = _xsiType;
                }
                else
                {
                    addError("Specified type '" + _contentType +
                        "' not compatible with found xsi:type '" + _xsiType + "'.");
                    _state = STATE_ERROR;
                    return;
                }
            }
        }
        else
        {
            if (_contentType != null)
            {
                validationType = _contentType;
            }
            else if (_attNamesList!=null)
            {
                // no xsi:type, no _contentType
                // this is the global attribute case
                validationType = _stl.findAttributeType((QName)_attNamesList.get(0));
                if (validationType==null)
                {
                    addError("A schema global attribute with name '" + _attNamesList.get(0) +
                        "' could not be found in the current schema type loader.");
                    _state = STATE_ERROR;
                    return;
                }
                // if _attNamesList.size() > 1 than the validator will add an error
            }
            else
            {
                addError("No content type provided for validation of a content model.");
                _state = STATE_ERROR;
                return;
            }
        }

        // here validationType is the right type, start pushing all acumulated attributes
        initValidator(validationType);
        _validator.nextEvent(Validator.BEGIN, _simpleEvent);

        // validate attributes from _attNamesList
        validate_attributes(_attNamesList.size());
        _attNamesList = null;
        _attValuesList = null;

        _state = STATE_VALIDATING;
    }

    private boolean isSpecialAttribute(QName qn)
    {
        if (qn.getNamespaceURI().equals(URI_XSI))
            return qn.getLocalPart().equals(XSI_TYPE.getLocalPart()) ||
                qn.getLocalPart().equals(XSI_NIL.getLocalPart()) ||
                qn.getLocalPart().equals(XSI_SL.getLocalPart()) ||
                qn.getLocalPart().equals(XSI_NSL.getLocalPart());

        return false;
    }

    /**
     * Initializes the validator for the given schemaType
     * @param schemaType
     */
    private void initValidator(SchemaType schemaType)
    {
        assert schemaType!=null;

        _validator = new Validator(schemaType, null, _stl, _options, _errorListener);
    }

    private SchemaType typeForGlobalElement(QName qname)
    {
        assert qname!=null;

        SchemaType docType = _stl.findDocumentType(qname);

        if (docType==null)
        {
            addError("Schema document type not found for element '" + qname + "'.");
            _state = STATE_ERROR;
        }
        return docType;
    }

    private void addError(String msg)
    {
        String source = null;
        Location location = getLocation();

        if (location != null)
        {
            source = location.getPublicId();
            if (source==null)
                source = location.getSystemId();

            _errorListener.add(XmlError.forLocation(msg, source, location));
        }
        else
            _errorListener.add(XmlError.forMessage(msg));
    }

    protected void validate_attributes(int attCount)
    {
        for(int i=0; i<attCount; i++)
        {
            validate_attribute(i);
        }

        if (_options!=null && _options.hasOption(OPTION_ATTTRIBUTE_VALIDATION_COMPAT_MODE))
        {}
        else
            _validator.nextEvent(Validator.ENDATTRS, _simpleEvent);
    }

    protected void validate_attribute(int attIndex)
    {
        ValidatorListener.Event event;
        if (_attNamesList==null)
        {
            _attEvent.setAttributeIndex(attIndex);
            QName qn = _attEvent.getName();
            if (isSpecialAttribute(qn))
                return;

            event = _attEvent;
        }
        else
        {
            _simpleEvent._qname = (QName)_attNamesList.get(attIndex);
            _simpleEvent._text = (String)_attValuesList.get(attIndex);
            event = _simpleEvent;
        }

        _validator.nextEvent(Validator.ATTR, event);
    }

    /**
     * @return Returns the validation state up to this point.
     * NOTE: At least one START ELEMENT should have been consumed for a valid value to be returned.
     */
    public boolean isValid()
    {
        if ( _state==STATE_ERROR || _validator==null)
            return false;

        return _validator.isValid();
    }

//    /* for unit testing */
//    public static void main(String[] args) throws FileNotFoundException, XMLStreamException
//    {
//        ValidatingXMLStreamReader valXsr = new ValidatingXMLStreamReader();
//        for( int i = 0; i<args.length; i++)
//        {
//            validate(valXsr, args[i]);
//        }
//    }
//
//    private static void validate(ValidatingXMLStreamReader valXsr, String file)
//        throws XMLStreamException, FileNotFoundException
//    {
//        Collection errors = new ArrayList();
//        XMLStreamReader xsr = XMLInputFactory.newInstance().
//            createXMLStreamReader(new FileInputStream(new File(file)));
//        valXsr.init(xsr, null,
//            XmlBeans.typeLoaderForClassLoader(ValidatingXMLStreamReader.class.getClassLoader()),
//            null,
//            errors);
//
//        while( valXsr.hasNext() )
//        {
//            valXsr.next();
//        }
//
//        System.out.println("File '" + file + "' is: " + (valXsr.isValid() ? "Valid" : "INVALID") + "\t\t\t\t ----------");
//        for (Iterator i = errors.iterator(); i.hasNext(); )
//        {
//            XmlError err = (XmlError)i.next();
//            System.out.println("ERROR " + err.getSeverity() + " " + err.getLine() + ":" + err.getColumn() + " " +
//                err.getMessage() + " ");
//        }
//    }
//
//    private void debugEvent(int evType)
//    {
//        switch(evType)
//        {
//        case XMLEvent.START_ELEMENT:
//            System.out.println("SE     " + _elemEvent.getName());
//            break;
//        case XMLEvent.START_DOCUMENT:
//            System.out.println("SDoc");
//            break;
//        case XMLEvent.END_ELEMENT:
//            System.out.println("EE     " + _elemEvent.getName());
//            break;
//        case XMLEvent.END_DOCUMENT:
//            System.out.println("EDoc");
//            break;
//        case XMLEvent.SPACE:
//            System.out.println("SPACE");
//            break;
//        case XMLEvent.CDATA:
//            System.out.println("CDATA");
//            break;
//        case XMLEvent.CHARACTERS:
//            String c = _elemEvent.getText();
//            System.out.println("TEXT     " + c);
//            break;
//
//        case XMLEvent.ATTRIBUTE:      // global attributes
//            System.out.println("ATT     count: " + _elemEvent._xmlStream.getAttributeCount());
//            for(int i=0; i<_elemEvent._xmlStream.getAttributeCount(); i++)
//            {
//                System.out.println("\t\t" + _elemEvent._xmlStream.getAttributeNamespace(i) + ":" +
//                    _elemEvent._xmlStream.getAttributeLocalName(i) + "  =  " +
//                    _elemEvent._xmlStream.getAttributeValue(i));
//            }
//            break;
//        case XMLEvent.COMMENT:
//            System.out.println("COMMENT");
//            break;
//        case XMLEvent.DTD:
//            System.out.println("DTD");
//            break;
//        case XMLEvent.ENTITY_DECLARATION:
//            System.out.println("ENTITY_DECL");
//            break;
//        case XMLEvent.ENTITY_REFERENCE:
//            System.out.println("ENTITY_REF");
//            break;
//        case XMLEvent.NAMESPACE:
//            System.out.println("NS");
//            break;
//        case XMLEvent.NOTATION_DECLARATION:
//            System.out.println("NOTATION_DECL");
//            break;
//        case XMLEvent.PROCESSING_INSTRUCTION:
//            System.out.println("PI");
//            break;
//        }
//    }
}
