/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:  
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, Lotus
 * Development Corporation., http://www.lotus.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
package org.apache.xalan.transformer;

import java.util.Enumeration;

import org.apache.xalan.templates.Stylesheet;
import org.apache.xalan.templates.StylesheetRoot;
import org.apache.xalan.templates.ElemTemplate;
import org.apache.xalan.templates.ElemTemplateElement;
import org.apache.xalan.trace.TraceManager;
import org.apache.xalan.trace.GenerateEvent;
import org.apache.xml.utils.MutableAttrListImpl;
import org.apache.xml.utils.QName;
import org.apache.xml.utils.TreeWalker;
import org.apache.xml.utils.ObjectPool;
import org.apache.xml.utils.XMLCharacterRecognizer;
import org.apache.xpath.objects.XObject;
import org.apache.xpath.XPathContext;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMIterator;
import org.apache.xml.dtm.DTMFilter;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.SAXParseException;
import org.xml.sax.SAXException;
import org.xml.sax.ErrorHandler;

import org.xml.sax.helpers.NamespaceSupport;
import org.apache.xml.utils.NamespaceSupport2;
import org.xml.sax.Locator;

import javax.xml.transform.TransformerException;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Transformer;

/**
 * This class is a layer between the direct calls to the result
 * tree content handler, and the transformer.  For one thing,
 * we have to delay the call to
 * getContentHandler().startElement(name, atts) because of the
 * xsl:attribute and xsl:copy calls.  In other words,
 * the attributes have to be fully collected before you
 * can call startElement.
 */
