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

import java.io.IOException;
import java.util.HashMap;
import java.util.Set;

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

import org.apache.xml.serializer.utils.MsgKey;
import org.apache.xml.serializer.utils.Utils;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;


/**
 * This class acts as a base class for the XML "serializers"
 * and the stream serializers.
 * It contains a number of common fields and methods.
 * 
 * @xsl.usage internal
 */
public abstract class SerializerBase
    implements SerializationHandler, SerializerConstants
{
    SerializerBase() {
        return;
    }
    
    /**
     * The name of the package that this class is in.
     * <p>
     * Not a public API.
     */
    public static final String PKG_NAME;

    /**
     * The same as the name of the package that this class is in
     * except that '.' are replaced with '/'.
     * <p>
     * Not a public API.
     */
    public static final String PKG_PATH;

    static {
        String fullyQualifiedName = SerializerBase.class.getName();
        int lastDot = fullyQualifiedName.lastIndexOf('.');
        if (lastDot < 0) {
            PKG_NAME = "";
        } else {
            PKG_NAME = fullyQualifiedName.substring(0, lastDot);
        }

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < PKG_NAME.length(); i++) {
            char ch = PKG_NAME.charAt(i);
            if (ch == '.')
                sb.append('/');
            else
                sb.append(ch);
        }
        PKG_PATH = sb.toString();
    }

    

    /**
     * To fire off the end element trace event
     * @param name Name of element
     */
    protected void fireEndElem(String name)
        throws org.xml.sax.SAXException
    {
        if (m_tracer != null)
        {
            flushMyWriter();
            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDELEMENT,name, (Attributes)null);
        }     	        	    	
    }

    /**
     * Report the characters trace event
     * @param chars  content of characters
     * @param start  starting index of characters to output
     * @param length  number of characters to output
     */
    protected void fireCharEvent(char[] chars, int start, int length)
        throws org.xml.sax.SAXException
    {
        if (m_tracer != null)
        {
            flushMyWriter();
            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CHARACTERS, chars, start,length);
        }     	        	    	
    }

    /**
     * true if we still need to call startDocumentInternal() 
	 */
    protected boolean m_needToCallStartDocument = true; 

    /** True if a trailing "]]>" still needs to be written to be
     * written out. Used to merge adjacent CDATA sections
     */
    protected boolean m_cdataTagOpen = false;

    /**
     * All the attributes of the current element, collected from
     * startPrefixMapping() calls, or addAddtribute() calls, or 
     * from the SAX attributes in a startElement() call.
     */
    protected AttributesImplSerializer m_attributes = new AttributesImplSerializer();

    /**
     * Tells if we're in an EntityRef event.
     */
    protected boolean m_inEntityRef = false;

    /** This flag is set while receiving events from the external DTD */
    protected boolean m_inExternalDTD = false;

    /**
     * The System ID for the doc type.
     */
    protected String m_doctypeSystem;

    /**
     * The public ID for the doc type.
     */
    protected String m_doctypePublic;

    /**
     * Flag to tell that we need to add the doctype decl, which we can't do
     * until the first element is encountered.
     */
    boolean m_needToOutputDocTypeDecl = true;

    /**
     * Tells if we should write the XML declaration.
     */
    protected boolean m_shouldNotWriteXMLHeader = false;

    /**
     * The standalone value for the doctype.
     */
    private String m_standalone;

    /**
     * True if standalone was specified.
     */
    protected boolean m_standaloneWasSpecified = false;

    /**
     * Flag to tell if indenting (pretty-printing) is on.
     */
    protected boolean m_doIndent = false;
    /**
     * Amount to indent.
     */
    protected int m_indentAmount = 0;

    /**
     * Tells the XML version, for writing out to the XML decl.
     */
    protected String m_version = null;

    /**
     * The mediatype.  Not used right now.
     */
    protected String m_mediatype;

    /**
     * The transformer that was around when this output handler was created (if
     * any).
     */
    private Transformer m_transformer;

    /**
     * Namespace support, that keeps track of currently defined 
     * prefix/uri mappings. As processed elements come and go, so do
     * the associated mappings for that element.
     */
    protected NamespaceMappings m_prefixMap;
    
    /**
     * Handle for firing generate events.  This interface may be implemented
     * by the referenced transformer object.
     */
    protected SerializerTrace m_tracer;
    
    protected SourceLocator m_sourceLocator;
    

    /**
     * The writer to send output to. This field is only used in the ToStream
     * serializers, but exists here just so that the fireStartDoc() and
     * other fire... methods can flush this writer when tracing.
     */
    protected java.io.Writer m_writer = null;
    
    /**
     * A reference to "stack frame" corresponding to
     * the current element. Such a frame is pushed at a startElement()
     * and popped at an endElement(). This frame contains information about
     * the element, such as its namespace URI. 
     */
    protected ElemContext m_elemContext = new ElemContext();
    
    /**
     * A utility buffer for converting Strings passed to
     * character() methods to character arrays.
     * Reusing this buffer means not creating a new character array
     * everytime and it runs faster.
     */
    protected char[] m_charsBuff = new char[60];
    
    /**
     * A utility buffer for converting Strings passed to
     * attribute methods to character arrays.
     * Reusing this buffer means not creating a new character array
     * everytime and it runs faster.
     */
    protected char[] m_attrBuff = new char[30];    

    /**
     * Receive notification of a comment.
     * 
     * @see ExtendedLexicalHandler#comment(String)
     */
    public void comment(String data) throws SAXException
    {
        m_docIsEmpty = false;
        
        final int length = data.length();
        if (length > m_charsBuff.length)
        {
            m_charsBuff = new char[length * 2 + 1];
        }
        data.getChars(0, length, m_charsBuff, 0);
        comment(m_charsBuff, 0, length);
    }

    /**
     * If at runtime, when the qname of the attribute is
     * known, another prefix is specified for the attribute, then we can
     * patch or hack the name with this method. For
     * a qname of the form "ns?:otherprefix:name", this function patches the
     * qname by simply ignoring "otherprefix".
     * TODO: This method is a HACK! We do not have access to the
     * XML file, it sometimes generates a NS prefix of the form "ns?" for
     * an attribute.
     */
    protected String patchName(String qname)
    {

        
        final int lastColon = qname.lastIndexOf(':');

        if (lastColon > 0) {
            final int firstColon = qname.indexOf(':');
            final String prefix = qname.substring(0, firstColon);
            final String localName = qname.substring(lastColon + 1);

        // If uri is "" then ignore prefix
            final String uri = m_prefixMap.lookupNamespace(prefix);
            if (uri != null && uri.length() == 0) {
                return localName;
            }
            else if (firstColon != lastColon) {
                return prefix + ':' + localName;
            }
        }
        return qname;        
    }

    /**
     * Returns the local name of a qualified name. If the name has no prefix,
     * then it works as the identity (SAX2).
     * @param qname the qualified name 
     * @return the name, but excluding any prefix and colon.
     */
    protected static String getLocalName(String qname)
    {
        final int col = qname.lastIndexOf(':');
        return (col > 0) ? qname.substring(col + 1) : qname;
    }

    /**
     * Receive an object for locating the origin of SAX document events.
     *
     * @param locator An object that can return the location of any SAX document
     * event.
     * 
     * Receive an object for locating the origin of SAX document events.
     *
     * <p>SAX parsers are strongly encouraged (though not absolutely
     * required) to supply a locator: if it does so, it must supply
     * the locator to the application by invoking this method before
     * invoking any of the other methods in the DocumentHandler
     * interface.</p>
     *
     * <p>The locator allows the application to determine the end
     * position of any document-related event, even if the parser is
     * not reporting an error.  Typically, the application will
     * use this information for reporting its own errors (such as
     * character content that does not match an application's
     * business rules).  The information returned by the locator
     * is probably not sufficient for use with a search engine.</p>
     *
     * <p>Note that the locator will return correct information only
     * during the invocation of the events in this interface.  The
     * application should not attempt to use it at any other time.</p>
     */
    public void setDocumentLocator(Locator locator)
    {
        return;

        // I don't do anything with this yet.
    }

    /**
     * Adds the given attribute to the set of collected attributes , but only if
     * there is a currently open element.
     * 
     * An element is currently open if a startElement() notification has
     * occured but the start of the element has not yet been written to the
     * output.  In the stream case this means that we have not yet been forced
     * to close the elements opening tag by another notification, such as a
     * character notification.
     * 
     * @param uri the URI of the attribute
     * @param localName the local name of the attribute
     * @param rawName    the qualified name of the attribute
     * @param type the type of the attribute (probably CDATA)
     * @param value the value of the attribute
     * @param XSLAttribute true if this attribute is coming from an xsl:attriute 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_elemContext.m_startTagOpen)
        {
            addAttributeAlways(uri, localName, rawName, type, value, XSLAttribute);
        }

    }
    
    /**
     * Adds the given attribute to the set of attributes, even if there is
     * no currently open element. This is useful if a SAX startPrefixMapping()
     * should need to add an attribute before the element name is seen.
     * 
     * @param uri the URI of the attribute
     * @param localName the local name of the attribute
     * @param rawName   the qualified name of the attribute
     * @param type the type of the attribute (probably CDATA)
     * @param value the value of the attribute
     * @param XSLAttribute true if this attribute is coming from an xsl:attribute element
     * @return true if the attribute was added, 
     * false if an existing value was replaced.
     */
    public boolean addAttributeAlways(
        String uri,
        String localName,
        String rawName,
        String type,
        String value,
        boolean XSLAttribute)
    {
        boolean was_added;
//            final int index =
//                (localName == null || uri == null) ?
//                m_attributes.getIndex(rawName):m_attributes.getIndex(uri, localName);        
            int index;
//            if (localName == null || uri == null){
//                index = m_attributes.getIndex(rawName);
//            }
//            else {
//                index = m_attributes.getIndex(uri, localName);
//            }
            if (localName == null || uri == null || uri.length() == 0)
                index = m_attributes.getIndex(rawName);
            else {
                index = m_attributes.getIndex(uri,localName);
            }
            if (index >= 0)
            {
                /* We've seen the attribute before.
                 * We may have a null uri or localName, but all
                 * we really want to re-set is the value anyway.
                 */
                m_attributes.setValue(index,value);
                was_added = false;
            }
            else
            {
                // the attribute doesn't exist yet, create it
                m_attributes.addAttribute(uri, localName, rawName, type, value);
                was_added = true;
            }
            return was_added;
        
    }
  

    /**
     *  Adds  the given attribute to the set of collected attributes, 
     * but only if there is a currently open element.
     *
     * @param name the attribute's qualified name
     * @param value the value of the attribute
     */
    public void addAttribute(String name, final String value)
    {
        if (m_elemContext.m_startTagOpen)
        {
            final String patchedName = patchName(name);
            final String localName = getLocalName(patchedName);
            final String uri = getNamespaceURI(patchedName, false);

            addAttributeAlways(uri,localName, patchedName, "CDATA", value, false);
         }
    }    

    /**
     * Adds the given xsl:attribute to the set of collected attributes, 
     * but only if there is a currently open element.
     *
     * @param name the attribute's qualified name (prefix:localName)
     * @param value the value of the attribute
     * @param uri the URI that the prefix of the name points to
     */
    public void addXSLAttribute(String name, final String value, final String uri)
    {
        if (m_elemContext.m_startTagOpen)
        {
            final String patchedName = patchName(name);
            final String localName = getLocalName(patchedName);

            addAttributeAlways(uri,localName, patchedName, "CDATA", value, true);
         }
    } 

    /**
     * Add the given attributes to the currently collected ones. These
     * attributes are always added, regardless of whether on not an element
     * is currently open.
     * @param atts List of attributes to add to this list
     */
    public void addAttributes(Attributes atts) throws SAXException
    {

        int nAtts = atts.getLength();

        for (int i = 0; i < nAtts; i++)
        {
            String uri = atts.getURI(i);

            if (null == uri)
                uri = "";

            addAttributeAlways(
                uri,
                atts.getLocalName(i),
                atts.getQName(i),
                atts.getType(i),
                atts.getValue(i),
                false);

        }
    }

    /**
     * Return a {@link ContentHandler} interface into this serializer.
     * If the serializer does not support the {@link ContentHandler}
     * interface, it should return null.
     *
     * @return A {@link ContentHandler} interface into this serializer,
     *  or null if the serializer is not SAX 2 capable
     * @throws IOException An I/O exception occured
     */
    public ContentHandler asContentHandler() throws IOException
    {
        return this;
    }

    /**
     * Report the end of an entity.
     *
     * @param name The name of the entity that is ending.
     * @throws org.xml.sax.SAXException The application may raise an exception.
     * @see #startEntity
     */
    public void endEntity(String name) throws org.xml.sax.SAXException
    {
        if (name.equals("[dtd]"))
            m_inExternalDTD = false;
        m_inEntityRef = false;

        if (m_tracer != null)
            this.fireEndEntity(name);        
    }

    /**
     * Flush and close the underlying java.io.Writer. This method applies to
     * ToStream serializers, not ToSAXHandler serializers.
     * @see ToStream
     */
    public void close()
    {
        // do nothing (base behavior)
    }

    /**
     * Initialize global variables
     */
    protected void initCDATA()
    {
        // CDATA stack
        //        _cdataStack = new Stack();
        //        _cdataStack.push(new Integer(-1)); // push dummy value
    }

    /**
     * Returns the character encoding to be used in the output document.
     * @return the character encoding to be used in the output document.
     */
    public String getEncoding()
    {
        return getOutputProperty(OutputKeys.ENCODING);
    }

   /**
     * Sets the character encoding coming from the xsl:output encoding stylesheet attribute.
     * @param m_encoding the character encoding
     */
    public void setEncoding(String encoding)
    {
        setOutputProperty(OutputKeys.ENCODING,encoding);
    }

    /**
     * Sets the value coming from the xsl:output omit-xml-declaration stylesheet attribute
     * @param b true if the XML declaration is to be omitted from the output
     * document.
     */
    public void setOmitXMLDeclaration(boolean b)
    {
        String val = b ? "yes":"no";
        setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,val);
    }


    /**
     * @return true if the XML declaration is to be omitted from the output
     * document.
     */
    public boolean getOmitXMLDeclaration()
    {
        return m_shouldNotWriteXMLHeader;
    }

    /**
     * Returns the previously set value of the value to be used as the public
     * identifier in the document type declaration (DTD).
     * 
     *@return the public identifier to be used in the DOCTYPE declaration in the
     * output document.
     */    
    public String getDoctypePublic()
    {
        return m_doctypePublic;
    }

    /** Set the value coming from the xsl:output doctype-public stylesheet attribute.
      * @param doctypePublic the public identifier to be used in the DOCTYPE
      * declaration in the output document.
      */
    public void setDoctypePublic(String doctypePublic)
    {
        setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, doctypePublic);
    }


    /**
     * Returns the previously set value of the value to be used
     * as the system identifier in the document type declaration (DTD).
	 * @return the system identifier to be used in the DOCTYPE declaration in
	 * the output document.
     *
     */    
    public String getDoctypeSystem()
    {
        return m_doctypeSystem;
    }

    /** Set the value coming from the xsl:output doctype-system stylesheet attribute.
      * @param doctypeSystem the system identifier to be used in the DOCTYPE
      * declaration in the output document.
      */
    public void setDoctypeSystem(String doctypeSystem)
    {
        setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doctypeSystem);
    }

    /** Set the value coming from the xsl:output doctype-public and doctype-system stylesheet properties
     * @param doctypeSystem the system identifier to be used in the DOCTYPE
     * declaration in the output document.
     * @param doctypePublic the public identifier to be used in the DOCTYPE
     * declaration in the output document.
     */
    public void setDoctype(String doctypeSystem, String doctypePublic)
    {
        setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doctypeSystem);
        setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, doctypePublic);
    }

    /**
     * Sets the value coming from the xsl:output standalone stylesheet attribute.
     * @param standalone a value of "yes" indicates that the
     * <code>standalone</code> delaration is to be included in the output
     * document. This method remembers if the value was explicitly set using
     * this method, verses if the value is the default value.
     */
    public void setStandalone(String standalone)
    {
        setOutputProperty(OutputKeys.STANDALONE, standalone);
    }
    /**
     * Sets the XSL standalone attribute, but does not remember if this is a
     * default or explicite setting.
     * @param standalone "yes" | "no"
     */    
    protected void setStandaloneInternal(String standalone)
    {
        if ("yes".equals(standalone))
            m_standalone = "yes";
        else
            m_standalone = "no";
        
    }

    /**
     * Gets the XSL standalone attribute
     * @return a value of "yes" if the <code>standalone</code> delaration is to
     * be included in the output document.
     *  @see XSLOutputAttributes#getStandalone()
     */
    public String getStandalone()
    {
        return m_standalone;
    }

    /**
     * @return true if the output document should be indented to visually
     * indicate its structure.
     */
    public boolean getIndent()
    {
        return m_doIndent;
    }
    /**
     * Gets the mediatype the media-type or MIME type associated with the output
     * document.
     * @return the mediatype the media-type or MIME type associated with the
     * output document.
     */
    public String getMediaType()
    {
        return m_mediatype;
    }

    /**
     * Gets the version of the output format.
     * @return the version of the output format.
     */
    public String getVersion()
    {
        return m_version;
    }

    /**
     * Sets the value coming from the xsl:output version attribute.
     * @param version the version of the output format.
     * @see SerializationHandler#setVersion(String)
     */
    public void setVersion(String version)
    {
        setOutputProperty(OutputKeys.VERSION, version);
    }

    /**
     * Sets the value coming from the xsl:output media-type stylesheet attribute.
     * @param mediaType the non-null media-type or MIME type associated with the
     * output document.
     * @see javax.xml.transform.OutputKeys#MEDIA_TYPE
     * @see SerializationHandler#setMediaType(String)
     */
    public void setMediaType(String mediaType)
    {
        setOutputProperty(OutputKeys.MEDIA_TYPE,mediaType);
    }

    /**
     * @return the number of spaces to indent for each indentation level.
     */
    public int getIndentAmount()
    {
        return m_indentAmount;
    }

    /**
     * Sets the indentation amount.
     * @param m_indentAmount The m_indentAmount to set
     */
    public void setIndentAmount(int m_indentAmount)
    {
        this.m_indentAmount = m_indentAmount;
    }

    /**
     * Sets the value coming from the xsl:output indent stylesheet
     * attribute.
     * @param doIndent true if the output document should be indented to
     * visually indicate its structure.
     * @see XSLOutputAttributes#setIndent(boolean)
     */
    public void setIndent(boolean doIndent)
    {
        String val = doIndent ? "yes":"no";
        setOutputProperty(OutputKeys.INDENT,val);
    }

    /**
     * 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 uri, String prefix)
        throws SAXException
    {
        // default behavior is to do nothing
    }

    /**
     * Return a {@link DOMSerializer} interface into this serializer. If the
     * serializer does not support the {@link DOMSerializer} interface, it should
     * return null.
     *
     * @return A {@link DOMSerializer} interface into this serializer,  or null
     * if the serializer is not DOM capable
     * @throws IOException An I/O exception occured
     * @see Serializer#asDOMSerializer()
     */
    public DOMSerializer asDOMSerializer() throws IOException
    { 
        return this;
    }

    /**
     * Tell if two strings are equal, without worry if the first string is null.
     *
     * @param p String reference, which may be null.
     * @param t String reference, which may be null.
     *
     * @return true if strings are equal.
     */
    private static final boolean subPartMatch(String p, String t)
    {
        return (p == t) || ((null != p) && (p.equals(t)));
    }

    /**
     * Returns the local name of a qualified name. 
     * If the name has no prefix,
     * then it works as the identity (SAX2). 
     * 
     * @param qname a qualified name
     * @return returns the prefix of the qualified name,
     * or null if there is no prefix.
     */
    protected static final String getPrefixPart(String qname)
    {
        final int col = qname.indexOf(':');
        return (col > 0) ? qname.substring(0, col) : null;
        //return (col > 0) ? qname.substring(0,col) : "";
    }

    /**
     * Some users of the serializer may need the current namespace mappings
     * @return the current namespace mappings (prefix/uri)
     * @see ExtendedContentHandler#getNamespaceMappings()
     */
    public NamespaceMappings getNamespaceMappings()
    {
        return m_prefixMap;
    }

    /**
     * Returns the prefix currently pointing to the given URI (if any).
     * @param namespaceURI the uri of the namespace in question
     * @return a prefix pointing to the given URI (if any).
     * @see ExtendedContentHandler#getPrefix(String)
     */
    public String getPrefix(String namespaceURI)
    {
        String prefix = m_prefixMap.lookupPrefix(namespaceURI);
        return prefix;
    }

    /**
     * Returns the URI of an element or attribute. Note that default namespaces
     * do not apply directly to attributes.
     * @param qname a qualified name
     * @param isElement true if the qualified name is the name of 
     * an element.
     * @return returns the namespace URI associated with the qualified name.
     */
    public String getNamespaceURI(String qname, boolean isElement)
    {
        String uri = EMPTYSTRING;
        int col = qname.lastIndexOf(':');
        final String prefix = (col > 0) ? qname.substring(0, col) : EMPTYSTRING;

        if (!EMPTYSTRING.equals(prefix) || isElement)
        {
            if (m_prefixMap != null)
            {
                uri = m_prefixMap.lookupNamespace(prefix);
                if (uri == null && !prefix.equals(XMLNS_PREFIX))
                {
                    throw new RuntimeException(
                        Utils.messages.createMessage(
                            MsgKey.ER_NAMESPACE_PREFIX,
                            new Object[] { qname.substring(0, col) }  ));
                }
            }
        }
        return uri;
    }

    /**
     * Returns the URI of prefix (if any)
     * 
	 * @param prefix the prefix whose URI is searched for
     * @return the namespace URI currently associated with the
     * prefix, null if the prefix is undefined.
     */
    public String getNamespaceURIFromPrefix(String prefix)
    {
        String uri = null;
        if (m_prefixMap != null)
            uri = m_prefixMap.lookupNamespace(prefix);
        return uri;
    }

    /**
     * Entity reference event.
     *
     * @param name Name of entity
     *
     * @throws org.xml.sax.SAXException
     */
    public void entityReference(String name) throws org.xml.sax.SAXException
    {

        flushPending();

        startEntity(name);
        endEntity(name);

        if (m_tracer != null)
		    fireEntityReference(name);
    }

    /**
     * Sets the transformer associated with this serializer
     * @param t the transformer associated with this serializer.
     * @see SerializationHandler#setTransformer(Transformer)
     */
    public void setTransformer(Transformer t)
    {
        m_transformer = t;
        
        // If this transformer object implements the SerializerTrace interface
        // then assign m_tracer to the transformer object so it can be used
        // to fire trace events.
        if ((m_transformer instanceof SerializerTrace) &&
            (((SerializerTrace) m_transformer).hasTraceListeners())) {
           m_tracer = (SerializerTrace) m_transformer;
        } else {
           m_tracer = null;
        }
    }
    /**
     * Gets the transformer associated with this serializer
     * @return returns the transformer associated with this serializer.
     * @see SerializationHandler#getTransformer()
     */
    public Transformer getTransformer()
    {
        return m_transformer;
    }
    
    /**
     * This method gets the nodes value as a String and uses that String as if
     * it were an input character notification.
     * @param node the Node to serialize
     * @throws org.xml.sax.SAXException
     */
    public void characters(org.w3c.dom.Node node)
        throws org.xml.sax.SAXException
    {
        flushPending();
        String data = node.getNodeValue();
        if (data != null)
        {
            final int length = data.length();
            if (length > m_charsBuff.length)
            {
                m_charsBuff = new char[length * 2 + 1];
            }
            data.getChars(0, length, m_charsBuff, 0);
            characters(m_charsBuff, 0, length);
        }
    }
    

    /**
     * @see org.xml.sax.ErrorHandler#error(SAXParseException)
     */
    public void error(SAXParseException exc) throws SAXException {
    }

    /**
     * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException)
     */
    public void fatalError(SAXParseException exc) throws SAXException {
        
      m_elemContext.m_startTagOpen = false;

    }

    /**
     * @see org.xml.sax.ErrorHandler#warning(SAXParseException)
     */
    public void warning(SAXParseException exc) throws SAXException 
    {
    }

    /**
     * To fire off start entity trace event
     * @param name Name of entity
     */
    protected void fireStartEntity(String name)
        throws org.xml.sax.SAXException
    {        
        if (m_tracer != null)
        {
            flushMyWriter();
            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENTITYREF, name);
        }     	        	    	
    }

    /**
     * Report the characters event
     * @param chars  content of characters
     * @param start  starting index of characters to output
     * @param length  number of characters to output
     */
