/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2003 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.xml.utils;

import org.apache.xml.res.XMLMessages;
import org.apache.xml.res.XMLErrorResources;
import org.apache.xml.utils.NodeVector;
import java.util.Stack;

import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.Attributes;

import org.w3c.dom.*;  // we pretty much use everything in the DOM here.

/**
 * <meta name="usage" content="general"/>
 * This class takes SAX events (in addition to some extra events
 * that SAX doesn't handle yet) and adds the result to a document
 * or document fragment.
 */
public class DOMBuilder
        implements ContentHandler, LexicalHandler
{

  /** Root document          */
  public Document m_doc;

  /** Current node           */
  protected Node m_currentNode = null;

  /** First node of document fragment or null if not a DocumentFragment     */
  public DocumentFragment m_docFrag = null;

  /** Vector of element nodes          */
  protected Stack m_elemStack = new Stack();

  /**
   * DOMBuilder instance constructor... it will add the DOM nodes
   * to the document fragment.
   *
   * @param doc Root document
   * @param node Current node
   */
  public DOMBuilder(Document doc, Node node)
  {
    m_doc = doc;
    m_currentNode = node;
  }

  /**
   * DOMBuilder instance constructor... it will add the DOM nodes
   * to the document fragment.
   *
   * @param doc Root document
   * @param docFrag Document fragment
   */
  public DOMBuilder(Document doc, DocumentFragment docFrag)
  {
    m_doc = doc;
    m_docFrag = docFrag;
  }

  /**
   * DOMBuilder instance constructor... it will add the DOM nodes
   * to the document.
   *
   * @param doc Root document
   */
  public DOMBuilder(Document doc)
  {
    m_doc = doc;
  }

  /**
   * Get the root node of the DOM being created.  This
   * is either a Document or a DocumentFragment.
   *
   * @return The root document or document fragment if not null
   */
  public Node getRootNode()
  {
    return (null != m_docFrag) ? (Node) m_docFrag : (Node) m_doc;
  }

  /**
   * Get the node currently being processed.
   *
   * @return the current node being processed
   */
  public Node getCurrentNode()
  {
    return m_currentNode;
  }

  /**
   * Return null since there is no Writer for this class.
   *
   * @return null
   */
  public java.io.Writer getWriter()
  {
    return null;
  }

  /**
   * Append a node to the current container.
   *
   * @param newNode New node to append
   */
  protected void append(Node newNode) throws org.xml.sax.SAXException
  {

    Node currentNode = m_currentNode;

    if (null != currentNode)
    {
      currentNode.appendChild(newNode);

      // System.out.println(newNode.getNodeName());
    }
    else if (null != m_docFrag)
    {
      m_docFrag.appendChild(newNode);
    }
    else
    {
      boolean ok = true;
      short type = newNode.getNodeType();

      if (type == Node.TEXT_NODE)
      {
        String data = newNode.getNodeValue();

        if ((null != data) && (data.trim().length() > 0))
        {
          throw new org.xml.sax.SAXException(
            XMLMessages.createXMLMessage(
              XMLErrorResources.ER_CANT_OUTPUT_TEXT_BEFORE_DOC, null));  //"Warning: can't output text before document element!  Ignoring...");
        }

        ok = false;
      }
      else if (type == Node.ELEMENT_NODE)
      {
        if (m_doc.getDocumentElement() != null)
        {
          throw new org.xml.sax.SAXException(
            XMLMessages.createXMLMessage(
              XMLErrorResources.ER_CANT_HAVE_MORE_THAN_ONE_ROOT, null));  //"Can't have more than one root on a DOM!");
        }
      }

      if (ok)
        m_doc.appendChild(newNode);
    }
  }

  /**
   * 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 ContentHandler
   * 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>
   *
   * @param locator An object that can return the location of
   *                any SAX document event.
   * @see org.xml.sax.Locator
   */
  public void setDocumentLocator(Locator locator)
  {

    // No action for the moment.
  }

  /**
   * Receive notification of the beginning of a document.
   *
   * <p>The SAX parser will invoke this method only once, before any
   * other methods in this interface or in DTDHandler (except for
   * setDocumentLocator).</p>
   */
  public void startDocument() throws org.xml.sax.SAXException
  {

    // No action for the moment.
  }

  /**
   * Receive notification of the end of a document.
   *
   * <p>The SAX parser will invoke this method only once, and it will
   * be the last method invoked during the parse.  The parser shall
   * not invoke this method until it has either abandoned parsing
   * (because of an unrecoverable error) or reached the end of
   * input.</p>
   */
  public void endDocument() throws org.xml.sax.SAXException
  {

    // No action for the moment.
  }

  /**
   * Receive notification of the beginning of an element.
   *
   * <p>The Parser will invoke this method at the beginning of every
   * element in the XML document; there will be a corresponding
   * endElement() event for every startElement() event (even when the
   * element is empty). All of the element's content will be
   * reported, in order, before the corresponding endElement()
   * event.</p>
   *
   * <p>If the element name has a namespace prefix, the prefix will
   * still be attached.  Note that the attribute list provided will
   * contain only attributes with explicit values (specified or
   * defaulted): #IMPLIED attributes will be omitted.</p>
   *
   *
   * @param ns The namespace of the node
   * @param localName The local part of the qualified name 
   * @param name The element name.
   * @param atts The attributes attached to the element, if any.
   * @see #endElement
   * @see org.xml.sax.Attributes
   */
  public void startElement(
          String ns, String localName, String name, Attributes atts)
            throws org.xml.sax.SAXException
  {

    Element elem;

	// Note that the namespace-aware call must be used to correctly
	// construct a Level 2 DOM, even for non-namespaced nodes.
    if ((null == ns) || (ns.length() == 0))
      elem = m_doc.createElementNS(null,name);
    else
      elem = m_doc.createElementNS(ns, name);

    append(elem);

    try
    {
      int nAtts = atts.getLength();
  
      if (0 != nAtts)
      {
        for (int i = 0; i < nAtts; i++)
        {
  
          //System.out.println("type " + atts.getType(i) + " name " + atts.getLocalName(i) );
          // First handle a possible ID attribute
          if (atts.getType(i).equalsIgnoreCase("ID"))
            setIDAttribute(atts.getValue(i), elem);
  
          String attrNS = atts.getURI(i);
          
          if("".equals(attrNS))
            attrNS = null; // DOM represents no-namespace as null
  
          // System.out.println("attrNS: "+attrNS+", localName: "+atts.getQName(i)
          //                   +", qname: "+atts.getQName(i)+", value: "+atts.getValue(i));
          // Crimson won't let us set an xmlns: attribute on the DOM.
          String attrQName = atts.getQName(i);
          // ALWAYS use the DOM Level 2 call!
          elem.setAttributeNS(attrNS,attrQName, atts.getValue(i));
        }
      }
      
      // append(elem);
  
      m_elemStack.push(elem);
  
      m_currentNode = elem;
      
      // append(elem);
    }
    catch(java.lang.Exception de)
    {
      // de.printStackTrace();
      throw new org.xml.sax.SAXException(de);
    }
    
  }

  /**
   * Receive notification of the end of an element.
   *
   * <p>The SAX parser will invoke this method at the end of every
   * element in the XML document; there will be a corresponding
   * startElement() event for every endElement() event (even when the
   * element is empty).</p>
   *
   * <p>If the element name has a namespace prefix, the prefix will
   * still be attached to the name.</p>
   *
   *
   * @param ns the namespace of the element
   * @param localName The local part of the qualified name of the element
   * @param name The element name
   */
  public void endElement(String ns, String localName, String name)
          throws org.xml.sax.SAXException
  {
    m_elemStack.pop();
    m_currentNode = m_elemStack.isEmpty() ? null : (Node)m_elemStack.peek();
  }

  /**
   * Set an ID string to node association in the ID table.
   *
   * @param id The ID string.
   * @param elem The associated ID.
   */
  public void setIDAttribute(String id, Element elem)
  {

    // Do nothing. This method is meant to be overiden.
  }

  /**
   * Receive notification of character data.
   *
   * <p>The Parser will call this method to report each chunk of
   * character data.  SAX parsers may return all contiguous character
   * data in a single chunk, or they may split it into several
   * chunks; however, all of the characters in any single event
   * must come from the same external entity, so that the Locator
   * provides useful information.</p>
   *
   * <p>The application must not attempt to read from the array
   * outside of the specified range.</p>
   *
   * <p>Note that some parsers will report whitespace using the
   * ignorableWhitespace() method rather than this one (validating
   * parsers must do so).</p>
   *
   * @param ch The characters from the XML document.
   * @param start The start position in the array.
   * @param length The number of characters to read from the array.
   * @see #ignorableWhitespace
   * @see org.xml.sax.Locator
   */
  public void characters(char ch[], int start, int length) throws org.xml.sax.SAXException
  {
    if(isOutsideDocElem()
       && org.apache.xml.utils.XMLCharacterRecognizer.isWhiteSpace(ch, start, length))
      return;  // avoid DOM006 Hierarchy request error

    if (m_inCData)
    {
      cdata(ch, start, length);

      return;
    }

    String s = new String(ch, start, length);
    Text text = m_doc.createTextNode(s);

    append(text);
  }

  /**
   * If available, when the disable-output-escaping attribute is used,
   * output raw text without escaping.  A PI will be inserted in front
   * of the node with the name "lotusxsl-next-is-raw" and a value of
   * "formatter-to-dom".
   *
   * @param ch Array containing the characters
   * @param start Index to start of characters in the array
   * @param length Number of characters in the array 
   */
  public void charactersRaw(char ch[], int start, int length)
          throws org.xml.sax.SAXException
  {
    if(isOutsideDocElem()  
       && org.apache.xml.utils.XMLCharacterRecognizer.isWhiteSpace(ch, start, length))
      return;  // avoid DOM006 Hierarchy request error


    String s = new String(ch, start, length);

    append(m_doc.createProcessingInstruction("xslt-next-is-raw",
                                             "formatter-to-dom"));
    append(m_doc.createTextNode(s));
  }

  /**
   * Report the beginning of an entity.
   *
   * The start and end of the document entity are not reported.
   * 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.
   *
   * @param name The name of the entity.  If it is a parameter
   *        entity, the name will begin with '%'.
   * @see #endEntity
   * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
   * @see org.xml.sax.ext.DeclHandler#externalEntityDecl
   */
  public void startEntity(String name) throws org.xml.sax.SAXException
  {

    // Almost certainly the wrong behavior...
    // entityReference(name);
  }

  /**
   * Report the end of an entity.
   *
   * @param name The name of the entity that is ending.
   * @see #startEntity
   */
  public void endEntity(String name) throws org.xml.sax.SAXException{}

  /**
   * Receive notivication of a entityReference.
   *
   * @param name name of the entity reference
   */
  public void entityReference(String name) throws org.xml.sax.SAXException
  {
    append(m_doc.createEntityReference(name));
  }

  /**
   * Receive notification of ignorable whitespace in element content.
   *
   * <p>Validating Parsers must use this method to report each chunk
   * of ignorable whitespace (see the W3C XML 1.0 recommendation,
   * section 2.10): non-validating parsers may also use this method
   * if they are capable of parsing and using content models.</p>
   *
   * <p>SAX parsers may return all contiguous whitespace in a single
   * chunk, or they may split it into several chunks; however, all of
   * the characters in any single event must come from the same
   * external entity, so that the Locator provides useful
   * information.</p>
   *
   * <p>The application must not attempt to read from the array
   * outside of the specified range.</p>
   *
   * @param ch The characters from the XML document.
   * @param start The start position in the array.
   * @param length The number of characters to read from the array.
   * @see #characters
   */
  public void ignorableWhitespace(char ch[], int start, int length)
          throws org.xml.sax.SAXException
  {
    if(isOutsideDocElem())
      return;  // avoid DOM006 Hierarchy request error

    String s = new String(ch, start, length);

    append(m_doc.createTextNode(s));
  }
  
  /**
   * Tell if the current node is outside the document element.
   * 
   * @return true if the current node is outside the document element.
   */
   private boolean isOutsideDocElem()
   {
      return (null == m_docFrag) && m_elemStack.size() == 0 && (null == m_currentNode || m_currentNode.getNodeType() == Node.DOCUMENT_NODE);
   }

  /**
   * Receive notification of a processing instruction.
   *
   * <p>The Parser will invoke this method once for each processing
   * instruction found: note that processing instructions may occur
   * before or after the main document element.</p>
   *
   * <p>A SAX parser should never report an XML declaration (XML 1.0,
   * section 2.8) or a text declaration (XML 1.0, section 4.3.1)
   * using this method.</p>
   *
   * @param target The processing instruction target.
   * @param data The processing instruction data, or null if
   *        none was supplied.
   */
  public void processingInstruction(String target, String data)
          throws org.xml.sax.SAXException
  {
    append(m_doc.createProcessingInstruction(target, data));
  }

  /**
   * Report an XML comment anywhere in the document.
   *
   * This callback will be used for comments inside or outside the
   * document element, including comments in the external DTD
   * subset (if read).
   *
   * @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.
   */
  public void comment(char ch[], int start, int length) throws org.xml.sax.SAXException
  {
    append(m_doc.createComment(new String(ch, start, length)));
  }

  /** Flag indicating that we are processing a CData section          */
  protected boolean m_inCData = false;

  /**
   * Report the start of a CDATA section.
   *
   * @see #endCDATA
   */
  public void startCDATA() throws org.xml.sax.SAXException
  {
    m_inCData = true;
  }

  /**
   * Report the end of a CDATA section.
   *
   * @see #startCDATA
   */
  public void endCDATA() throws org.xml.sax.SAXException
  {
    m_inCData = false;
  }

  /**
   * Receive notification of cdata.
   *
   * <p>The Parser will call this method to report each chunk of
   * character data.  SAX parsers may return all contiguous character
   * data in a single chunk, or they may split it into several
   * chunks; however, all of the characters in any single event
   * must come from the same external entity, so that the Locator
   * provides useful information.</p>
   *
   * <p>The application must not attempt to read from the array
   * outside of the specified range.</p>
   *
   * <p>Note that some parsers will report whitespace using the
   * ignorableWhitespace() method rather than this one (validating
   * parsers must do so).</p>
   *
   * @param ch The characters from the XML document.
   * @param start The start position in the array.
   * @param length The number of characters to read from the array.
   * @see #ignorableWhitespace
   * @see org.xml.sax.Locator
   */
  public void cdata(char ch[], int start, int length) throws org.xml.sax.SAXException
  {
    if(isOutsideDocElem()  
       && org.apache.xml.utils.XMLCharacterRecognizer.isWhiteSpace(ch, start, length))
      return;  // avoid DOM006 Hierarchy request error

    String s = new String(ch, start, length);

    append(m_doc.createCDATASection(s));
  }

  /**
   * Report the start of DTD declarations, if any.
   *
   * Any declarations are assumed to be in the internal subset
   * unless otherwise indicated.
   *
   * @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.
   * @see #endDTD
   * @see #startEntity
   */
  public void startDTD(String name, String publicId, String systemId)
          throws org.xml.sax.SAXException
  {

    // Do nothing for now.
  }

  /**
   * Report the end of DTD declarations.
   *
   * @see #startDTD
   */
  public void endDTD() throws org.xml.sax.SAXException
  {

    // Do nothing for now.
  }

  /**
   * 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.
   * @see #endPrefixMapping
   * @see #startElement
   */
  public void startPrefixMapping(String prefix, String uri)
          throws org.xml.sax.SAXException
  {

    /*
    // Not sure if this is needed or wanted
    // Also, it fails in the stree.
    if((null != m_currentNode)
       && (m_currentNode.getNodeType() == Node.ELEMENT_NODE))
    {
      String qname;
      if(((null != prefix) && (prefix.length() == 0))
         || (null == prefix))
        qname = "xmlns";
      else
        qname = "xmlns:"+prefix;

      Element elem = (Element)m_currentNode;
      String val = elem.getAttribute(qname); // Obsolete, should be DOM2...?
      if(val == null)
      {
        elem.setAttributeNS("http://www.w3.org/XML/1998/namespace",
                            qname, 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.
   * @see #startPrefixMapping
   * @see #endElement
   */
  public void endPrefixMapping(String prefix) throws org.xml.sax.SAXException{}

  /**
   * 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 '%'.
   */
  public void skippedEntity(String name) throws org.xml.sax.SAXException{}
}
