FileDocCategorySizeDatePackage
StAXStream2SAX.javaAPI DocJava SE 6 API17002Tue Jun 10 00:22:34 BST 2008com.sun.org.apache.xalan.internal.xsltc.trax

StAXStream2SAX.java

/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the "License").  You may not use this file except
 * in compliance with the License.
 *
 * You can obtain a copy of the license at
 * https://jaxp.dev.java.net/CDDLv1.0.html.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * HEADER in each file and include the License file at
 * https://jaxp.dev.java.net/CDDLv1.0.html
 * If applicable add the following below this CDDL HEADER
 * with the fields enclosed by brackets "[]" replaced with
 * your own identifying information: Portions Copyright
 * [year] [name of copyright owner]
 */

/*
 * $Id: StAXStream2SAX.java,v 1.7 2007/05/16 15:03:52 spericas Exp $
 * @(#)StAXStream2SAX.java	1.7 07/05/29
 *
 * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
 */

package com.sun.org.apache.xalan.internal.xsltc.trax;

import java.io.IOException;
import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;
import java.util.Iterator;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.ext.Locator2;
import org.xml.sax.helpers.AttributesImpl;
import com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl;



import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.Namespace;
import javax.xml.stream.events.ProcessingInstruction;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.StartDocument;
import javax.xml.stream.events.XMLEvent;



/**
 * @author Padmaja Vedula
 * @author Sunitha Reddy
 */
public class StAXStream2SAX implements XMLReader, Locator {

    //private final static String EMPTYSTRING = "";
    //private static final String XMLNS_PREFIX = "xmlns";
  
    // StAX Stream source
    private final XMLStreamReader staxStreamReader;
    
    //private Node _dom = null;
    private ContentHandler _sax = null;
    private LexicalHandler _lex = null;
    private SAXImpl _saxImpl = null;
    //private Hashtable _nsPrefixes = new Hashtable();
    
    public StAXStream2SAX(XMLStreamReader staxSrc) {
            staxStreamReader = staxSrc;
    }

    public ContentHandler getContentHandler() { 
	return _sax;
    }

    public void setContentHandler(ContentHandler handler) throws 
	NullPointerException 
    {
	_sax = handler;
	if (handler instanceof LexicalHandler) {
	    _lex = (LexicalHandler) handler;
	}
	
	if (handler instanceof SAXImpl) {
	    _saxImpl = (SAXImpl)handler;
	}
    }

    
    public void parse(InputSource unused) throws IOException, SAXException {
        try {
            bridge();
        } catch (XMLStreamException e) {
            throw new SAXException(e);
        }
    }


    //Main Work Starts Here.
    public void parse() throws IOException, SAXException, XMLStreamException {
        bridge();
    }

    
   /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public void parse(String sysId) throws IOException, SAXException {
	throw new IOException("This method is not yet implemented.");
    }
    

   public void bridge() throws XMLStreamException {

        try {
            // remembers the nest level of elements to know when we are done.
            int depth=0;

            // skip over START_DOCUMENT
            int event = staxStreamReader.getEventType();
            if (event == XMLStreamConstants.START_DOCUMENT) {
                event = staxStreamReader.next();
            }

            // If not a START_ELEMENT (e.g., a DTD), skip to next tag
            if (event != XMLStreamConstants.START_ELEMENT) {
                event = staxStreamReader.nextTag();
                // An error if a START_ELEMENT isn't found now
                if (event != XMLStreamConstants.START_ELEMENT) {
                    throw new IllegalStateException("The current event is " +
                            "not START_ELEMENT\n but" + event);
                }            
            }
                  
            handleStartDocument();

            do {
                // These are all of the events listed in the javadoc for
                // XMLEvent.
                // The spec only really describes 11 of them.
                switch (event) {
                    case XMLStreamConstants.START_ELEMENT :
                        depth++;
                        handleStartElement();
                        break;
                    case XMLStreamConstants.END_ELEMENT :
                        handleEndElement();
                        depth--;
                        break;
                    case XMLStreamConstants.CHARACTERS :
                        handleCharacters();
                        break;
                    case XMLStreamConstants.ENTITY_REFERENCE :
                        handleEntityReference();
                        break;
                    case XMLStreamConstants.PROCESSING_INSTRUCTION :
                        handlePI();
                        break;
                    case XMLStreamConstants.COMMENT :
                        handleComment();
                        break;
                    case XMLStreamConstants.DTD :
                        handleDTD();
                        break;
                    case XMLStreamConstants.ATTRIBUTE :
                        handleAttribute();
                        break;
                    case XMLStreamConstants.NAMESPACE :
                        handleNamespace();
                        break;
                    case XMLStreamConstants.CDATA :
                        handleCDATA();
                        break;
                    case XMLStreamConstants.ENTITY_DECLARATION :
                        handleEntityDecl();
                        break;
                    case XMLStreamConstants.NOTATION_DECLARATION :
                        handleNotationDecl();
                        break;
                    case XMLStreamConstants.SPACE :
                        handleSpace();
                        break;
                    default :
                        throw new InternalError("processing event: " + event);
                }
                
                event=staxStreamReader.next();
            } while (depth!=0);

            handleEndDocument();
        } catch (SAXException e) {
            throw new XMLStreamException(e);
        }
    }