//    protected void fireCharEvent(char[] chars, int start, int length)
//        throws org.xml.sax.SAXException
//    {
//        if (m_tracer != null)
//            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CHARACTERS, chars, start,length);     	        	    	
//    }
//        

    /**
     * This method is only used internally when flushing the writer from the
     * various fire...() trace events.  Due to the writer being wrapped with 
     * SerializerTraceWriter it may cause the flush of these trace events:
     * EVENTTYPE_OUTPUT_PSEUDO_CHARACTERS 
     * EVENTTYPE_OUTPUT_CHARACTERS
     * which trace the output written to the output stream.
     * 
     */
    private void flushMyWriter()
    {
        if (m_writer != null)
        {
            try
            {
                m_writer.flush();
            }
            catch(IOException ioe)
            {
            
            }
        }
    }
    /**
     * Report the CDATA trace event
     * @param chars  content of CDATA
     * @param start  starting index of characters to output
     * @param length  number of characters to output
     */
    protected void fireCDATAEvent(char[] chars, int start, int length)
        throws org.xml.sax.SAXException
    {
		if (m_tracer != null)
        {
            flushMyWriter();
			m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CDATA, chars, start,length);
        }     	        	    	
    }

    /**
     * Report the comment trace event
     * @param chars  content of comment
     * @param start  starting index of comment to output
     * @param length  number of characters to output
     */
    protected void fireCommentEvent(char[] chars, int start, int length)
        throws org.xml.sax.SAXException
    {
		if (m_tracer != null)
        {
            flushMyWriter();
			m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_COMMENT, new String(chars, start, length));
        }     	        	    	
    }


    /**
     * To fire off end entity trace event
     * @param name Name of entity
     */
    public void fireEndEntity(String name)
        throws org.xml.sax.SAXException
    {
        if (m_tracer != null)
            flushMyWriter();
    	// we do not need to handle this.
    }    

    /**
     * To fire off start document trace  event
     */
     protected void fireStartDoc()
        throws org.xml.sax.SAXException
    {
        if (m_tracer != null)
        {
            flushMyWriter();
            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_STARTDOCUMENT);
        }     	    
    }    


    /**
     * To fire off end document trace event
     */
    protected void fireEndDoc()
        throws org.xml.sax.SAXException
    {
        if (m_tracer != null)
        {
            flushMyWriter();
            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDDOCUMENT);
        }     	        	
    }    
    
    /**
     * Report the start element trace event. This trace method needs to be
     * called just before the attributes are cleared.
     * 
     * @param elemName the qualified name of the element
     * 
     */
    protected void fireStartElem(String elemName)
        throws org.xml.sax.SAXException
    {        
        if (m_tracer != null)
        {
            flushMyWriter();
            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_STARTELEMENT,
                elemName, m_attributes);     	 
        }       	
    }    


    /**
     * To fire off the end element event
     * @param name Name of element
     */
