/*
 * 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.
 */
/*
 * $Id: ToUnknownStream.java 471981 2006-11-07 04:28:00Z minchau $
 */
package org.apache.xml.serializer;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.Properties;
import java.util.Vector;

import javax.xml.transform.SourceLocator;
import javax.xml.transform.Transformer;

import org.w3c.dom.Node;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;


/**
 *This class wraps another SerializationHandler. The wrapped object will either
 * handler XML or HTML, which is not known until a little later when the first XML
 * tag is seen.  If the first tag is <html> then the wrapped object is an HTML
 * handler, otherwise it is an XML handler.
 *
 * This class effectively caches the first few calls to it then passes them
 * on to the wrapped handler (once it exists).  After that subsequent calls a
 * simply passed directly to the wrapped handler.
 *
 * The user of this class doesn't know if the output is ultimatley XML or HTML.
 * 
 * This class is not a public API, it is public because it is used within Xalan.
 * @xsl.usage internal
 */
public final class ToUnknownStream extends SerializerBase
{

    /**
     * The wrapped handler, initially XML but possibly switched to HTML
     */
    private SerializationHandler m_handler;

    /**
     * A String with no characters
     */
    private static final String EMPTYSTRING = "";

    /**
     * true if the underlying handler (XML or HTML) is fully initialized
     */
    private boolean m_wrapped_handler_not_initialized = false;


    /**
     * the prefix of the very first tag in the document
     */
    private String m_firstElementPrefix;
    /**
     * the element name (including any prefix) of the very first tag in the document
     */
    private String m_firstElementName;

    /**
     * the namespace URI associated with the first element
     */
    private String m_firstElementURI;
    
    /**
     * the local name (no prefix) associated with the first element
     */
    private String m_firstElementLocalName = null;

    /**
     * true if the first tag has been emitted to the wrapped handler
     */
    private boolean m_firstTagNotEmitted = true;

    /**
     * A collection of namespace URI's (only for first element).
     * _namespacePrefix has the matching prefix for these URI's
     */
    private Vector m_namespaceURI = null;
    /**
     * A collection of namespace Prefix (only for first element)
     * _namespaceURI has the matching URIs for these prefix'
     */
    private Vector m_namespacePrefix = null;

    /**
     * true if startDocument() was called before the underlying handler
     * was initialized
     */
    private boolean m_needToCallStartDocument = false;
    /**
     * true if setVersion() was called before the underlying handler
     * was initialized
     */
    private boolean m_setVersion_called = false;
    /**
     * true if setDoctypeSystem() was called before the underlying handler
     * was initialized
     */
    private boolean m_setDoctypeSystem_called = false;
    /**
     * true if setDoctypePublic() was called before the underlying handler
     * was initialized
     */
    private boolean m_setDoctypePublic_called = false;
    /**
     * true if setMediaType() was called before the underlying handler
     * was initialized
     */
    private boolean m_setMediaType_called = false;

    /**
     * Default constructor.
     * Initially this object wraps an XML Stream object, so _handler is never null.
     * That may change later to an HTML Stream object.
     */
    public ToUnknownStream()
    {
        m_handler = new ToXMLStream();
    }

    /**
     * @see Serializer#asContentHandler()
     * @return the wrapped XML or HTML handler
     */
    public ContentHandler asContentHandler() throws IOException
    {
        /* don't return the real handler ( m_handler ) because
         * that would expose the real handler to the outside.
         * Keep m_handler private so it can be internally swapped
         * to an HTML handler.
         */
        return this;
    }

    /**
     * @see SerializationHandler#close()
     */
    public void close()
    {
        m_handler.close();
    }

    /**
     * @see Serializer#getOutputFormat()
     * @return the properties of the underlying handler
     */
    public Properties getOutputFormat()
    {
        return m_handler.getOutputFormat();
    }

    /**
     * @see Serializer#getOutputStream()
     * @return the OutputStream of the underlying XML or HTML handler
     */
    public OutputStream getOutputStream()
    {
        return m_handler.getOutputStream();
    }

    /**
     * @see Serializer#getWriter()
     * @return the Writer of the underlying XML or HTML handler
     */
    public Writer getWriter()
    {
        return m_handler.getWriter();
    }