    private void handleEndDocument() throws SAXException {
        _sax.endDocument();
    }

    private void handleStartDocument() throws SAXException {
        _sax.setDocumentLocator(new Locator2() {
            public int getColumnNumber() {
                return staxStreamReader.getLocation().getColumnNumber();
            }
            public int getLineNumber() {
                return staxStreamReader.getLocation().getLineNumber();
            }
            public String getPublicId() {
                return staxStreamReader.getLocation().getPublicId();
            }
            public String getSystemId() {
                return staxStreamReader.getLocation().getSystemId();
            }
            public String getXMLVersion() {
                return staxStreamReader.getVersion();
            }
            public String getEncoding() {
                return staxStreamReader.getEncoding();
            }
         });
        _sax.startDocument();
    }

    private void handlePI() throws XMLStreamException {
        try {
            _sax.processingInstruction(
                staxStreamReader.getPITarget(),
                staxStreamReader.getPIData());
        } catch (SAXException e) {
            throw new XMLStreamException(e);
        }
    }

    private void handleCharacters() throws XMLStreamException {

        // workaround for bugid 5046319 - switch over to commented section
        // below when it is fixed.
        int textLength = staxStreamReader.getTextLength();
        char[] chars = new char[textLength];

        staxStreamReader.getTextCharacters(0, chars, 0, textLength);

        try {
            _sax.characters(chars, 0, chars.length);
        } catch (SAXException e) {
            throw new XMLStreamException(e);
        }

        
//        int start = 0;
//        int len;
//        do {
//            len = staxStreamReader.getTextCharacters(start, buf, 0, buf.length);
//            start += len;
//            try {
//                _sax.characters(buf, 0, len);
//            } catch (SAXException e) {
//                throw new XMLStreamException(e);
//            }
//        } while (len == buf.length);
    }

    private void handleEndElement() throws XMLStreamException {
        QName qName = staxStreamReader.getName();

        try {
            //construct prefix:localName from qName
            String qname = "";
            if (qName.getPrefix() != null && qName.getPrefix().trim().length() != 0){
                qname = qName.getPrefix() + ":";
            }
            qname += qName.getLocalPart();
            
            // fire endElement
            _sax.endElement(
                qName.getNamespaceURI(),
                qName.getLocalPart(),
                qname); 

            // end namespace bindings
            int nsCount = staxStreamReader.getNamespaceCount();
            for (int i = nsCount - 1; i >= 0; i--) {
                String prefix = staxStreamReader.getNamespacePrefix(i);
                if (prefix == null) { // true for default namespace
                    prefix = "";
                }
                _sax.endPrefixMapping(prefix);
            }
        } catch (SAXException e) {
            throw new XMLStreamException(e);
        }
    }