//    protected void fireEndElem(String name)
//        throws org.xml.sax.SAXException
//    {
//        if (m_tracer != null)
//            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDELEMENT,name, (Attributes)null);     	        	    	
//    }    


    /**
     * To fire off the PI trace event
     * @param name Name of PI
     */
    protected void fireEscapingEvent(String name, String data)
        throws org.xml.sax.SAXException
    {

        if (m_tracer != null)
        {
            flushMyWriter();
            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_PI,name, data);
        }     	        	    	
    }    


    /**
     * To fire off the entity reference trace event
     * @param name Name of entity reference
     */
    protected void fireEntityReference(String name)
        throws org.xml.sax.SAXException
    {
        if (m_tracer != null)
        {
            flushMyWriter();
            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENTITYREF,name, (Attributes)null);
        }     	        	    	
    }    

    /**
     * Receive notification of the beginning of a document.
     * This method is never a self generated call, 
     * but only called externally.
     *
     * <p>The SAX parser will invoke this method only once, before any
     * other methods in this interface or in DTDHandler (except for
     * setDocumentLocator).</p>
     *
     * @throws org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     *
     * @throws org.xml.sax.SAXException
     */
    public void startDocument() throws org.xml.sax.SAXException
    {

        // if we do get called with startDocument(), handle it right away       
        startDocumentInternal();
        m_needToCallStartDocument = false;
        return;
    }   
    
    /**
     * This method handles what needs to be done at a startDocument() call,
     * whether from an external caller, or internally called in the 
     * serializer.  For historical reasons the serializer is flexible to
     * startDocument() not always being called.
     * Even if no external call is
     * made into startDocument() this method will always be called as a self
     * generated internal startDocument, it handles what needs to be done at a
     * startDocument() call.
     * 
     * This method exists just to make sure that startDocument() is only ever
     * called from an external caller, which in principle is just a matter of
     * style.
     * 
     * @throws SAXException
     */
    protected void startDocumentInternal() throws org.xml.sax.SAXException
    {
        if (m_tracer != null)
            this.fireStartDoc();
    } 
    /**
     * 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_sourceLocator = locator;    
    }

    
    /** 
     * Used only by TransformerSnapshotImpl to restore the serialization 
     * to a previous state. 
     * 
     * @param mappings NamespaceMappings
     */
    public void setNamespaceMappings(NamespaceMappings mappings) {
        m_prefixMap = mappings;
    }
    
    public boolean reset()
    {
    	resetSerializerBase();
    	return true;
    }
    
    /**
     * Reset all of the fields owned by SerializerBase
     *
     */
    private void resetSerializerBase()
    {
    	this.m_attributes.clear();
        this.m_CdataElems = null;
        this.m_cdataTagOpen = false;
        this.m_docIsEmpty = true;
    	this.m_doctypePublic = null;
    	this.m_doctypeSystem = null;
    	this.m_doIndent = false;
        this.m_elemContext = new ElemContext();
    	this.m_indentAmount = 0;
    	this.m_inEntityRef = false;
    	this.m_inExternalDTD = false;
    	this.m_mediatype = null;
    	this.m_needToCallStartDocument = true;
    	this.m_needToOutputDocTypeDecl = false;
        if (m_OutputProps != null)
            this.m_OutputProps.clear();
        if (m_OutputPropsDefault != null)
            this.m_OutputPropsDefault.clear();
        if (this.m_prefixMap != null)
    	    this.m_prefixMap.reset();
    	this.m_shouldNotWriteXMLHeader = false;
    	this.m_sourceLocator = null;
    	this.m_standalone = null;
    	this.m_standaloneWasSpecified = false;
        this.m_StringOfCDATASections = null;
    	this.m_tracer = null;
    	this.m_transformer = null;
    	this.m_version = null;
    	// don't set writer to null, so that it might be re-used
    	//this.m_writer = null;
    }
    
    /**
     * Returns true if the serializer is used for temporary output rather than
     * final output.
     * 
     * This concept is made clear in the XSLT 2.0 draft.
     */
    final boolean inTemporaryOutputState() 
    {
        /* This is a hack. We should really be letting the serializer know
         * that it is in temporary output state with an explicit call, but
         * from a pragmatic point of view (for now anyways) having no output
         * encoding at all, not even the default UTF-8 indicates that the serializer
         * is being used for temporary RTF.
         */ 
        return (getEncoding() == null);
        
    }
    
    /**
     * This method adds an attribute the the current element,
     * but should not be used for an xsl:attribute child.
     * @see ExtendedContentHandler#addAttribute(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
     */
    public void addAttribute(String uri, String localName, String rawName, String type, String value) throws SAXException 
    {
        if (m_elemContext.m_startTagOpen)
        {
            addAttributeAlways(uri, localName, rawName, type, value, false);
        }
    }
    
    /**
     * @see org.xml.sax.DTDHandler#notationDecl(java.lang.String, java.lang.String, java.lang.String)
     */
    public void notationDecl(String arg0, String arg1, String arg2)
        throws SAXException {
        // This method just provides a definition to satisfy the interface
        // A particular sub-class of SerializerBase provides the implementation (if desired)        
    }

    /**
     * @see org.xml.sax.DTDHandler#unparsedEntityDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
     */
    public void unparsedEntityDecl(
        String arg0,
        String arg1,
        String arg2,
        String arg3)
        throws SAXException {
        // This method just provides a definition to satisfy the interface
        // A particular sub-class of SerializerBase provides the implementation (if desired)        
    }

    /**
     * If set to false the serializer does not expand DTD entities,
     * but leaves them as is, the default value is true.
     */
    public void setDTDEntityExpansion(boolean expand) {
        // This method just provides a definition to satisfy the interface
        // A particular sub-class of SerializerBase provides the implementation (if desired)        
    }
 

    /** 
     * The CDATA section names stored in a whitespace separateed list with
     * each element being a word of the form "{uri}localName" This list
     * comes from the cdata-section-elements attribute.
     * 
     * This field replaces m_cdataSectionElements Vector.
     */
    protected String m_StringOfCDATASections = null; 
    
    boolean m_docIsEmpty = true;
    void initCdataElems(String s)
    {
        if (s != null)
        {            
            int max = s.length();

            // true if we are in the middle of a pair of curly braces that delimit a URI
            boolean inCurly = false;

            // true if we found a URI but haven't yet processed the local name 
            boolean foundURI = false;

            StringBuffer buf = new StringBuffer();
            String uri = null;
            String localName = null;

            // parse through string, breaking on whitespaces.  I do this instead
            // of a tokenizer so I can track whitespace inside of curly brackets,
            // which theoretically shouldn't happen if they contain legal URLs.


            for (int i = 0; i < max; i++)
            {

                char c = s.charAt(i);

                if (Character.isWhitespace(c))
                {
                    if (!inCurly)
                    {
                        if (buf.length() > 0)
                        {
                            localName = buf.toString();
                            if (!foundURI)
                                uri = "";
                            addCDATAElement(uri,localName);
                            buf.setLength(0);
                            foundURI = false;
                        }
                        continue;
                    }
                    else
                        buf.append(c); // add whitespace to the URI
                }
                else if ('{' == c) // starting a URI
                    inCurly = true;
                else if ('}' == c)
                {
                    // we just ended a URI, add the URI to the vector
                    foundURI = true;
                    uri = buf.toString();
                    buf.setLength(0);
                    inCurly = false;
                }
                else
                {
                    // append non-whitespace, non-curly to current URI or localName being gathered.                    
                    buf.append(c);
                }

            }

            if (buf.length() > 0)
            {
                // We have one last localName to process.
                localName = buf.toString();
                if (!foundURI)
                    uri = "";
                addCDATAElement(uri,localName);
            }
        }
    }
    protected java.util.Hashtable m_CdataElems = null;
    private void addCDATAElement(String uri, String localName) 
    {
        if (m_CdataElems == null) {
            m_CdataElems = new java.util.Hashtable();
        }
        
        java.util.Hashtable h = (java.util.Hashtable) m_CdataElems.get(localName);
        if (h == null) {
            h = new java.util.Hashtable();
            m_CdataElems.put(localName,h);
        }
        h.put(uri,uri);
        
    }
    
    
    /**
     * Return true if nothing has been sent to this result tree yet.
     * <p>
     * This is not a public API.
     * 
     * @xsl.usage internal
     */
    public boolean documentIsEmpty() {
        // If we haven't called startDocument() yet, then this document is empty
        return m_docIsEmpty && (m_elemContext.m_currentElemDepth == 0);
    }    
    
    /**
     * Return true if the current element in m_elemContext
     * is a CDATA section.
     * CDATA sections are specified in the <xsl:output> attribute
     * cdata-section-names or in the JAXP equivalent property.
     * In any case the format of the value of such a property is:
     * <pre>
     * "{uri1}localName1 {uri2}localName2 . . . "
     * </pre>
     * 
     * <p>
     * This method is not a public API, but is only used internally by the serializer.
     */
    protected boolean isCdataSection()
    {

        boolean b = false;

        if (null != m_StringOfCDATASections)
        {
            if (m_elemContext.m_elementLocalName == null) 
            {
                String localName =  getLocalName(m_elemContext.m_elementName); 
                m_elemContext.m_elementLocalName = localName;                   
            }
            
            if ( m_elemContext.m_elementURI == null) {
                
                m_elemContext.m_elementURI = getElementURI();
            }
            else if ( m_elemContext.m_elementURI.length() == 0) {
                if ( m_elemContext.m_elementName == null) {
                    m_elemContext.m_elementName = m_elemContext.m_elementLocalName;    
                    // leave URI as "", meaning in no namespace
                }
                else if (m_elemContext.m_elementLocalName.length() < m_elemContext.m_elementName.length()){
                    // We were told the URI was "", yet the name has a prefix since the name is longer than the localname.
                    // So we will fix that incorrect information here.
                    m_elemContext.m_elementURI = getElementURI();  
                }
            }

            java.util.Hashtable h = (java.util.Hashtable) m_CdataElems.get(m_elemContext.m_elementLocalName);
            if (h != null) 
            {
                Object obj = h.get(m_elemContext.m_elementURI);
                if (obj != null)
                    b = true; 
            }

        }
        return b;
    }
    
    /**
     * Before this call m_elementContext.m_elementURI is null,
     * which means it is not yet known. After this call it
     * is non-null, but possibly "" meaning that it is in the
     * default namespace.
     * 
     * @return The URI of the element, never null, but possibly "".
     */
    private String getElementURI() {
        String uri = null;
        // At this point in processing we have received all the
        // namespace mappings
        // As we still don't know the elements namespace,
        // we now figure it out.

        String prefix = getPrefixPart(m_elemContext.m_elementName);

        if (prefix == null) {
            // no prefix so lookup the URI of the default namespace
            uri = m_prefixMap.lookupNamespace("");
        } else {
            uri = m_prefixMap.lookupNamespace(prefix);
        }
        if (uri == null) {
            // We didn't find the namespace for the
            // prefix ... ouch, that shouldn't happen.
            // This is a hack, we really don't know
            // the namespace
            uri = EMPTYSTRING;
        }

        return uri;
    }
    

    /**
     * Get the value of an output property,
     * the explicit value, if any, otherwise the
     * default value, if any, otherwise null.
     */
    public String getOutputProperty(String name) {
        String val = getOutputPropertyNonDefault(name);
        // If no explicit value, try to get the default value
        if (val == null)
            val = getOutputPropertyDefault(name);
        return val;
        
    }
    /**
     * Get the value of an output property, 
     * not the default value. If there is a default
     * value, but no non-default value this method
     * will return null.
     * <p>
     * 
     */
    public String getOutputPropertyNonDefault(String name )
    {
        return getProp(name,false);
    }

    /**
     * Return a {@link DOM3Serializer} interface into this serializer. If the
     * serializer does not support the {@link DOM3Serializer} interface, it should
     * return null.
     *
     * @return A {@link DOM3Serializer} interface into this serializer,  or null
     * if the serializer is not DOM capable
     * @throws IOException An I/O exception occured
     * @see org.apache.xml.serializer.Serializer#asDOM3Serializer()
     */
    public Object asDOM3Serializer() throws IOException
    {
        return new org.apache.xml.serializer.dom3.DOM3SerializerImpl(this);
    }
    /**
     * Get the default value of an xsl:output property,
     * which would be null only if no default value exists
     * for the property.
     */
    public String getOutputPropertyDefault(String name) {
        return getProp(name, true);
    } 
    
    /**
     * Set the value for the output property, typically from
     * an xsl:output element, but this does not change what
     * the default value is.
     */
    public void   setOutputProperty(String name, String val) {
        setProp(name,val,false);
        
    }
    
    /**
     * Set the default value for an output property, but this does
     * not impact any explicitly set value.
     */
    public void   setOutputPropertyDefault(String name, String val) {
        setProp(name,val,true);
        
    }
    
    /**
     * A mapping of keys to explicitly set values, for example if 
     * and <xsl:output/> has an "encoding" attribute, this
     * map will have what that attribute maps to.
     */
    private HashMap m_OutputProps;
    /**
     * A mapping of keys to default values, for example if
     * the default value of the encoding is "UTF-8" then this
     * map will have that "encoding" maps to "UTF-8".
     */
    private HashMap m_OutputPropsDefault;
    
    Set getOutputPropDefaultKeys() {
        return m_OutputPropsDefault.keySet();
    }
    Set getOutputPropKeys() {
        return m_OutputProps.keySet();
    }
    
    private String getProp(String name, boolean defaultVal) {
        if (m_OutputProps == null) {
            m_OutputProps = new HashMap();
            m_OutputPropsDefault = new HashMap();
        }
        
        String val;
        if (defaultVal)
            val = (String) m_OutputPropsDefault.get(name);
        else
            val = (String) m_OutputProps.get(name);
        
        return val;
        
    }
    /**
     * 
     * @param name The name of the property, e.g. "{http://myprop}indent-tabs" or "indent".
     * @param val The value of the property, e.g. "4"
     * @param defaultVal true if this is a default value being set for the property as 
     * opposed to a user define on, set say explicitly in the stylesheet or via JAXP
     */
    void setProp(String name, String val, boolean defaultVal) {
        if (m_OutputProps == null) {
            m_OutputProps = new HashMap();
            m_OutputPropsDefault = new HashMap();
        }
        
        if (defaultVal)
            m_OutputPropsDefault.put(name,val);
        else {
            if (OutputKeys.CDATA_SECTION_ELEMENTS.equals(name) && val != null) {
                initCdataElems(val);
                String oldVal = (String) m_OutputProps.get(name);
                String newVal;
                if (oldVal == null)
                    newVal = oldVal + ' ' + val;
                else
                    newVal = val;
                m_OutputProps.put(name,newVal);
            }
            else {
                m_OutputProps.put(name,val);
            }
        }
        

    }

    /**
     * Get the first char of the local name
     * @param name Either a local name, or a local name
     * preceeded by a uri enclosed in curly braces.
     */
    static char getFirstCharLocName(String name) {
        final char first;
        int i = name.indexOf('}');
        if (i < 0)
            first = name.charAt(0);
        else
            first = name.charAt(i+1);
        return first;
    }
}
    