public class ResultTreeHandler extends QueuedEvents
        implements ContentHandler, LexicalHandler, TransformState,
        org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.CharacterNodeHandler,
        ErrorHandler
{

  /** Indicate whether running in Debug mode */
  private static final boolean DEBUG = false;

  /**
   * Null constructor for object pooling.
   */
  public ResultTreeHandler(){}

  /**
   * Create a new result tree handler.  The real content
   * handler will be the ContentHandler passed as an argument.
   *
   * @param transformer non-null transformer instance
   * @param realHandler Content Handler instance
   */
  public ResultTreeHandler(TransformerImpl transformer,
                           ContentHandler realHandler)
  {
    init(transformer, realHandler);
  }

  /**
   * Initializer method.
   *
   * @param transformer non-null transformer instance
   * @param realHandler Content Handler instance
   */
  public void init(TransformerImpl transformer, ContentHandler realHandler)
  {

    m_transformer = transformer;

    // m_startDoc.setTransformer(m_transformer);
    TraceManager tracer = transformer.getTraceManager();

    if ((null != tracer) && tracer.hasTraceListeners())
      m_tracer = tracer;
    else
      m_tracer = null;

    // m_startDoc.setTraceManager(m_tracer);
    m_contentHandler = realHandler;

    // m_startDoc.setContentHandler(m_contentHandler);
    if (m_contentHandler instanceof LexicalHandler)
      m_lexicalHandler = (LexicalHandler) m_contentHandler;
    else
      m_lexicalHandler = null;

    m_isTransformClient = (m_contentHandler instanceof TransformerClient);

    m_cloner = new ClonerToResultTree(transformer, this);

    // The stylesheet is set at a rather late stage, so I do 
    // this here, though it would probably be better done elsewhere.
    if (null != m_transformer)
      m_stylesheetRoot = m_transformer.getStylesheet();

    pushDocumentEvent();  // not pending yet.
  }

  /**
   * Bottleneck the startDocument event.
   *
   * @throws org.xml.sax.SAXException
   */
  public void startDocument() throws org.xml.sax.SAXException{}

  /**
   * Bottleneck the endDocument event.  This may be called
   * more than once in order to make sure the pending start
   * document is called.
   *
   * @throws org.xml.sax.SAXException
   */
  public void endDocument() throws org.xml.sax.SAXException
  {

    flushPending(true);

    if (!m_docEnded)
    {
      m_contentHandler.endDocument();

      if (null != m_tracer)
      {
        GenerateEvent ge =
          new GenerateEvent(m_transformer,
                            GenerateEvent.EVENTTYPE_ENDDOCUMENT, null);

        m_tracer.fireGenerateEvent(ge);
      }

      m_docEnded = true;
      m_docPending = false;
    }
  }

  /**
   * Bottleneck the startElement event.  This is used to "pend" an
   * element, so that attributes can still be added to it before
   * the real "startElement" is called on the result tree listener.
   *
   * @param ns Namespace URI of element
   * @param localName Local part of qname of element
   * @param name Name of element
   * @param atts List of attributes for the element
   *
   * @throws org.xml.sax.SAXException
   */
  public void startElement(
          String ns, String localName, String name, Attributes atts)
            throws org.xml.sax.SAXException
  {

    if (DEBUG)
    {
      if (m_elemIsPending)
        System.out.println("(ResultTreeHandler#startElement - pended: "
                           + m_url + "#" + m_localName);

      System.out.println("ResultTreeHandler#startElement: " + ns + "#"
                         + localName);

      //      if(null == ns)
      //      {
      //        (new RuntimeException(localName+" has a null namespace!")).printStackTrace();
      //      }
    }

    if(m_docPending)
      checkForSerializerSwitch(ns, localName);
      
    flushPending(true);

    if (!m_nsContextPushed)
    {
      if (DEBUG)
        System.out.println(
          "ResultTreeHandler#startElement - push(startElement)");

      m_nsSupport.pushContext();

      m_nsContextPushed = true;
    }
    
    if (ns != null)
      ensurePrefixIsDeclared(ns, name);

    m_name = name;
    m_url = ns;
    m_localName = localName;

    if (null != atts)
      m_attributes.addAttributes(atts);

    m_elemIsPending = true;
    m_elemIsEnded = false;
    
    if(m_isTransformClient && (null != m_transformer))
    {
      m_snapshot.m_currentElement = m_transformer.getCurrentElement();
      m_snapshot.m_currentTemplate = m_transformer.getCurrentTemplate();
      m_snapshot.m_matchedTemplate = m_transformer.getMatchedTemplate();
      int currentNodeHandle = m_transformer.getCurrentNode();
      DTM dtm = m_transformer.getXPathContext().getDTM(currentNodeHandle);
      m_snapshot.m_currentNode = dtm.getNode(currentNodeHandle);
      m_snapshot.m_matchedNode = m_transformer.getMatchedNode();
      m_snapshot.m_contextNodeList = m_transformer.getContextNodeList(); // TODO: Need to clone
    }
    // initQSE(m_startElement);

    m_eventCount++;
  }

  /**
   * Bottleneck the endElement event.
   *
   * @param ns Namespace URI of element
   * @param localName Local part of qname of element
   * @param name Name of element
   *
   * @throws org.xml.sax.SAXException
   */
  public void endElement(String ns, String localName, String name)
          throws org.xml.sax.SAXException
  {

    if (DEBUG)
    {
      if (m_elemIsPending)
        System.out.println("(ResultTreeHandler#endElement - pended: "
                           + m_url + "#" + m_localName);

      System.out.println("ResultTreeHandler#endElement: " + ns + "#"
                         + localName);
    }

    flushPending(true);
    m_contentHandler.endElement(ns, localName, name);

    if (null != m_tracer)
    {
      GenerateEvent ge = new GenerateEvent(m_transformer,
                                           GenerateEvent.EVENTTYPE_ENDELEMENT,
                                           name, (Attributes)null);

      m_tracer.fireGenerateEvent(ge);
    }

    sendEndPrefixMappings();
    popEvent();

    if (DEBUG)
      System.out.println("ResultTreeHandler#startElement pop: " + localName);

    m_nsSupport.popContext();
  }

  /** Indicate whether a namespace context was pushed */
  boolean m_nsContextPushed = false;

  /**
   * Begin the scope of a prefix-URI Namespace mapping.
   *
   * <p>The information from this event is not necessary for
   * normal Namespace processing: the SAX XML reader will
   * automatically replace prefixes for element and attribute
   * names when the http://xml.org/sax/features/namespaces
   * feature is true (the default).</p>
   *
   * <p>There are cases, however, when applications need to
   * use prefixes in character data or in attribute values,
   * where they cannot safely be expanded automatically; the
   * start/endPrefixMapping event supplies the information
   * to the application to expand prefixes in those contexts
   * itself, if necessary.</p>
   *
   * <p>Note that start/endPrefixMapping events are not
   * guaranteed to be properly nested relative to each-other:
   * all startPrefixMapping events will occur before the
   * corresponding startElement event, and all endPrefixMapping
   * events will occur after the corresponding endElement event,
   * but their order is not guaranteed.</p>
   *
   * @param prefix The Namespace prefix being declared.
   * @param uri The Namespace URI the prefix is mapped to.
   * @throws org.xml.sax.SAXException The client may throw
   *            an exception during processing.
   * @see #endPrefixMapping
   * @see #startElement
   */
  public void startPrefixMapping(String prefix, String uri)
          throws org.xml.sax.SAXException
  {
    startPrefixMapping(prefix, uri, true);
  }

  /**
   * Begin the scope of a prefix-URI Namespace mapping.
   *
   *
   * @param prefix The Namespace prefix being declared.
   * @param uri The Namespace URI the prefix is mapped to.
   * @param shouldFlush Indicate whether pending events needs
   * to be flushed first
   *
   * @throws org.xml.sax.SAXException The client may throw
   *            an exception during processing.
   */
  public void startPrefixMapping(
          String prefix, String uri, boolean shouldFlush)
            throws org.xml.sax.SAXException
  {

    if (shouldFlush)
      flushPending(false);

    if (!m_nsContextPushed)
    {
      if (DEBUG)
        System.out.println(
          "ResultTreeHandler#startPrefixMapping push(startPrefixMapping: "
          + prefix + ")");

      m_nsSupport.pushContext();

      m_nsContextPushed = true;
    }

    if (null == prefix)
      prefix = "";  // bit-o-hack, that that's OK

    String existingURI = m_nsSupport.getURI(prefix);

    if (null == existingURI)
      existingURI = "";

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

    if (!existingURI.equals(uri))
    {
      if (DEBUG)
      {
        System.out.println("ResultTreeHandler#startPrefixMapping Prefix: "
                           + prefix);
        System.out.println("ResultTreeHandler#startPrefixMapping uri: "
                           + uri);
      }

      m_nsSupport.declarePrefix(prefix, uri);
    }
  }

  /**
   * End the scope of a prefix-URI mapping.
   *
   * <p>See startPrefixMapping for details.  This event will
   * always occur after the corresponding endElement event,
   * but the order of endPrefixMapping events is not otherwise
   * guaranteed.</p>
   *
   * @param prefix The prefix that was being mapping.
   * @throws org.xml.sax.SAXException The client may throw
   *            an exception during processing.
   * @see #startPrefixMapping
   * @see #endElement
   */
  public void endPrefixMapping(String prefix)
          throws org.xml.sax.SAXException{}

  /**
   * Bottleneck the characters event.
   *
   * @param ch Array of characters to process
   * @param start start of characters in the array
   * @param length Number of characters in the array
   *
   * @throws org.xml.sax.SAXException
   */
  public void characters(char ch[], int start, int length)
          throws org.xml.sax.SAXException
  {

    // It would be nice to suppress all whitespace before the
    // first element, but this is going to cause potential problems with 
    // text serialization and with text entities (right term?).
    // So this really needs to be done at the serializer level.

    /*if (m_startDoc.isPending
    && XMLCharacterRecognizer.isWhiteSpace(ch, start, length))
    return;*/
    if (DEBUG)
    {
      System.out.print("ResultTreeHandler#characters: ");

      int n = start + length;

      for (int i = start; i < n; i++)
      {
        if (Character.isWhitespace(ch[i]))
          System.out.print("\\" + ((int) ch[i]));
        else
          System.out.print(ch[i]);
      }

      System.out.println("");
    }

    flushPending(true);
    m_contentHandler.characters(ch, start, length);

    if (null != m_tracer)
    {
      GenerateEvent ge = new GenerateEvent(m_transformer,
                                           GenerateEvent.EVENTTYPE_CHARACTERS,
                                           ch, start, length);

      m_tracer.fireGenerateEvent(ge);
    }
  }
  
  public void characters(org.w3c.dom.Node node)
          throws org.xml.sax.SAXException
  {

    flushPending(true);
    
    if(m_isTransformClient)
      m_snapshot.m_currentNode = node;

    String data = node.getNodeValue();
    char [] ch = null;
    int length = 0;
    if (data != null)
    {
    ch = data.toCharArray();
    length = data.length();
    m_contentHandler.characters(ch, 0, length);
    }
    
    if (null != m_tracer)
    {
      GenerateEvent ge = new GenerateEvent(m_transformer,
                                           GenerateEvent.EVENTTYPE_CHARACTERS,
                                           ch, 0, length);

      m_tracer.fireGenerateEvent(ge);
    }  
    if(m_isTransformClient)
      m_snapshot.m_currentNode = null;
  }

  /**
   * Bottleneck the ignorableWhitespace event.
   *
   * @param ch Array of characters to process
   * @param start start of characters in the array
   * @param length Number of characters in the array
   *
   * @throws org.xml.sax.SAXException
   */
  public void ignorableWhitespace(char ch[], int start, int length)
          throws org.xml.sax.SAXException
  {

    if (m_docPending
            && XMLCharacterRecognizer.isWhiteSpace(ch, start, length))
      return;

    flushPending(true);
    m_contentHandler.ignorableWhitespace(ch, start, length);

    if (null != m_tracer)
    {
      GenerateEvent ge =
        new GenerateEvent(m_transformer,
                          GenerateEvent.EVENTTYPE_IGNORABLEWHITESPACE, ch,
                          start, length);

      m_tracer.fireGenerateEvent(ge);
    }
  }

  /**
   * Bottleneck the processingInstruction event.
   *
   * @param target Processing instruction target name
   * @param data Processing instruction data
   *
   * @throws org.xml.sax.SAXException
   */
  public void processingInstruction(String target, String data)
          throws org.xml.sax.SAXException
  {

    flushPending(true);
    m_contentHandler.processingInstruction(target, data);

    if (null != m_tracer)
    {
      GenerateEvent ge = new GenerateEvent(m_transformer,
                                           GenerateEvent.EVENTTYPE_PI,
                                           target, data);

      m_tracer.fireGenerateEvent(ge);
    }
  }

  /**
   * Bottleneck the comment event.
   *
   * @param data Comment data
   *
   * @throws org.xml.sax.SAXException
   */
  public void comment(String data) throws org.xml.sax.SAXException
  {

    flushPending(true);

    if (null != m_lexicalHandler)
    {
      m_lexicalHandler.comment(data.toCharArray(), 0, data.length());
    }

    if (null != m_tracer)
    {
      GenerateEvent ge = new GenerateEvent(m_transformer,
                                           GenerateEvent.EVENTTYPE_COMMENT,
                                           data);

      m_tracer.fireGenerateEvent(ge);
    }
  }

  /**
   * Bottleneck the comment event.
   *
   * @param ch Character array with comment data
   * @param start start of characters in the array
   * @param length number of characters in the array
   *
   * @throws org.xml.sax.SAXException
   */
  public void comment(char ch[], int start, int length)
          throws org.xml.sax.SAXException
  {

    flushPending(true);

    if (null != m_lexicalHandler)
    {
      m_lexicalHandler.comment(ch, start, length);
    }

    if (null != m_tracer)
    {
      GenerateEvent ge = new GenerateEvent(m_transformer,
                                           GenerateEvent.EVENTTYPE_COMMENT,
                                           new String(ch, start, length));

      m_tracer.fireGenerateEvent(ge);
    }
  }

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

    flushPending(true);

    if (null != m_lexicalHandler)
    {
      m_lexicalHandler.startEntity(name);
      m_lexicalHandler.endEntity(name);
    }

    if (null != m_tracer)
    {
      GenerateEvent ge = new GenerateEvent(m_transformer,
                                           GenerateEvent.EVENTTYPE_ENTITYREF,
                                           name);

      m_tracer.fireGenerateEvent(ge);
    }
  }

  /**
   * Start an entity.
   *
   * @param name Name of the entity
   *
   * @throws org.xml.sax.SAXException
   */
  public void startEntity(String name) throws org.xml.sax.SAXException
  {

    flushPending(true);

    if (null != m_lexicalHandler)
    {
      m_lexicalHandler.startEntity(name);
    }
  }

  /**
   * End an entity.
   *
   * @param name Name of the entity
   *
   * @throws org.xml.sax.SAXException
   */
  public void endEntity(String name) throws org.xml.sax.SAXException
  {

    flushPending(true);

    if (null != m_lexicalHandler)
    {
      m_lexicalHandler.endEntity(name);
    }

    if (null != m_tracer)
    {
      GenerateEvent ge = new GenerateEvent(m_transformer,
                                           GenerateEvent.EVENTTYPE_ENTITYREF,
                                           name);

      m_tracer.fireGenerateEvent(ge);
    }
  }

  /**
   * Start the DTD.
   *
   * @param s1 The document type name.
   * @param s2 The declared public identifier for the
   *        external DTD subset, or null if none was declared.
   * @param s3 The declared system identifier for the
   *        external DTD subset, or null if none was declared.
   *
   * @throws org.xml.sax.SAXException
   */
  public void startDTD(String s1, String s2, String s3)
          throws org.xml.sax.SAXException
  {

    flushPending(true);

    if (null != m_lexicalHandler)
    {
      m_lexicalHandler.startDTD(s1, s2, s3);
    }
  }

  /**
   * End the DTD.
   *
   * @throws org.xml.sax.SAXException
   */
  public void endDTD() throws org.xml.sax.SAXException
  {

    flushPending(true);

    if (null != m_lexicalHandler)
    {
      m_lexicalHandler.endDTD();
    }
  }

  /**
   * Start the CDATACharacters.
   *
   * @throws org.xml.sax.SAXException
   */
  public void startCDATA() throws org.xml.sax.SAXException
  {

    flushPending(true);

    if (null != m_lexicalHandler)
    {
      m_lexicalHandler.startCDATA();
    }
  }

  /**
   * End the CDATA characters.
   *
   * @throws org.xml.sax.SAXException
   */
  public void endCDATA() throws org.xml.sax.SAXException
  {

    flushPending(true);

    if (null != m_lexicalHandler)
    {
      m_lexicalHandler.endCDATA();
    }
  }

  /**
   * Receive notification of a skipped entity.
   *
   * <p>The Parser will invoke this method once for each entity
   * skipped.  Non-validating processors may skip entities if they
   * have not seen the declarations (because, for example, the
   * entity was declared in an external DTD subset).  All processors
   * may skip external entities, depending on the values of the
   * http://xml.org/sax/features/external-general-entities and the
   * http://xml.org/sax/features/external-parameter-entities
   * properties.</p>
   *
   * @param name The name of the skipped entity.  If it is a
   *        parameter entity, the name will begin with '%'.
   * @throws org.xml.sax.SAXException Any SAX exception, possibly
   *            wrapping another exception.
   */
  public void skippedEntity(String name) throws org.xml.sax.SAXException{}

  /**
   * Set whether Namespace declarations have been added to
   * this element
   *
   *
   * @param b Flag indicating whether Namespace declarations
   * have been added to this element
   */
  public void setNSDeclsHaveBeenAdded(boolean b)
  {

    m_nsDeclsHaveBeenAdded = b;
  }

  /**
   * Flush the event.
   *
   * @throws TransformerException
   *
   * @throws org.xml.sax.SAXException
   */
  void flushDocEvent() throws org.xml.sax.SAXException
  {

    if (m_docPending)
    {
      m_contentHandler.startDocument();

      if (null != m_tracer)
      {
        GenerateEvent ge =
          new GenerateEvent(m_transformer,
                            GenerateEvent.EVENTTYPE_STARTDOCUMENT);

        m_tracer.fireGenerateEvent(ge);
      }

      if (m_contentHandler instanceof TransformerClient)
      {
        ((TransformerClient) m_contentHandler).setTransformState(this);
      }

      m_docPending = false;
    }
  }
  
  /**
   * Flush the event.
   *
   * @throws SAXException
   */
  void flushElem() throws org.xml.sax.SAXException
  {

    if (m_elemIsPending)
    {
      if (null != m_name)
      {
        try
        {
          m_contentHandler.startElement(m_url, m_localName, m_name,
                                      m_attributes);
        }
        catch(Exception re)
        {
          // If we don't do this, and the exception is a RuntimeException, 
          // good line numbers of where the exception occured in the stylesheet
          // won't get reported.  I tried just catching RuntimeException, but 
          // for whatever reason it didn't seem to catch.
          // Fix for Christina's DOMException error problem.
          throw new SAXParseException(re.getMessage(), 
          m_transformer.getCurrentElement().getPublicId(), 
          m_transformer.getCurrentElement().getSystemId(), 
          m_transformer.getCurrentElement().getLineNumber(), 
          m_transformer.getCurrentElement().getColumnNumber(), 
          re);
        }
        
        if(null != m_tracer)
        {
          GenerateEvent ge =
            new GenerateEvent(m_transformer,
                              GenerateEvent.EVENTTYPE_STARTELEMENT, m_name,
                                      m_attributes);
  
          m_tracer.fireGenerateEvent(ge);
        }
        if(m_isTransformClient)
          m_snapshot.m_currentNode = null;
      }

      m_elemIsPending = false;
      m_attributes.clear();
  
      m_nsDeclsHaveBeenAdded = false;
      m_name = null;
      m_url = null;
      m_localName = null;
      m_namespaces = null;

      // super.flush();
    }
  }


  /**
   * Flush the pending element.
   *
   * @throws org.xml.sax.SAXException
   */
  public final void flushPending() throws org.xml.sax.SAXException
  {
    flushPending(true);
  }

  /**
   * Flush the pending element, and any attributes associated with it.
   *
   * NOTE: If there are attributes but _no_ pending element (which can
   * happen if the user's stylesheet is doing something inappropriate),
   * we still want to make sure they are flushed.
   *
   * @param type Event type
   *
   * NEEDSDOC @param flushPrefixes
   *
   * @throws org.xml.sax.SAXException
   */
  public final void flushPending(boolean flushPrefixes)
          throws org.xml.sax.SAXException
  {

    if (flushPrefixes && m_docPending)
    {
      flushDocEvent();
    }

    if (m_elemIsPending)
    {
      // Combined loop shoud be much more efficient.
      // %REVIEW% %OPT% Will the "else" case ever arise?
      if (!m_nsDeclsHaveBeenAdded)
//        addNSDeclsToAttrs();
          startAndAddPrefixMappings();  // new
      else                              // new
          sendStartPrefixMappings();


      if (DEBUG)
      {
        System.out.println("ResultTreeHandler#flushPending - start flush: "
                           + m_name);
      }

      flushElem();

      if (DEBUG)
      {
        System.out.println(
          "ResultTreeHandler#flushPending - after flush, isPending: "
          + m_elemIsPending);
      }

      m_nsContextPushed = false;
    }
  }

  /**
   * Given a result tree fragment, walk the tree and
   * output it to the result stream.
   *
   * @param obj Result tree fragment object
   * @param support XPath context for the result tree fragment
   *
   * @throws org.xml.sax.SAXException
   */
  public void outputResultTreeFragment(XObject obj, XPathContext support)
          throws org.xml.sax.SAXException
  {

    int doc = obj.rtf();
    DTM dtm = support.getDTM(doc);

    for (int n = dtm.getFirstChild(doc); DTM.NULL != n;
            n = dtm.getNextSibling(n))
    {
      flushPending(true);  // I think.
      dtm.dispatchToEvents(n, this);
    }
  }

  /**
   * To fullfill the FormatterListener interface... no action
   * for the moment.
   *
   * @param locator Document locator
   */
  public void setDocumentLocator(Locator locator){}

  /**
   * This function checks to make sure a given prefix is really
   * declared.  It might not be, because it may be an excluded prefix.
   * If it's not, it still needs to be declared at this point.
   * TODO: This needs to be done at an earlier stage in the game... -sb
   *
   * @param ns Namespace URI of the element
   * @param rawName Raw name of element (with prefix)
   *
   * @throws org.xml.sax.SAXException
   */
  public void ensurePrefixIsDeclared(String ns, String rawName)
          throws org.xml.sax.SAXException
  {

    if (ns != null && ns.length() > 0)
    {
      int index;
      String prefix = (index = rawName.indexOf(":")) < 0
                      ? "" : rawName.substring(0, index);

      if (null != prefix)
      {
        String foundURI = m_nsSupport.getURI(prefix);

        if ((null == foundURI) ||!foundURI.equals(ns))
        {
          startPrefixMapping(prefix, ns, false);
                                        
          // Bugzilla1133: Generate attribute as well as namespace event.
          // SAX does expect both.

          m_attributes.addAttribute("http://www.w3.org/2000/xmlns/", 
                                    prefix, 
                                    "xmlns"+(prefix.length()==0 ? "" : ":")+prefix, 
                                    "CDATA", ns);
        }
      }
    }
  }

  /**
   * This function checks to make sure a given prefix is really
   * declared.  It might not be, because it may be an excluded prefix.
   * If it's not, it still needs to be declared at this point.
   * TODO: This needs to be done at an earlier stage in the game... -sb
   *
   * @param ns Namespace URI of the element
   * @param rawName Raw name of element (with prefix)
   *
   * NEEDSDOC @param dtm
   * NEEDSDOC @param namespace
   *
   * @throws org.xml.sax.SAXException
   */
  public void ensureNamespaceDeclDeclared(DTM dtm, int namespace)
          throws org.xml.sax.SAXException
  {

    String uri = dtm.getNodeValue(namespace);
    String prefix = dtm.getNodeNameX(namespace);

    if ((uri != null && uri.length() > 0) && (null != prefix))
    {
      String foundURI = m_nsSupport.getURI(prefix);

      if ((null == foundURI) ||!foundURI.equals(uri))
      {
        startPrefixMapping(prefix, uri, false);
      }
    }
  }

  /**
   * Add the attributes that have been declared to the attribute list.
   * (Seems like I shouldn't have to do this...)
   * Internally deprecated in favor of combined startAndAddPrefixMappings();
   * 
   *
   * @throws org.xml.sax.SAXException
   */
  protected void sendStartPrefixMappings() throws org.xml.sax.SAXException
  {
    Enumeration prefixes = m_nsSupport.getDeclaredPrefixes();
    ContentHandler handler = m_contentHandler;
    while (prefixes.hasMoreElements())
    {
      String prefix = (String) prefixes.nextElement();
      handler.startPrefixMapping(prefix, m_nsSupport.getURI(prefix));
    }
  }

  /**
   * Combination of sendStartPrefixMappings and
   * addNSDeclsToAttrs() (which it mostly replaces).  Merging the two
   * loops is significantly more efficient.
   *
   * @throws org.xml.sax.SAXException */
  protected void startAndAddPrefixMappings() throws org.xml.sax.SAXException
  {

    Enumeration prefixes = m_nsSupport.getDeclaredPrefixes();
    ContentHandler handler = m_contentHandler;

    while (prefixes.hasMoreElements())
    {
      String prefix = (String) prefixes.nextElement();
      String uri=m_nsSupport.getURI(prefix);
      
      // Send event
      handler.startPrefixMapping(prefix, uri);

      // Set attribute
      boolean isDefault = (prefix.length() == 0);
      String name;

      if (isDefault)
      {
        //prefix = "xml";
        name = "xmlns";
      }
      else
        name = "xmlns:" + prefix;

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

      m_attributes.addAttribute("http://www.w3.org/2000/xmlns/", 
                                prefix, name, "CDATA", uri);
    }
    m_nsDeclsHaveBeenAdded=true;
  }

  /**
   * Add the attributes that have been declared to the attribute list.
   * (Seems like I shouldn't have to do this...)
   *
   * @throws org.xml.sax.SAXException
   */
  protected void sendEndPrefixMappings() throws org.xml.sax.SAXException
  {

    Enumeration prefixes = m_nsSupport.getDeclaredPrefixes();
    ContentHandler handler = m_contentHandler;

    while (prefixes.hasMoreElements())
    {
      String prefix = (String) prefixes.nextElement();

      handler.endPrefixMapping(prefix);
    }
  }

  /**
   * Check to see if we should switch serializers based on the
   * first output element being an HTML element.
   *
   * @param ns Namespace URI of the element
   * @param localName Local part of name of the element
   *
   * @throws org.xml.sax.SAXException
   */
  private void checkForSerializerSwitch(String ns, String localName)
          throws org.xml.sax.SAXException
  {

    try
    {
      if (m_docPending)
      {
        SerializerSwitcher.switchSerializerIfHTML(m_transformer, ns,
                                                  localName);
      }
    }
    catch (TransformerException te)
    {
      throw new org.xml.sax.SAXException(te);
    }
  }

  /**
   * Add the attributes that have been declared to the attribute list.
   *
   * %REVIEW% This should have been done automatically during
   * flushPending(boolean); is it ever explicitly reinvoked?
   */
  public void addNSDeclsToAttrs()
  {

    Enumeration prefixes = m_nsSupport.getDeclaredPrefixes();

    while (prefixes.hasMoreElements())
    {
      String prefix = (String) prefixes.nextElement();
      boolean isDefault = (prefix.length() == 0);
      String name;

      if (isDefault)
      {

        //prefix = "xml";
        name = "xmlns";
      }
      else
        name = "xmlns:" + prefix;

      String uri = m_nsSupport.getURI(prefix);

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

      m_attributes.addAttribute("http://www.w3.org/2000/xmlns/", 
                                prefix, name, "CDATA", uri);
    }

    m_nsDeclsHaveBeenAdded = true;
  }

  /**
   * Copy <KBD>xmlns:</KBD> attributes in if not already in scope.
   * 
   * As a quick hack to support ClonerToResultTree, this can also be used
   * to copy an individual namespace node.
   *
   * @param src Source Node
   * NEEDSDOC @param type
   * NEEDSDOC @param dtm
   *
   * @throws TransformerException
   */
  public void processNSDecls(int src, int type, DTM dtm)
          throws TransformerException
  {

    try
    {
      if (type == DTM.ELEMENT_NODE)
      {
        for (int namespace = dtm.getFirstNamespaceNode(src, true);
                DTM.NULL != namespace;
                namespace = dtm.getNextNamespaceNode(src, namespace, true))
        {

          // String prefix = dtm.getPrefix(namespace);
          String prefix = dtm.getNodeNameX(namespace);
          String desturi = getURI(prefix);
          String srcURI = dtm.getNodeValue(namespace);

          if (!srcURI.equalsIgnoreCase(desturi))
          {
            this.startPrefixMapping(prefix, srcURI, false);
          }
        }
      }
      else if (type == DTM.NAMESPACE_NODE)
			{
          String prefix = dtm.getNodeNameX(src);
          String desturi = getURI(prefix);
          String srcURI = dtm.getNodeValue(src);

          if (!srcURI.equalsIgnoreCase(desturi))
          {
            this.startPrefixMapping(prefix, srcURI, false);
          }
			}
    }
    catch (org.xml.sax.SAXException se)
    {
      throw new TransformerException(se);
    }
  }

  /**
   * Given a prefix, return the namespace,
   *
   * @param prefix Given prefix name
   *
   * @return Namespace associated with the given prefix, or null
   */
  public String getURI(String prefix)
  {
    return m_nsSupport.getURI(prefix);
  }

  /**
   * Given a namespace, try and find a prefix.
   *
   * @param namespace Given namespace URI
   *
   * @return Prefix name associated with namespace URI
   */
  public String getPrefix(String namespace)
  {

    // This Enumeration business may be too slow for our purposes...
    Enumeration enum = m_nsSupport.getPrefixes();

    while (enum.hasMoreElements())
    {
      String prefix = (String) enum.nextElement();

      if (m_nsSupport.getURI(prefix).equals(namespace))
        return prefix;
    }

    return null;
  }

  /**
   * Get the NamespaceSupport object.
   *
   * @return NamespaceSupport object.
   */
  public NamespaceSupport getNamespaceSupport()
  {
    return m_nsSupport;
  }

  //  /**
  //   * Override QueuedEvents#initQSE.
  //   *
  //   * @param qse Give queued Sax event
  //   */
  //  protected void initQSE(QueuedSAXEvent qse)
  //  {
  //
  //    // qse.setContentHandler(m_contentHandler);
  //    // qse.setTransformer(m_transformer);
  //    // qse.setTraceManager(m_tracer);
  //  }

  /**
   * Return the current content handler.
   *
   * @return The current content handler, or null if none
   *         has been registered.
   * @see #setContentHandler
   */
  public final ContentHandler getContentHandler()
  {
    return m_contentHandler;
  }

  /**
   * Set the current content handler.
   *
   *
   * @param ch Content Handler to be set
   * @return The current content handler, or null if none
   *         has been registered.
   * @see #getContentHandler
   */
  public void setContentHandler(ContentHandler ch)
  {

    m_contentHandler = ch;

    m_isTransformClient = (m_contentHandler instanceof TransformerClient);

    if (m_contentHandler instanceof LexicalHandler)
      m_lexicalHandler = (LexicalHandler) m_contentHandler;
    else
      m_lexicalHandler = null;

    reInitEvents();
  }

  /**
   * Get a unique namespace value.
   *
   * @return a unique namespace value to be used with a
   * fabricated prefix
   */
  public int getUniqueNSValue()
  {
    return m_uniqueNSValue++;
  }

  /**
   * Get new unique namespace prefix.
   *
   * @return Unique fabricated prefix.
   */
  public String getNewUniqueNSPrefix()
  {
    return S_NAMESPACEPREFIX + String.valueOf(getUniqueNSValue());
  }

  /**
   * Get the pending attributes.  We have to delay the call to
   * m_flistener.startElement(name, atts) because of the
   * xsl:attribute and xsl:copy calls.  In other words,
   * the attributes have to be fully collected before you
   * can call startElement.
   *
   * @return the pending attributes.
   */
  public MutableAttrListImpl getPendingAttributes()
  {
    return m_attributes;
  }

  /**
   * Add an attribute to the end of the list.
   *
   * <p>Do not pass in xmlns decls to this function!
   *
   * <p>For the sake of speed, this method does no checking
   * to see if the attribute is already in the list: that is
   * the responsibility of the application.</p>
   *
   * @param uri The Namespace URI, or the empty string if
   *        none is available or Namespace processing is not
   *        being performed.
   * @param localName The local name, or the empty string if
   *        Namespace processing is not being performed.
   * @param rawName The raw XML 1.0 name, or the empty string
   *        if raw names are not available.
   * @param type The attribute type as a string.
   * @param value The attribute value.
   *
   * @throws TransformerException
   */
  public void addAttribute(
          String uri, String localName, String rawName, String type, String value)
            throws TransformerException
  {
    // %REVIEW% See Bugzilla 4344. Do we need an "else" that announces
    // an error? Technically, this can't happen unless the stylesheet
    // is unreasonable... but it's unclear whether silent or noisy
    // failure is called for.
    if (m_elemIsPending)
    {
      // %REVIEW% %OPT% Is this ever needed?????
      if (!m_nsDeclsHaveBeenAdded)
	addNSDeclsToAttrs();

      if (null == uri)  // defensive, should not really need this.
	uri = "";

      try
      {
	if (!rawName.equals("xmlns"))  // don't handle xmlns default namespace.
	  ensurePrefixIsDeclared(uri, rawName);
      }
      catch (org.xml.sax.SAXException se)
      {
	throw new TransformerException(se);
      }
      
      if (DEBUG)
	System.out.println("ResultTreeHandler#addAttribute Adding attr: "
			   + localName + ", " + uri);

      if (!isDefinedNSDecl(rawName, value))
	m_attributes.addAttribute(uri, localName, rawName, type, value);
    }
  }

  /**
   * Return whether or not a namespace declaration is defined
   *
   *
   * @param rawName Raw name of namespace element
   * @param value URI of given namespace
   *
   * @return True if the namespace is already defined in list of
   * namespaces
   */
  public boolean isDefinedNSDecl(String rawName, String value)
  {

    if (rawName.equals("xmlns") || rawName.startsWith("xmlns:"))
    {
      int index;
      String prefix = (index = rawName.indexOf(":")) < 0
                      ? "" : rawName.substring(0, index);
      String definedURI = m_nsSupport.getURI(prefix);

      if (null != definedURI)
      {
        if (definedURI.equals(value))
        {
          return true;
        }
        else
          return false;
      }
      else
        return false;
    }
    else
      return false;
  }

  /**
   * Returns whether a namespace is defined
   *
   *
   * @param attr Namespace attribute node
   *
   * @return True if the namespace is already defined in
   * list of namespaces
   */
  public boolean isDefinedNSDecl(int attr)
  {

    DTM dtm = m_transformer.getXPathContext().getDTM(attr);

    if (DTM.NAMESPACE_NODE == dtm.getNodeType(attr))
    {

      // String prefix = dtm.getPrefix(attr);
      String prefix = dtm.getNodeNameX(attr);
      String uri = getURI(prefix);

      if ((null != uri) && uri.equals(dtm.getStringValue(attr)))
        return true;
    }

    return false;
  }

  /**
   * Returns whether a namespace is defined
   *
   *
   * @param attr Namespace attribute node
   * @param dtm The DTM that owns attr.
   *
   * @return True if the namespace is already defined in
   * list of namespaces
   */
  public boolean isDefinedNSDecl(int attr, DTM dtm)
  {

    if (DTM.NAMESPACE_NODE == dtm.getNodeType(attr))
    {

      // String prefix = dtm.getPrefix(attr);
      String prefix = dtm.getNodeNameX(attr);
      String uri = getURI(prefix);

      if ((null != uri) && uri.equals(dtm.getStringValue(attr)))
        return true;
    }

    return false;
  }

  /**
   * Copy an DOM attribute to the created output element, executing
   * attribute templates as need be, and processing the xsl:use
   * attribute.
   *
   * @param attr Attribute node to add to result tree
   *
   * @throws TransformerException
   */
  public void addAttribute(int attr) throws TransformerException
  {

    DTM dtm = m_transformer.getXPathContext().getDTM(attr);

    if (isDefinedNSDecl(attr, dtm))
      return;

    String ns = dtm.getNamespaceURI(attr);

    if (ns == null)
      ns = "";

    // %OPT% ...can I just store the node handle?    
    addAttribute(ns, dtm.getLocalName(attr), dtm.getNodeName(attr), "CDATA",
                 dtm.getNodeValue(attr));
  }  // end copyAttributeToTarget method

  /**
   * Copy DOM attributes to the result element.
   *
   * @param src Source node with the attributes
   *
   * @throws TransformerException
   */
  public void addAttributes(int src) throws TransformerException
  {

    DTM dtm = m_transformer.getXPathContext().getDTM(src);

    for (int node = dtm.getFirstAttribute(src); DTM.NULL != node;
            node = dtm.getNextAttribute(node))
    {
      addAttribute(node);
    }
  }

  /**
   * Tell if an element is pending, to be output to the result tree.
   *
   * @return True if an element is pending
   */
  public final boolean isElementPending()
  {
    
    return m_elemIsPending;
  }

  /**
   * Retrieves the stylesheet element that produced
   * the SAX event.
   *
   * <p>Please note that the ElemTemplateElement returned may
   * be in a default template, and thus may not be
   * defined in the stylesheet.</p>
   *
   * @return the stylesheet element that produced the SAX event.
   */
  public ElemTemplateElement getCurrentElement()
  {

    if (m_elemIsPending)
      return m_snapshot.m_currentElement;
    else
      return m_transformer.getCurrentElement();
  }

  /**
   * This method retrieves the current context node
   * in the source tree.
   *
   * @return the current context node in the source tree.
   */
  public org.w3c.dom.Node getCurrentNode()
  {
    
    if (m_snapshot.m_currentNode != null)
    {
      return m_snapshot.m_currentNode;
    }
    else
    {
      DTM dtm = m_transformer.getXPathContext().getDTM(m_transformer.getCurrentNode());
      return dtm.getNode(m_transformer.getCurrentNode());
    }
  }

  /**
   * This method retrieves the xsl:template
   * that is in effect, which may be a matched template
   * or a named template.
   *
   * <p>Please note that the ElemTemplate returned may
   * be a default template, and thus may not have a template
   * defined in the stylesheet.</p>
   *
   * @return the xsl:template that is in effect
   */
  public ElemTemplate getCurrentTemplate()
  {

    if (m_elemIsPending)
      return m_snapshot.m_currentTemplate;
    else
      return m_transformer.getCurrentTemplate();
  }

  /**
   * This method retrieves the xsl:template
   * that was matched.  Note that this may not be
   * the same thing as the current template (which
   * may be from getCurrentElement()), since a named
   * template may be in effect.
   *
   * <p>Please note that the ElemTemplate returned may
   * be a default template, and thus may not have a template
   * defined in the stylesheet.</p>
   *
   * @return the xsl:template that was matched.
   */
  public ElemTemplate getMatchedTemplate()
  {

    if (m_elemIsPending)
      return m_snapshot.m_matchedTemplate;
    else
      return m_transformer.getMatchedTemplate();
  }

  /**
   * Retrieves the node in the source tree that matched
   * the template obtained via getMatchedTemplate().
   *
   * @return the node in the source tree that matched
   * the template obtained via getMatchedTemplate().
   */
  public org.w3c.dom.Node getMatchedNode()
  {

    if (m_elemIsPending)
    {
      DTM dtm = m_transformer.getXPathContext().getDTM(m_snapshot.m_matchedNode);
      return dtm.getNode(m_snapshot.m_matchedNode);
    }
    else
    {
      DTM dtm = m_transformer.getXPathContext().getDTM(m_transformer.getMatchedNode());
      return dtm.getNode(m_transformer.getMatchedNode());
    }
  }

  /**
   * Get the current context node list.
   *
   * @return the current context node list.
   */
  public org.w3c.dom.traversal.NodeIterator getContextNodeList()
  {

    if (m_elemIsPending)
    {
      return new org.apache.xml.dtm.ref.DTMNodeIterator(m_snapshot.m_contextNodeList);
    }
    else
      return new org.apache.xml.dtm.ref.DTMNodeIterator(m_transformer.getContextNodeList());
  }

  /**
   * Get the TrAX Transformer object in effect.
   *
   * @return the TrAX Transformer object in effect.
   */
  public Transformer getTransformer()
  {
    return m_transformer;
  }
  
  
  // Implement ErrorHandler
  
  /**
    * Receive notification of a warning.
    *
    * <p>SAX parsers will use this method to report conditions that
    * are not errors or fatal errors as defined by the XML 1.0
    * recommendation.  The default behaviour is to take no action.</p>
    *
    * <p>The SAX parser must continue to provide normal parsing events
    * after invoking this method: it should still be possible for the
    * application to process the document through to the end.</p>
    *
    * <p>Filters may use this method to report other, non-XML warnings
    * as well.</p>
    *
    * @param exception The warning information encapsulated in a
    *                  SAX parse exception.
    * @exception org.xml.sax.SAXException Any SAX exception, possibly
    *            wrapping another exception.
    * @see org.xml.sax.SAXParseException 
    */
  public void warning (SAXParseException exception)
    throws SAXException
  {
    if (m_contentHandler instanceof ErrorHandler)
      ((ErrorHandler)m_contentHandler).warning(exception);
  }
    
    
   /**
    * Receive notification of a recoverable error.
    *
    * <p>This corresponds to the definition of "error" in section 1.2
    * of the W3C XML 1.0 Recommendation.  For example, a validating
    * parser would use this callback to report the violation of a
    * validity constraint.  The default behaviour is to take no
    * action.</p>
    *
    * <p>The SAX parser must continue to provide normal parsing events
    * after invoking this method: it should still be possible for the
    * application to process the document through to the end.  If the
    * application cannot do so, then the parser should report a fatal
    * error even if the XML 1.0 recommendation does not require it to
    * do so.</p>
    *
    * <p>Filters may use this method to report other, non-XML errors
    * as well.</p>
    *
    * @param exception The error information encapsulated in a
    *                  SAX parse exception.
    * @exception org.xml.sax.SAXException Any SAX exception, possibly
    *            wrapping another exception.
    * @see org.xml.sax.SAXParseException 
    */
  public void error (SAXParseException exception)
    throws SAXException
  {
    if (m_contentHandler instanceof ErrorHandler)
      ((ErrorHandler)m_contentHandler).error(exception);
  }
    
    
   /**
    * Receive notification of a non-recoverable error.
    *
    * <p>This corresponds to the definition of "fatal error" in
    * section 1.2 of the W3C XML 1.0 Recommendation.  For example, a
    * parser would use this callback to report the violation of a
    * well-formedness constraint.</p>
    *
    * <p>The application must assume that the document is unusable
    * after the parser has invoked this method, and should continue
    * (if at all) only for the sake of collecting addition error
    * messages: in fact, SAX parsers are free to stop reporting any
    * other events once this method has been invoked.</p>
    *
    * @param exception The error information encapsulated in a
    *                  SAX parse exception.  
    * @exception org.xml.sax.SAXException Any SAX exception, possibly
    *            wrapping another exception.
    * @see org.xml.sax.SAXParseException
    */
  public void fatalError (SAXParseException exception)
    throws SAXException
  {      
    m_elemIsPending = false;
    m_docEnded = true;
    m_docPending = false;
    
    if (m_contentHandler instanceof ErrorHandler)
      ((ErrorHandler)m_contentHandler).fatalError(exception);
  }
  
  boolean m_isTransformClient = false;

  /**
   * Use the SAX2 helper class to track result namespaces.
   */
  NamespaceSupport m_nsSupport = new NamespaceSupport2();

  /**
   * The transformer object.
   */
  private TransformerImpl m_transformer;

  /**
   * The content handler.  May be null, in which
   * case, we'll defer to the content handler in the
   * transformer.
   */
  private ContentHandler m_contentHandler;

  /** The LexicalHandler */
  private LexicalHandler m_lexicalHandler;

  /**
   * The root of a linked set of stylesheets.
   */
  private StylesheetRoot m_stylesheetRoot = null;

  /**
   * This is used whenever a unique namespace is needed.
   */
  private int m_uniqueNSValue = 0;

  /** Prefix used to create unique prefix names */
  private static final String S_NAMESPACEPREFIX = "ns";

  /**
   * This class clones nodes to the result tree.
   */
  public ClonerToResultTree m_cloner;

  /**
   * Trace manager for debug support.
   */
  private TraceManager m_tracer;
  
  private QueuedStateSnapshot m_snapshot = new QueuedStateSnapshot();

  // These are passed to flushPending, to help it decide if it 
  // should really flush.
  
  class QueuedStateSnapshot
  {
    /**
     * The stylesheet element that produced the SAX event.
     */
    ElemTemplateElement m_currentElement;
    
    /**
     * The current context node in the source tree.
     */
    org.w3c.dom.Node m_currentNode;
    
    /**
     * The xsl:template that is in effect, which may be a matched template
     * or a named template.
     */
    ElemTemplate m_currentTemplate;
    
    /**
     * The xsl:template that was matched.
     */
    ElemTemplate m_matchedTemplate;
    
    /**
     * The node in the source tree that matched
     * the template obtained via getMatchedTemplate().
     */
    int m_matchedNode;
    
    /**
     * The current context node list.
     */
    DTMIterator m_contextNodeList;
  }
}