    /**
     * passes the call on to the underlying HTML or XML handler
     * @see Serializer#reset()
     * @return ???
     */
    public boolean reset()
    {
        return m_handler.reset();
    }

    /**
     * Converts the DOM node to output
     * @param node the DOM node to transform to output
     * @see DOMSerializer#serialize(Node)
     *
     */
    public void serialize(Node node) throws IOException
    {
        if (m_firstTagNotEmitted)
        {
            flush();
        }
        m_handler.serialize(node);
    }

    /**
     * @see SerializationHandler#setEscaping(boolean)
     */
    public boolean setEscaping(boolean escape) throws SAXException
    {
        return m_handler.setEscaping(escape);
    }

    /**
     * Set the properties of the handler
     * @param format the output properties to set
     * @see Serializer#setOutputFormat(Properties)
     */
    public void setOutputFormat(Properties format)
    {
        m_handler.setOutputFormat(format);
    }

    /**
     * Sets the output stream to write to
     * @param output the OutputStream to write to
     * @see Serializer#setOutputStream(OutputStream)
     */
    public void setOutputStream(OutputStream output)
    {
        m_handler.setOutputStream(output);
    }

    /**
     * Sets the writer to write to
     * @param writer the writer to write to
     * @see Serializer#setWriter(Writer)
     */
    public void setWriter(Writer writer)
    {
        m_handler.setWriter(writer);
    }

