/*
 * 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$
 */
package org.apache.xalan.transformer;

import java.io.IOException;

import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.sax.TransformerHandler;

import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMManager;
import org.apache.xml.dtm.ref.IncrementalSAXSource_Filter;
import org.apache.xml.dtm.ref.sax2dtm.SAX2DTM;
import org.apache.xpath.XPathContext;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.ext.LexicalHandler;
import org.apache.xml.serializer.SerializationHandler;


/**
 * A TransformerHandler
 * listens for SAX ContentHandler parse events and transforms
 * them to a Result.
 */
public class TransformerHandlerImpl
        implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler,
                   LexicalHandler, TransformerHandler, DeclHandler
{
    /**
     * The flag for the setting of the optimize feature;
     */    
    private final boolean m_optimizer;

    /**
     * The flag for the setting of the incremental feature;
     */    
    private final boolean m_incremental;

    /**
     * The flag for the setting of the source_location feature;
     */  
    private final boolean m_source_location;
  
  private boolean m_insideParse = false;

  ////////////////////////////////////////////////////////////////////
  // Constructors.
  ////////////////////////////////////////////////////////////////////

  /**
   * Construct a TransformerHandlerImpl.
   *
   * @param transformer Non-null reference to the Xalan transformer impl.
   * @param doFragment True if the result should be a document fragement.
   * @param baseSystemID  The system ID to use as the base for relative URLs.
   */
  public TransformerHandlerImpl(TransformerImpl transformer,
                                boolean doFragment, String baseSystemID)
  {

    super();

    m_transformer = transformer;
    m_baseSystemID = baseSystemID;

    XPathContext xctxt = transformer.getXPathContext();
    DTM dtm = xctxt.getDTM(null, true, transformer, true, true);
    
    m_dtm = dtm;
    dtm.setDocumentBaseURI(baseSystemID);

    m_contentHandler = dtm.getContentHandler();
    m_dtdHandler = dtm.getDTDHandler();
    m_entityResolver = dtm.getEntityResolver();
    m_errorHandler = dtm.getErrorHandler();
    m_lexicalHandler = dtm.getLexicalHandler();
    m_incremental = transformer.getIncremental();
    m_optimizer = transformer.getOptimize();
    m_source_location = transformer.getSource_location();
  }
  
  /** 
   * Do what needs to be done to shut down the CoRoutine management.
   */
  protected void clearCoRoutine()
  {
    clearCoRoutine(null);
  }
  
  /** 
   * Do what needs to be done to shut down the CoRoutine management.
   */
  protected void clearCoRoutine(SAXException ex)
  {
    if(null != ex)
      m_transformer.setExceptionThrown(ex);
    
    if(m_dtm instanceof SAX2DTM)
    {
      if(DEBUG)
        System.err.println("In clearCoRoutine...");
      try
      {
        SAX2DTM sax2dtm = ((SAX2DTM)m_dtm);          
        if(null != m_contentHandler 
           && m_contentHandler instanceof IncrementalSAXSource_Filter)
        {
          IncrementalSAXSource_Filter sp =
            (IncrementalSAXSource_Filter)m_contentHandler;
          // This should now be all that's needed.
          sp.deliverMoreNodes(false);
        }
        
        sax2dtm.clearCoRoutine(true);
        m_contentHandler = null;
        m_dtdHandler = null;
        m_entityResolver = null;
        m_errorHandler = null;
        m_lexicalHandler = null;
      }
      catch(Throwable throwable)
      {
        throwable.printStackTrace();
      }
      
      if(DEBUG)
        System.err.println("...exiting clearCoRoutine");
    }
  }
  
  ////////////////////////////////////////////////////////////////////
  // Implementation of javax.xml.transform.sax.TransformerHandler.
  ////////////////////////////////////////////////////////////////////

  /**
   * Enables the user of the TransformerHandler to set the
   * to set the Result for the transformation.
   *
   * @param result A Result instance, should not be null.
   *
   * @throws IllegalArgumentException if result is invalid for some reason.
   */
  public void setResult(Result result) throws IllegalArgumentException
  {

    if (null == result)
      throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_RESULT_NULL, null)); //"result should not be null");

    try
    {
//      ContentHandler handler =
//        m_transformer.createResultContentHandler(result);
//      m_transformer.setContentHandler(handler);
        SerializationHandler xoh = 
            m_transformer.createSerializationHandler(result);
        m_transformer.setSerializationHandler(xoh);
    }
    catch (javax.xml.transform.TransformerException te)
    {
      throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_RESULT_COULD_NOT_BE_SET, null)); //"result could not be set");
    }

    m_result = result;
  }

  /**
   * Set the base ID (URI or system ID) from where relative
   * URLs will be resolved.
   * @param systemID Base URI for the source tree.
   */
  public void setSystemId(String systemID)
  {
    m_baseSystemID = systemID;
    m_dtm.setDocumentBaseURI(systemID);
  }

  /**
   * Get the base ID (URI or system ID) from where relative
   * URLs will be resolved.
   * @return The systemID that was set with {@link #setSystemId}.
   */
  public String getSystemId()
  {
    return m_baseSystemID;
  }

  /**
   * Get the Transformer associated with this handler, which
   * is needed in order to set parameters and output properties.
   *
   * @return The Transformer associated with this handler
   */
  public Transformer getTransformer()
  {
    return m_transformer;
  }

  ////////////////////////////////////////////////////////////////////
  // Implementation of org.xml.sax.EntityResolver.
  ////////////////////////////////////////////////////////////////////

  /**
   * Filter an external entity resolution.
   *
   * @param publicId The entity's public identifier, or null.
   * @param systemId The entity's system identifier.
   * @return A new InputSource or null for the default.
   *
   * @throws IOException
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @throws java.io.IOException The client may throw an
   *            I/O-related exception while obtaining the
   *            new InputSource.
   * @see org.xml.sax.EntityResolver#resolveEntity
   */
  public InputSource resolveEntity(String publicId, String systemId)
          throws SAXException, IOException
  {

    if (m_entityResolver != null)
    {
      return m_entityResolver.resolveEntity(publicId, systemId);
    }
    else
    {
      return null;
    }
  }

  ////////////////////////////////////////////////////////////////////
  // Implementation of org.xml.sax.DTDHandler.
  ////////////////////////////////////////////////////////////////////

  /**
   * Filter a notation declaration event.
   *
   * @param name The notation name.
   * @param publicId The notation's public identifier, or null.
   * @param systemId The notation's system identifier, or null.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.DTDHandler#notationDecl
   */
  public void notationDecl(String name, String publicId, String systemId)
          throws SAXException
  {

    if (m_dtdHandler != null)
    {
      m_dtdHandler.notationDecl(name, publicId, systemId);
    }
  }

  /**
   * Filter an unparsed entity declaration event.
   *
   * @param name The entity name.
   * @param publicId The entity's public identifier, or null.
   * @param systemId The entity's system identifier, or null.
   * @param notationName The name of the associated notation.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
   */
  public void unparsedEntityDecl(
          String name, String publicId, String systemId, String notationName)
            throws SAXException
  {

    if (m_dtdHandler != null)
    {
      m_dtdHandler.unparsedEntityDecl(name, publicId, systemId, notationName);
    }
  }

  ////////////////////////////////////////////////////////////////////
  // Implementation of org.xml.sax.ContentHandler.
  ////////////////////////////////////////////////////////////////////

  /**
   * Filter a new document locator event.
   *
   * @param locator The document locator.
   * @see org.xml.sax.ContentHandler#setDocumentLocator
   */
  public void setDocumentLocator(Locator locator)
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#setDocumentLocator: "
                         + locator.getSystemId());

    this.m_locator = locator;
    
    if(null == m_baseSystemID)
    {
      setSystemId(locator.getSystemId());
    }

    if (m_contentHandler != null)
    {
      m_contentHandler.setDocumentLocator(locator);
    }
  }

  /**
   * Filter a start document event.
   *
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ContentHandler#startDocument
   */
  public void startDocument() throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#startDocument");
      
    m_insideParse = true;

   // Thread listener = new Thread(m_transformer);

    if (m_contentHandler != null)
    {
      //m_transformer.setTransformThread(listener);
      if(m_incremental)
      {
        m_transformer.setSourceTreeDocForThread(m_dtm.getDocument());
            
        int cpriority = Thread.currentThread().getPriority();
    
        // runTransformThread is equivalent with the 2.0.1 code,
        // except that the Thread may come from a pool.
        m_transformer.runTransformThread( cpriority );
      }

      // This is now done _last_, because IncrementalSAXSource_Filter
      // will immediately go into a "wait until events are requested"
      // pause. I believe that will close our timing window.
      // %REVIEW%
      m_contentHandler.startDocument();
   }
        
   //listener.setDaemon(false);
   //listener.start();

  }

  /**
   * Filter an end document event.
   *
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ContentHandler#endDocument
   */
  public void endDocument() throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#endDocument");

    m_insideParse = false;
    
    if (m_contentHandler != null)
    {
      m_contentHandler.endDocument();
    }
    
    if(m_incremental)
    {
      m_transformer.waitTransformThread();
    }
    else
    {
      m_transformer.setSourceTreeDocForThread(m_dtm.getDocument());
      m_transformer.run();
    }
   /* Thread transformThread = m_transformer.getTransformThread();

    if (null != transformThread)
    {
      try
      {

        // This should wait until the transformThread is considered not alive.
        transformThread.join();

        if (!m_transformer.hasTransformThreadErrorCatcher())
        {
          Exception e = m_transformer.getExceptionThrown();

          if (null != e)
            throw new org.xml.sax.SAXException(e);
        }

        m_transformer.setTransformThread(null);
      }
      catch (InterruptedException ie){}
    }*/
  }

  /**
   * Filter a start Namespace prefix mapping event.
   *
   * @param prefix The Namespace prefix.
   * @param uri The Namespace URI.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ContentHandler#startPrefixMapping
   */
  public void startPrefixMapping(String prefix, String uri)
          throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#startPrefixMapping: "
                         + prefix + ", " + uri);

    if (m_contentHandler != null)
    {
      m_contentHandler.startPrefixMapping(prefix, uri);
    }
  }

  /**
   * Filter an end Namespace prefix mapping event.
   *
   * @param prefix The Namespace prefix.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ContentHandler#endPrefixMapping
   */
  public void endPrefixMapping(String prefix) throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#endPrefixMapping: "
                         + prefix);

    if (m_contentHandler != null)
    {
      m_contentHandler.endPrefixMapping(prefix);
    }
  }

  /**
   * Filter a start element event.
   *
   * @param uri The element's Namespace URI, or the empty string.
   * @param localName The element's local name, or the empty string.
   * @param qName The element's qualified (prefixed) name, or the empty
   *        string.
   * @param atts The element's attributes.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ContentHandler#startElement
   */
  public void startElement(
          String uri, String localName, String qName, Attributes atts)
            throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#startElement: " + qName);

    if (m_contentHandler != null)
    {
      m_contentHandler.startElement(uri, localName, qName, atts);
    }
  }

  /**
   * Filter an end element event.
   *
   * @param uri The element's Namespace URI, or the empty string.
   * @param localName The element's local name, or the empty string.
   * @param qName The element's qualified (prefixed) name, or the empty
   *        string.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ContentHandler#endElement
   */
  public void endElement(String uri, String localName, String qName)
          throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#endElement: " + qName);

    if (m_contentHandler != null)
    {
      m_contentHandler.endElement(uri, localName, qName);
    }
  }

  /**
   * Filter a character data event.
   *
   * @param ch An array of characters.
   * @param start The starting position in the array.
   * @param length The number of characters to use from the array.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ContentHandler#characters
   */
  public void characters(char ch[], int start, int length) throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#characters: " + start + ", "
                         + length);

    if (m_contentHandler != null)
    {
      m_contentHandler.characters(ch, start, length);
    }
  }

  /**
   * Filter an ignorable whitespace event.
   *
   * @param ch An array of characters.
   * @param start The starting position in the array.
   * @param length The number of characters to use from the array.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ContentHandler#ignorableWhitespace
   */
  public void ignorableWhitespace(char ch[], int start, int length)
          throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#ignorableWhitespace: "
                         + start + ", " + length);

    if (m_contentHandler != null)
    {
      m_contentHandler.ignorableWhitespace(ch, start, length);
    }
  }

  /**
   * Filter a processing instruction event.
   *
   * @param target The processing instruction target.
   * @param data The text following the target.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ContentHandler#processingInstruction
   */
  public void processingInstruction(String target, String data)
          throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#processingInstruction: "
                         + target + ", " + data);

    if (m_contentHandler != null)
    {
      m_contentHandler.processingInstruction(target, data);
    }
  }

  /**
   * Filter a skipped entity event.
   *
   * @param name The name of the skipped entity.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ContentHandler#skippedEntity
   */
  public void skippedEntity(String name) throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#skippedEntity: " + name);

    if (m_contentHandler != null)
    {
      m_contentHandler.skippedEntity(name);
    }
  }

  ////////////////////////////////////////////////////////////////////
  // Implementation of org.xml.sax.ErrorHandler.
  ////////////////////////////////////////////////////////////////////

  /**
   * Filter a warning event.
   *
   * @param e The nwarning as an exception.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ErrorHandler#warning
   */
  public void warning(SAXParseException e) throws SAXException
  {
    // This is not great, but we really would rather have the error 
    // handler be the error listener if it is a error handler.  Coroutine's fatalError 
    // can't really be configured, so I think this is the best thing right now 
    // for error reporting.  Possibly another JAXP 1.1 hole.  -sb
    javax.xml.transform.ErrorListener errorListener = m_transformer.getErrorListener();
    if(errorListener instanceof ErrorHandler)
    {
      ((ErrorHandler)errorListener).warning(e);
    }
    else
    {
      try
      {
        errorListener.warning(new javax.xml.transform.TransformerException(e));
      }
      catch(javax.xml.transform.TransformerException te)
      {
        throw e;
      }
    }
  }

  /**
   * Filter an error event.
   *
   * @param e The error as an exception.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ErrorHandler#error
   */
  public void error(SAXParseException e) throws SAXException
  {
    // %REVIEW% I don't think this should be called.  -sb
    // clearCoRoutine(e);

    // This is not great, but we really would rather have the error 
    // handler be the error listener if it is a error handler.  Coroutine's fatalError 
    // can't really be configured, so I think this is the best thing right now 
    // for error reporting.  Possibly another JAXP 1.1 hole.  -sb
    javax.xml.transform.ErrorListener errorListener = m_transformer.getErrorListener();
    if(errorListener instanceof ErrorHandler)
    {
      ((ErrorHandler)errorListener).error(e);
      if(null != m_errorHandler)
        m_errorHandler.error(e); // may not be called.
    }
    else
    {
      try
      {
        errorListener.error(new javax.xml.transform.TransformerException(e));
        if(null != m_errorHandler)
          m_errorHandler.error(e); // may not be called.
      }
      catch(javax.xml.transform.TransformerException te)
      {
        throw e;
      }
    }
  }

  /**
   * Filter a fatal error event.
   *
   * @param e The error as an exception.
   * @throws SAXException The client may throw
   *            an exception during processing.
   * @see org.xml.sax.ErrorHandler#fatalError
   */
  public void fatalError(SAXParseException e) throws SAXException
  {
    if(null != m_errorHandler)
    {
      try
      {
        m_errorHandler.fatalError(e);
      }
      catch(SAXParseException se)
      {
        // ignore
      }
      // clearCoRoutine(e);
    }

    // This is not great, but we really would rather have the error 
    // handler be the error listener if it is a error handler.  Coroutine's fatalError 
    // can't really be configured, so I think this is the best thing right now 
    // for error reporting.  Possibly another JAXP 1.1 hole.  -sb
    javax.xml.transform.ErrorListener errorListener = m_transformer.getErrorListener();
    
    if(errorListener instanceof ErrorHandler)
    {
      ((ErrorHandler)errorListener).fatalError(e);
      if(null != m_errorHandler)
        m_errorHandler.fatalError(e); // may not be called.
    }
    else
    {
      try
      {
        errorListener.fatalError(new javax.xml.transform.TransformerException(e));
        if(null != m_errorHandler)
          m_errorHandler.fatalError(e); // may not be called.
      }
      catch(javax.xml.transform.TransformerException te)
      {
        throw e;
      }
    }
  }

  ////////////////////////////////////////////////////////////////////
  // Implementation of org.xml.sax.ext.LexicalHandler.
  ////////////////////////////////////////////////////////////////////

  /**
   * Report the start of DTD declarations, if any.
   *
   * <p>Any declarations are assumed to be in the internal subset
   * unless otherwise indicated by a {@link #startEntity startEntity}
   * event.</p>
   *
   * <p>Note that the start/endDTD events will appear within
   * the start/endDocument events from ContentHandler and
   * before the first startElement event.</p>
   *
   * @param name The document type name.
   * @param publicId The declared public identifier for the
   *        external DTD subset, or null if none was declared.
   * @param systemId The declared system identifier for the
   *        external DTD subset, or null if none was declared.
   * @throws SAXException The application may raise an
   *            exception.
   * @see #endDTD
   * @see #startEntity
   */
  public void startDTD(String name, String publicId, String systemId)
          throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#startDTD: " + name + ", "
                         + publicId + ", " + systemId);

    if (null != m_lexicalHandler)
    {
      m_lexicalHandler.startDTD(name, publicId, systemId);
    }
  }

  /**
   * Report the end of DTD declarations.
   *
   * @throws SAXException The application may raise an exception.
   * @see #startDTD
   */
  public void endDTD() throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#endDTD");

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

  /**
   * Report the beginning of an entity in content.
   *
   * <p><strong>NOTE:</entity> entity references in attribute
   * values -- and the start and end of the document entity --
   * are never reported.</p>
   *
   * <p>The start and end of the external DTD subset are reported
   * using the pseudo-name "[dtd]".  All other events must be
   * properly nested within start/end entity events.</p>
   *
   * <p>Note that skipped entities will be reported through the
   * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity}
   * event, which is part of the ContentHandler interface.</p>
   *
   * @param name The name of the entity.  If it is a parameter
   *        entity, the name will begin with '%'.
   * @throws SAXException The application may raise an exception.
   * @see #endEntity
   * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
   * @see org.xml.sax.ext.DeclHandler#externalEntityDecl
   */
  public void startEntity(String name) throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#startEntity: " + name);

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

  /**
   * Report the end of an entity.
   *
   * @param name The name of the entity that is ending.
   * @throws SAXException The application may raise an exception.
   * @see #startEntity
   */
  public void endEntity(String name) throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#endEntity: " + name);

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

  /**
   * Report the start of a CDATA section.
   *
   * <p>The contents of the CDATA section will be reported through
   * the regular {@link org.xml.sax.ContentHandler#characters
   * characters} event.</p>
   *
   * @throws SAXException The application may raise an exception.
   * @see #endCDATA
   */
  public void startCDATA() throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#startCDATA");

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

  /**
   * Report the end of a CDATA section.
   *
   * @throws SAXException The application may raise an exception.
   * @see #startCDATA
   */
  public void endCDATA() throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#endCDATA");

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

  /**
   * Report an XML comment anywhere in the document.
   *
   * <p>This callback will be used for comments inside or outside the
   * document element, including comments in the external DTD
   * subset (if read).</p>
   *
   * @param ch An array holding the characters in the comment.
   * @param start The starting position in the array.
   * @param length The number of characters to use from the array.
   * @throws SAXException The application may raise an exception.
   */
  public void comment(char ch[], int start, int length) throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#comment: " + start + ", "
                         + length);

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

  ////////////////////////////////////////////////////////////////////
  // Implementation of org.xml.sax.ext.DeclHandler.
  ////////////////////////////////////////////////////////////////////

  /**
   * Report an element type declaration.
   *
   * <p>The content model will consist of the string "EMPTY", the
   * string "ANY", or a parenthesised group, optionally followed
   * by an occurrence indicator.  The model will be normalized so
   * that all whitespace is removed,and will include the enclosing
   * parentheses.</p>
   *
   * @param name The element type name.
   * @param model The content model as a normalized string.
   * @throws SAXException The application may raise an exception.
   */
  public void elementDecl(String name, String model) throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#elementDecl: " + name + ", "
                         + model);

    if (null != m_declHandler)
    {
      m_declHandler.elementDecl(name, model);
    }
  }

  /**
   * Report an attribute type declaration.
   *
   * <p>Only the effective (first) declaration for an attribute will
   * be reported.  The type will be one of the strings "CDATA",
   * "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY",
   * "ENTITIES", or "NOTATION", or a parenthesized token group with
   * the separator "|" and all whitespace removed.</p>
   *
   * @param eName The name of the associated element.
   * @param aName The name of the attribute.
   * @param type A string representing the attribute type.
   * @param valueDefault A string representing the attribute default
   *        ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if
   *        none of these applies.
   * @param value A string representing the attribute's default value,
   *        or null if there is none.
   * @throws SAXException The application may raise an exception.
   */
  public void attributeDecl(
          String eName, String aName, String type, String valueDefault, String value)
            throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#attributeDecl: " + eName
                         + ", " + aName + ", etc...");

    if (null != m_declHandler)
    {
      m_declHandler.attributeDecl(eName, aName, type, valueDefault, value);
    }
  }

  /**
   * Report an internal entity declaration.
   *
   * <p>Only the effective (first) declaration for each entity
   * will be reported.</p>
   *
   * @param name The name of the entity.  If it is a parameter
   *        entity, the name will begin with '%'.
   * @param value The replacement text of the entity.
   * @throws SAXException The application may raise an exception.
   * @see #externalEntityDecl
   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
   */
  public void internalEntityDecl(String name, String value)
          throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#internalEntityDecl: " + name
                         + ", " + value);

    if (null != m_declHandler)
    {
      m_declHandler.internalEntityDecl(name, value);
    }
  }

  /**
   * Report a parsed external entity declaration.
   *
   * <p>Only the effective (first) declaration for each entity
   * will be reported.</p>
   *
   * @param name The name of the entity.  If it is a parameter
   *        entity, the name will begin with '%'.
   * @param publicId The declared public identifier of the entity, or
   *        null if none was declared.
   * @param systemId The declared system identifier of the entity.
   * @throws SAXException The application may raise an exception.
   * @see #internalEntityDecl
   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
   */
  public void externalEntityDecl(
          String name, String publicId, String systemId) throws SAXException
  {

    if (DEBUG)
      System.out.println("TransformerHandlerImpl#externalEntityDecl: " + name
                         + ", " + publicId + ", " + systemId);

    if (null != m_declHandler)
    {
      m_declHandler.externalEntityDecl(name, publicId, systemId);
    }
  }

  ////////////////////////////////////////////////////////////////////
  // Internal state.
  ////////////////////////////////////////////////////////////////////

  /** Set to true for diagnostics output.         */
  private static boolean DEBUG = false;

  /**
   * The transformer this will use to transform a
   * source tree into a result tree.
   */
  private TransformerImpl m_transformer;

  /** The system ID to use as a base for relative URLs. */
  private String m_baseSystemID;

  /** The result for the transformation. */
  private Result m_result = null;

  /** The locator for this TransformerHandler. */
  private Locator m_locator = null;

  /** The entity resolver to aggregate to. */
  private EntityResolver m_entityResolver = null;

  /** The DTD handler to aggregate to. */
  private DTDHandler m_dtdHandler = null;

  /** The content handler to aggregate to. */
  private ContentHandler m_contentHandler = null;

  /** The error handler to aggregate to. */
  private ErrorHandler m_errorHandler = null;

  /** The lexical handler to aggregate to. */
  private LexicalHandler m_lexicalHandler = null;

  /** The decl handler to aggregate to. */
  private DeclHandler m_declHandler = null;
  
  /** The Document Table Instance we are transforming. */
  DTM m_dtm;
}