    private void handleStartElement() throws XMLStreamException {

        try {
            // start namespace bindings
            int nsCount = staxStreamReader.getNamespaceCount();
            for (int i = 0; i < nsCount; i++) {
                String prefix = staxStreamReader.getNamespacePrefix(i);
                if (prefix == null) { // true for default namespace
                    prefix = "";
                }
                _sax.startPrefixMapping(
                    prefix,
                    staxStreamReader.getNamespaceURI(i));
            }

            // fire startElement
            QName qName = staxStreamReader.getName();
            String prefix = qName.getPrefix();
            String rawname;
            if(prefix==null || prefix.length()==0)
                rawname = qName.getLocalPart();
            else
                rawname = prefix + ':' + qName.getLocalPart();
            Attributes attrs = getAttributes();
            _sax.startElement(
                qName.getNamespaceURI(),
                qName.getLocalPart(),
                rawname,
                attrs);
        } catch (SAXException e) {
            throw new XMLStreamException(e);
        }
    }

    /**
     * Get the attributes associated with the given START_ELEMENT or ATTRIBUTE
     * StAXevent.
     * 
     * @return the StAX attributes converted to an org.xml.sax.Attributes
     */
    private Attributes getAttributes() {
        AttributesImpl attrs = new AttributesImpl();

        int eventType = staxStreamReader.getEventType();
        if (eventType != XMLStreamConstants.ATTRIBUTE
            && eventType != XMLStreamConstants.START_ELEMENT) {
            throw new InternalError(
                "getAttributes() attempting to process: " + eventType);
        }
        
        // in SAX, namespace declarations are not part of attributes by default.
        // (there's a property to control that, but as far as we are concerned
        // we don't use it.) So don't add xmlns:* to attributes.

        // gather non-namespace attrs
        for (int i = 0; i < staxStreamReader.getAttributeCount(); i++) {
            String uri = staxStreamReader.getAttributeNamespace(i);
            if(uri==null)   uri="";
            String localName = staxStreamReader.getAttributeLocalName(i);
            String prefix = staxStreamReader.getAttributePrefix(i);
            String qName;
            if(prefix==null || prefix.length()==0)
                qName = localName;
            else
                qName = prefix + ':' + localName;
            String type = staxStreamReader.getAttributeType(i);
            String value = staxStreamReader.getAttributeValue(i);

            attrs.addAttribute(uri, localName, qName, type, value);
        }

        return attrs;
    }

    private void handleNamespace() {
        // no-op ???
        // namespace events don't normally occur outside of a startElement
        // or endElement
    }

    private void handleAttribute() {
        // no-op ???
        // attribute events don't normally occur outside of a startElement
        // or endElement
    }

    private void handleDTD() {
        // no-op ???
        // it seems like we need to pass this info along, but how?
    }

    private void handleComment() {
        // no-op ???
    }

    private void handleEntityReference() {
        // no-op ???
    }

    private void handleSpace() {
        // no-op ???
        // this event is listed in the javadoc, but not in the spec.
    }

    private void handleNotationDecl() {
        // no-op ???
        // this event is listed in the javadoc, but not in the spec.
    }

    private void handleEntityDecl() {
        // no-op ???
        // this event is listed in the javadoc, but not in the spec.
    }

    private void handleCDATA() {
        // no-op ???
        // this event is listed in the javadoc, but not in the spec.
    }
    
    
    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public DTDHandler getDTDHandler() { 
	return null;
    }

    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public ErrorHandler getErrorHandler() {
	return null;
    }

    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public boolean getFeature(String name) throws SAXNotRecognizedException,
	SAXNotSupportedException
    {
	return false;
    }

    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public void setFeature(String name, boolean value) throws 
	SAXNotRecognizedException, SAXNotSupportedException 
    {
    }

    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public void setDTDHandler(DTDHandler handler) throws NullPointerException {
    }

    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public void setEntityResolver(EntityResolver resolver) throws 
	NullPointerException 
    {
    }

    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public EntityResolver getEntityResolver() {
	return null;
    }

    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public void setErrorHandler(ErrorHandler handler) throws 
	NullPointerException
    {
    }

    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public void setProperty(String name, Object value) throws
	SAXNotRecognizedException, SAXNotSupportedException {
    }

    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public Object getProperty(String name) throws SAXNotRecognizedException,
	SAXNotSupportedException
    {
	return null;
    }
    
    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public int getColumnNumber() { 
	return 0; 
    }
    
    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public int getLineNumber() { 
	return 0; 
    }

    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public String getPublicId() { 
	return null; 
    }

    /**
     * This class is only used internally so this method should never 
     * be called.
     */
    public String getSystemId() { 
	return null; 
    }  
    
}