    /**
     * Adds an attribute to the currenly open tag
     * @param uri the URI of a namespace
     * @param localName the attribute name, without prefix
     * @param rawName the attribute name, with prefix (if any)
     * @param type the type of the attribute, typically "CDATA"
     * @param value the value of the parameter
     * @param XSLAttribute true if this attribute is coming from an xsl:attribute element
     * @see ExtendedContentHandler#addAttribute(String, String, String, String, String)
     */
    public void addAttribute(
        String uri,
        String localName,
        String rawName,
        String type,
        String value,
        boolean XSLAttribute)
        throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            flush();
        }
        m_handler.addAttribute(uri, localName, rawName, type, value, XSLAttribute);
    }
    /**
     * Adds an attribute to the currenly open tag
     * @param rawName the attribute name, with prefix (if any)
     * @param value the value of the parameter
     * @see ExtendedContentHandler#addAttribute(String, String)
     */
    public void addAttribute(String rawName, String value)
    {
        if (m_firstTagNotEmitted)
        {
            flush();
        }
        m_handler.addAttribute(rawName, value);
 
    }

    /**
     * Adds a unique attribute to the currenly open tag
     */
    public void addUniqueAttribute(String rawName, String value, int flags)
        throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            flush();
        }
        m_handler.addUniqueAttribute(rawName, value, flags);
 
    }

    /**
     * Converts the String to a character array and calls the SAX method 
     * characters(char[],int,int);
     * 
     * @see ExtendedContentHandler#characters(String)
     */
    public void characters(String chars) throws SAXException
    {
        final int length = chars.length();
        if (length > m_charsBuff.length)
        {
            m_charsBuff = new char[length*2 + 1];
        }
        chars.getChars(0, length, m_charsBuff, 0);
        this.characters(m_charsBuff, 0, length);  
    }    

    /**
     * Pass the call on to the underlying handler
     * @see ExtendedContentHandler#endElement(String)
     */
    public void endElement(String elementName) throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            flush();
        }
        m_handler.endElement(elementName);
    }


    /**
     * @see org.xml.sax.ContentHandler#startPrefixMapping(String, String)
     * @param prefix The prefix that maps to the URI
     * @param uri The URI for the namespace
     */
    public void startPrefixMapping(String prefix, String uri) throws SAXException
    {
        this.startPrefixMapping(prefix,uri, true);
    }

    /**
     * This method is used when a prefix/uri namespace mapping
     * is indicated after the element was started with a
     * startElement() and before and endElement().
     * startPrefixMapping(prefix,uri) would be used before the
     * startElement() call.
     * @param uri the URI of the namespace
     * @param prefix the prefix associated with the given URI.
     *
     * @see ExtendedContentHandler#namespaceAfterStartElement(String, String)
     */    
    public void namespaceAfterStartElement(String prefix, String uri)
        throws SAXException 
    {  
        // hack for XSLTC with finding URI for default namespace
        if (m_firstTagNotEmitted && m_firstElementURI == null && m_firstElementName != null)
        {
            String prefix1 = getPrefixPart(m_firstElementName);
            if (prefix1 == null && EMPTYSTRING.equals(prefix))
            {
                // the elements URI is not known yet, and it
                // doesn't have a prefix, and we are currently
                // setting the uri for prefix "", so we have
                // the uri for the element... lets remember it
                m_firstElementURI = uri;
            }
        }         
        startPrefixMapping(prefix,uri, false);          
    }
    
    public boolean startPrefixMapping(String prefix, String uri, boolean shouldFlush)
        throws SAXException
    {
        boolean pushed = false;
        if (m_firstTagNotEmitted)
        {
            if (m_firstElementName != null && shouldFlush)
            {
                /* we've already seen a startElement, and this is a prefix mapping
                 * for the up coming element, so flush the old element
                 * then send this event on its way.
                 */
                flush();
                pushed = m_handler.startPrefixMapping(prefix, uri, shouldFlush);
            } 
            else 
            {           
                if (m_namespacePrefix == null)
                {
                    m_namespacePrefix = new Vector();
                    m_namespaceURI = new Vector();
                }
                m_namespacePrefix.addElement(prefix);
                m_namespaceURI.addElement(uri);
            
                if (m_firstElementURI == null)
                {
                    if (prefix.equals(m_firstElementPrefix))
                        m_firstElementURI = uri;
                }
            }

        }
        else
        {
           pushed = m_handler.startPrefixMapping(prefix, uri, shouldFlush);
        }
        return pushed;
    }

    /**
      * This method cannot be cached because default is different in
      * HTML and XML (we need more than a boolean).
      */

    public void setVersion(String version)
    {
        m_handler.setVersion(version);

        // Cache call to setVersion()
        //       super.setVersion(version);
        m_setVersion_called = true;
    }

    /**
     * @see org.xml.sax.ContentHandler#startDocument()
     */
    public void startDocument() throws SAXException
    {
        m_needToCallStartDocument = true;
    }

 
    
    public void startElement(String qName) throws SAXException
    {
        this.startElement(null, null, qName, null);
    }
    
    public void startElement(String namespaceURI, String localName, String qName) throws SAXException
    {
        this.startElement(namespaceURI, localName, qName, null);
    }

    public void startElement(
        String namespaceURI,
        String localName,
        String elementName,
        Attributes atts) throws SAXException
    {
        /* we are notified of the start of an element */
        if (m_firstTagNotEmitted)
        {
            /* we have not yet sent the first element on its way */
            if (m_firstElementName != null) 
            {
                /* this is not the first element, but a later one.
                 * But we have the old element pending, so flush it out,
                 * then send this one on its way. 
                 */
                flush();
                m_handler.startElement(namespaceURI, localName, elementName,  atts);                
            }
            else
            {
                /* this is the very first element that we have seen, 
                 * so save it for flushing later.  We may yet get to know its
                 * URI due to added attributes.
                 */
                 
                m_wrapped_handler_not_initialized = true;
                m_firstElementName = elementName;
                
                // null if not known
                m_firstElementPrefix = getPrefixPartUnknown(elementName);
                
                // null if not known
                m_firstElementURI = namespaceURI;
                
                // null if not known
                m_firstElementLocalName = localName;

                if (m_tracer != null)
                    firePseudoElement(elementName);
                    
                /* we don't want to call our own addAttributes, which
                 * merely delegates to the wrapped handler, but we want to
                 * add these attributes to m_attributes. So me must call super.
                 * addAttributes() In this case m_attributes is only used for the
                 * first element, after that this class totally delegates to the
                 * wrapped handler which is either XML or HTML.
                 */
                if (atts != null)   
                    super.addAttributes(atts);
                
                // if there are attributes, then lets make the flush()
                // call the startElement on the handler and send the
                // attributes on their way.
                if (atts != null)   
                    flush();
                
            }
        }
        else
        {
            // this is not the first element, but a later one, so just
            // send it on its way.
            m_handler.startElement(namespaceURI, localName, elementName,  atts);
        }
    }

    /**
     * Pass the call on to the underlying handler
     * @see ExtendedLexicalHandler#comment(String)
     */
    public void comment(String comment) throws SAXException
    {
        if (m_firstTagNotEmitted && m_firstElementName != null)
        {
            emitFirstTag();
        }
        else if (m_needToCallStartDocument)
        {
            m_handler.startDocument();
            m_needToCallStartDocument = false;
        }

        m_handler.comment(comment);
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#getDoctypePublic()
     */
    public String getDoctypePublic()
    {

        return m_handler.getDoctypePublic();
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#getDoctypeSystem()
     */
    public String getDoctypeSystem()
    {
        return m_handler.getDoctypeSystem();
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#getEncoding()
     */
    public String getEncoding()
    {
        return m_handler.getEncoding();
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#getIndent()
     */
    public boolean getIndent()
    {
        return m_handler.getIndent();
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#getIndentAmount()
     */
    public int getIndentAmount()
    {
        return m_handler.getIndentAmount();
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#getMediaType()
     */
    public String getMediaType()
    {
        return m_handler.getMediaType();
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#getOmitXMLDeclaration()
     */
    public boolean getOmitXMLDeclaration()
    {
        return m_handler.getOmitXMLDeclaration();
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#getStandalone()
     */
    public String getStandalone()
    {
        return m_handler.getStandalone();
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#getVersion()
     */
    public String getVersion()
    {
        return m_handler.getVersion();
    }

    /**
     * @see XSLOutputAttributes#setDoctype(String, String)
     */
    public void setDoctype(String system, String pub)
    {
        m_handler.setDoctypePublic(pub);
        m_handler.setDoctypeSystem(system);
    }

    /**
     * Set the doctype in the underlying XML handler. Remember that this method
     * was called, just in case we need to transfer this doctype to an HTML handler
     * @param doctype the public doctype to set
     * @see XSLOutputAttributes#setDoctypePublic(String)
     */
    public void setDoctypePublic(String doctype)
    {
        m_handler.setDoctypePublic(doctype);
        m_setDoctypePublic_called = true;
    }

    /**
     * Set the doctype in the underlying XML handler. Remember that this method
     * was called, just in case we need to transfer this doctype to an HTML handler
     * @param doctype the system doctype to set
     * @see XSLOutputAttributes#setDoctypeSystem(String)
     */
    public void setDoctypeSystem(String doctype)
    {
        m_handler.setDoctypeSystem(doctype);
        m_setDoctypeSystem_called = true;
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#setEncoding(String)
     */
    public void setEncoding(String encoding)
    {
        m_handler.setEncoding(encoding);
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#setIndent(boolean)
     */
    public void setIndent(boolean indent)
    {
        m_handler.setIndent(indent);
    }

    /**
     * Pass the call on to the underlying handler
     */
    public void setIndentAmount(int value)
    {
        m_handler.setIndentAmount(value);
    }

    /**
     * @see XSLOutputAttributes#setMediaType(String)
     */
    public void setMediaType(String mediaType)
    {
        m_handler.setMediaType(mediaType);
        m_setMediaType_called = true;
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#setOmitXMLDeclaration(boolean)
     */
    public void setOmitXMLDeclaration(boolean b)
    {
        m_handler.setOmitXMLDeclaration(b);
    }

    /**
     * Pass the call on to the underlying handler
     * @see XSLOutputAttributes#setStandalone(String)
     */
    public void setStandalone(String standalone)
    {
        m_handler.setStandalone(standalone);
    }

    /**
     * @see XSLOutputAttributes#setVersion(String)
     */

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ext.DeclHandler#attributeDecl(String, String, String, String, String)
     */
    public void attributeDecl(
        String arg0,
        String arg1,
        String arg2,
        String arg3,
        String arg4)
        throws SAXException
    {
        m_handler.attributeDecl(arg0, arg1, arg2, arg3, arg4);
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ext.DeclHandler#elementDecl(String, String)
     */
    public void elementDecl(String arg0, String arg1) throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            emitFirstTag();
        }
        m_handler.elementDecl(arg0, arg1);
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ext.DeclHandler#externalEntityDecl(String, String, String)
     */
    public void externalEntityDecl(
        String name,
        String publicId,
        String systemId)
        throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            flush();
        }
        m_handler.externalEntityDecl(name, publicId, systemId);
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ext.DeclHandler#internalEntityDecl(String, String)
     */
    public void internalEntityDecl(String arg0, String arg1)
        throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            flush();
        }
        m_handler.internalEntityDecl(arg0, arg1);
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ContentHandler#characters(char[], int, int)
     */
    public void characters(char[] characters, int offset, int length)
        throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            flush();
        }

        m_handler.characters(characters, offset, length);

    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ContentHandler#endDocument()
     */
    public void endDocument() throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            flush();
        }

        m_handler.endDocument();
        
    
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ContentHandler#endElement(String, String, String)
     */
    public void endElement(String namespaceURI, String localName, String qName)
        throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            flush();
            if (namespaceURI == null && m_firstElementURI != null)
                namespaceURI = m_firstElementURI;


            if (localName == null && m_firstElementLocalName != null)
                localName = m_firstElementLocalName;
        }
        
        m_handler.endElement(namespaceURI, localName, qName);
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ContentHandler#endPrefixMapping(String)
     */
    public void endPrefixMapping(String prefix) throws SAXException
    {
        m_handler.endPrefixMapping(prefix);
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
     */
    public void ignorableWhitespace(char[] ch, int start, int length)
        throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            flush();
        }
        m_handler.ignorableWhitespace(ch, start, length);
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ContentHandler#processingInstruction(String, String)
     */
    public void processingInstruction(String target, String data)
        throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            flush();
        }

        m_handler.processingInstruction(target, data);
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ContentHandler#setDocumentLocator(Locator)
     */
    public void setDocumentLocator(Locator locator)
    {
        m_handler.setDocumentLocator(locator);
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ContentHandler#skippedEntity(String)
     */
    public void skippedEntity(String name) throws SAXException
    {
        m_handler.skippedEntity(name);
    }



    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ext.LexicalHandler#comment(char[], int, int)
     */
    public void comment(char[] ch, int start, int length) throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            flush();
        }

        m_handler.comment(ch, start, length);
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ext.LexicalHandler#endCDATA()
     */
    public void endCDATA() throws SAXException
    {

        m_handler.endCDATA();
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ext.LexicalHandler#endDTD()
     */
    public void endDTD() throws SAXException
    {

        m_handler.endDTD();
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ext.LexicalHandler#endEntity(String)
     */
    public void endEntity(String name) throws SAXException
    {
        if (m_firstTagNotEmitted)
        {
            emitFirstTag();
        }
        m_handler.endEntity(name);
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ext.LexicalHandler#startCDATA()
     */
    public void startCDATA() throws SAXException
    {
        m_handler.startCDATA();
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ext.LexicalHandler#startDTD(String, String, String)
     */
    public void startDTD(String name, String publicId, String systemId)
        throws SAXException
    {
        m_handler.startDTD(name, publicId, systemId);
    }

    /**
     * Pass the call on to the underlying handler
     * @see org.xml.sax.ext.LexicalHandler#startEntity(String)
     */
    public void startEntity(String name) throws SAXException
    {
        m_handler.startEntity(name);
    }

    /**
     * Initialize the wrapped output stream (XML or HTML).
     * If the stream handler should be HTML, then replace the XML handler with
     * an HTML handler. After than send the starting method calls that were cached
     * to the wrapped handler.
     *
     */
    private void initStreamOutput() throws SAXException
    {

        // Try to rule out if this is an not to be an HTML document based on prefix
        boolean firstElementIsHTML = isFirstElemHTML();

        if (firstElementIsHTML)
        {
            // create an HTML output handler, and initialize it

            // keep a reference to the old handler, ... it will soon be gone
            SerializationHandler oldHandler = m_handler;

            /* We have to make sure we get an output properties with the proper
             * defaults for the HTML method.  The easiest way to do this is to
             * have the OutputProperties class do it.
             */

            Properties htmlProperties =
                OutputPropertiesFactory.getDefaultMethodProperties(Method.HTML);
            Serializer serializer =
                SerializerFactory.getSerializer(htmlProperties);

            // The factory should be returning a ToStream
            // Don't know what to do if it doesn't
            // i.e. the user has over-ridden the content-handler property
            // for html
            m_handler = (SerializationHandler) serializer;
            //m_handler = new ToHTMLStream();

            Writer writer = oldHandler.getWriter();

            if (null != writer)
                m_handler.setWriter(writer);
            else
            {
                OutputStream os = oldHandler.getOutputStream();

                if (null != os)
                    m_handler.setOutputStream(os);
            }

            // need to copy things from the old handler to the new one here

            //            if (_setVersion_called)
            //            {
            m_handler.setVersion(oldHandler.getVersion());
            //            }
            //            if (_setDoctypeSystem_called)
            //            {
            m_handler.setDoctypeSystem(oldHandler.getDoctypeSystem());
            //            }
            //            if (_setDoctypePublic_called)
            //            {
            m_handler.setDoctypePublic(oldHandler.getDoctypePublic());
            //            }
            //            if (_setMediaType_called)
            //            {
            m_handler.setMediaType(oldHandler.getMediaType());
            //            }
            
            m_handler.setTransformer(oldHandler.getTransformer());
        }

        /* Now that we have a real wrapped handler (XML or HTML) lets
         * pass any cached calls to it
         */
        // Call startDocument() if necessary
        if (m_needToCallStartDocument)
        {
            m_handler.startDocument();
            m_needToCallStartDocument = false;
        }

        // the wrapped handler is now fully initialized
        m_wrapped_handler_not_initialized = false;
    }

    private void emitFirstTag() throws SAXException
    {   
        if (m_firstElementName != null)
        {
            if (m_wrapped_handler_not_initialized)
            {
                initStreamOutput();
                m_wrapped_handler_not_initialized = false;
            }
            // Output first tag
            m_handler.startElement(m_firstElementURI, null, m_firstElementName, m_attributes);
            // don't need the collected attributes of the first element anymore.
            m_attributes = null;

            // Output namespaces of first tag
            if (m_namespacePrefix != null)
            {
                final int n = m_namespacePrefix.size();
                for (int i = 0; i < n; i++)
                {
                    final String prefix =
                        (String) m_namespacePrefix.elementAt(i);
                    final String uri = (String) m_namespaceURI.elementAt(i);
                    m_handler.startPrefixMapping(prefix, uri, false);
                }
                m_namespacePrefix = null;
                m_namespaceURI = null;
            }
            m_firstTagNotEmitted = false;
        }
    }

    /**
     * Utility function for calls to local-name().
     *
     * Don't want to override static function on SerializerBase
     * So added Unknown suffix to method name.
     */
    private String getLocalNameUnknown(String value)
    {
        int idx = value.lastIndexOf(':');
        if (idx >= 0)
            value = value.substring(idx + 1);
        idx = value.lastIndexOf('@');
        if (idx >= 0)
            value = value.substring(idx + 1);
        return (value);
    }

    /**
         * Utility function to return prefix
         *
         * Don't want to override static function on SerializerBase
         * So added Unknown suffix to method name.
         */
    private String getPrefixPartUnknown(String qname)
    {
        final int index = qname.indexOf(':');
        return (index > 0) ? qname.substring(0, index) : EMPTYSTRING;
    }

    /**
     * Determine if the firts element in the document is <html> or <HTML>
     * This uses the cached first element name, first element prefix and the
     * cached namespaces from previous method calls
     *
     * @return true if the first element is an opening <html> tag
     */
    private boolean isFirstElemHTML()
    {
        boolean isHTML;

        // is the first tag html, not considering the prefix ?
        isHTML =
            getLocalNameUnknown(m_firstElementName).equalsIgnoreCase("html");

        // Try to rule out if this is not to be an HTML document based on URI
        if (isHTML
            && m_firstElementURI != null
            && !EMPTYSTRING.equals(m_firstElementURI))
        {
            // the <html> element has a non-trivial namespace
            isHTML = false;
        }
        // Try to rule out if this is an not to be an HTML document based on prefix
        if (isHTML && m_namespacePrefix != null)
        {
            /* the first element has a name of "html", but lets check the prefix.
             * If the prefix points to a namespace with a URL that is not ""
             * then the doecument doesn't start with an <html> tag, and isn't html
             */
            final int max = m_namespacePrefix.size();
            for (int i = 0; i < max; i++)
            {
                final String prefix = (String) m_namespacePrefix.elementAt(i);
                final String uri = (String) m_namespaceURI.elementAt(i);

                if (m_firstElementPrefix != null
                    && m_firstElementPrefix.equals(prefix)
                    && !EMPTYSTRING.equals(uri))
                {
                    // The first element has a prefix, so it can't be <html>
                    isHTML = false;
                    break;
                }
            }

        }
        return isHTML;
    }
    /**
     * @see Serializer#asDOMSerializer()
     */
    public DOMSerializer asDOMSerializer() throws IOException
    {
        return m_handler.asDOMSerializer();
    }

    /**
     * @param URI_and_localNames Vector a list of pairs of URI/localName
     * specified in the cdata-section-elements attribute.
     * @see SerializationHandler#setCdataSectionElements(java.util.Vector)
     */
    public void setCdataSectionElements(Vector URI_and_localNames)
    {
        m_handler.setCdataSectionElements(URI_and_localNames);
    }
    /**
     * @see ExtendedContentHandler#addAttributes(org.xml.sax.Attributes)
     */
    public void addAttributes(Attributes atts) throws SAXException
    {
        m_handler.addAttributes(atts);
    }

    /**
     * Get the current namespace mappings.
     * Simply returns the mappings of the wrapped handler.
     * @see ExtendedContentHandler#getNamespaceMappings()
     */
    public NamespaceMappings getNamespaceMappings()
    {
        NamespaceMappings mappings = null;
        if (m_handler != null)
        {
            mappings = m_handler.getNamespaceMappings();
        }
        return mappings;
    }
    /**
     * @see SerializationHandler#flushPending()
     */
    public void flushPending() throws SAXException
    {
 
        flush();
      
        m_handler.flushPending();
    }
    
    private void flush()
    {
        try
        {
        if (m_firstTagNotEmitted)
        {
            emitFirstTag();
        }
        if (m_needToCallStartDocument)
        {
            m_handler.startDocument();
            m_needToCallStartDocument = false;
        }
        }
        catch(SAXException e)
        {
            throw new RuntimeException(e.toString());
        }
          
    
    }

    /**
     * @see ExtendedContentHandler#getPrefix
     */
    public String getPrefix(String namespaceURI)
    {
        return m_handler.getPrefix(namespaceURI);
    }
    /**
     * @see ExtendedContentHandler#entityReference(java.lang.String)
     */
    public void entityReference(String entityName) throws SAXException
    {
        m_handler.entityReference(entityName);
    }

    /**
     * @see ExtendedContentHandler#getNamespaceURI(java.lang.String, boolean)
     */
    public String getNamespaceURI(String qname, boolean isElement)
    {
        return m_handler.getNamespaceURI(qname, isElement);
    }

    public String getNamespaceURIFromPrefix(String prefix)
    {
        return m_handler.getNamespaceURIFromPrefix(prefix);
    }

    public void setTransformer(Transformer t)
    {       
        m_handler.setTransformer(t);
        if ((t instanceof SerializerTrace) &&
            (((SerializerTrace) t).hasTraceListeners())) {
           m_tracer = (SerializerTrace) t;
        } else {
           m_tracer = null;
        }        
    }
    public Transformer getTransformer()
    {
        return m_handler.getTransformer();
    }

    /**
     * @see SerializationHandler#setContentHandler(org.xml.sax.ContentHandler)
     */
    public void setContentHandler(ContentHandler ch)
    {
        m_handler.setContentHandler(ch);
    }
    /**
     * This method is used to set the source locator, which might be used to
     * generated an error message.
     * @param locator the source locator
     *
     * @see ExtendedContentHandler#setSourceLocator(javax.xml.transform.SourceLocator)
     */    
    public void setSourceLocator(SourceLocator locator)
    {
        m_handler.setSourceLocator(locator);
    }

    protected void firePseudoElement(String elementName)
    {
        
        if (m_tracer != null) {
            StringBuffer sb = new StringBuffer();
                
            sb.append('<');
            sb.append(elementName);
            
            // convert the StringBuffer to a char array and
            // emit the trace event that these characters "might"
            // be written
            char ch[] = sb.toString().toCharArray();
            m_tracer.fireGenerateEvent(
                SerializerTrace.EVENTTYPE_OUTPUT_PSEUDO_CHARACTERS,
                ch,
                0,
                ch.length);
        }
    }

    /**
     * @see org.apache.xml.serializer.Serializer#asDOM3Serializer()
     */
    public Object asDOM3Serializer() throws IOException
    {
        return m_handler.asDOM3Serializer();
    }
}
