/*
 * 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 java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import org.xml.sax.InputSource;

/**
 * @deprecated Since the introduction of the DTM, this class will be removed.
 * This class provides a DOM level 2 "helper", which provides services currently 
 * not provided be the DOM standard.
 */
public class DOM2Helper extends DOMHelper
{

  /**
   * Construct an instance.
   */
  public DOM2Helper(){}

  /**
   * Check node to see if it was created by a DOM implementation
   * that this helper is intended to support. This is currently
   * disabled, and assumes all nodes are acceptable rather than checking
   * that they implement org.apache.xerces.dom.NodeImpl.
   *
   * @param node The node to be tested.
   *
   * @throws TransformerException if the node is not one which this
   * DOM2Helper can support. If we return without throwing the exception,
   * the node is compatable.
   * @xsl.usage internal
   */
  public void checkNode(Node node) throws TransformerException
  {

    // if(!(node instanceof org.apache.xerces.dom.NodeImpl))
    //  throw new TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_XERCES_CANNOT_HANDLE_NODES, new Object[]{((Object)node).getClass()})); //"DOM2Helper can not handle nodes of type"
    //+((Object)node).getClass());
  }

  /**
   * Returns true if the DOM implementation handled by this helper
   * supports the SAX ContentHandler interface.
   *
   * @return true (since Xerces does).
   */
  public boolean supportsSAX()
  {
    return true;
  }

  /** Field m_doc: Document Node for the document this helper is currently
   * accessing or building
   * @see #setDocument
   * @see #getDocument
   *  */
  private Document m_doc;

  /**
   * Specify which document this helper is currently operating on.
   * 	
   * @param doc The DOM Document node for this document.
   * @see #getDocument
   */
  public void setDocument(Document doc)
  {
    m_doc = doc;
  }

  /**
   * Query which document this helper is currently operating on.
   * 	
   * @return The DOM Document node for this document.
   * @see #setDocument
   */
  public Document getDocument()
  {
    return m_doc;
  }

  /**
   * Parse an XML document.
   *
   * <p>Right now the Xerces DOMParser class is used.  This needs
   * fixing, either via jaxp, or via some other, standard method.</p>
   *
   * <p>The application can use this method to instruct the SAX parser
   * to begin parsing an XML document from any valid input
   * source (a character stream, a byte stream, or a URI).</p>
   *
   * <p>Applications may not invoke this method while a parse is in
   * progress (they should create a new Parser instead for each
   * additional XML document).  Once a parse is complete, an
   * application may reuse the same Parser object, possibly with a
   * different input source.</p>
   *
   * @param source The input source for the top-level of the
   *        XML document.
   *
   * @throws TransformerException if any checked exception is thrown.
   * @xsl.usage internal
   */
  public void parse(InputSource source) throws TransformerException
  {

    try
    {

      // I guess I should use JAXP factory here... when it's legal.
      // org.apache.xerces.parsers.DOMParser parser 
      //  = new org.apache.xerces.parsers.DOMParser();
      DocumentBuilderFactory builderFactory =
        DocumentBuilderFactory.newInstance();

      builderFactory.setNamespaceAware(true);
      builderFactory.setValidating(true);

      DocumentBuilder parser = builderFactory.newDocumentBuilder();

      /*
      // domParser.setFeature("http://apache.org/xml/features/dom/create-entity-ref-nodes", getShouldExpandEntityRefs()? false : true);
      if(m_useDOM2getNamespaceURI)
      {
      parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", true);
      parser.setFeature("http://xml.org/sax/features/namespaces", true);
      }
      else
      {
      parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
      }

      parser.setFeature("http://apache.org/xml/features/allow-java-encodings", true);
      */

      parser.setErrorHandler(
        new org.apache.xml.utils.DefaultErrorHandler());

      // if(null != m_entityResolver)
      // {
      // System.out.println("Setting the entity resolver.");
      //  parser.setEntityResolver(m_entityResolver);
      // }
      setDocument(parser.parse(source));
    }
    catch (org.xml.sax.SAXException se)
    {
      throw new TransformerException(se);
    }
    catch (ParserConfigurationException pce)
    {
      throw new TransformerException(pce);
    }
    catch (IOException ioe)
    {
      throw new TransformerException(ioe);
    }

    // setDocument(((org.apache.xerces.parsers.DOMParser)parser).getDocument());
  }

  /**
   * Given an XML ID, return the element. This requires assistance from the
   * DOM and parser, and is meaningful only in the context of a DTD 
   * or schema which declares attributes as being of type ID. This
   * information may or may not be available in all parsers, may or
   * may not be available for specific documents, and may or may not
   * be available when validation is not turned on.
   *
   * @param id The ID to search for, as a String.
   * @param doc The document to search within, as a DOM Document node.
   * @return DOM Element node with an attribute of type ID whose value
   * uniquely matches the requested id string, or null if there isn't
   * such an element or if the DOM can't answer the question for other
   * reasons.
   */
  public Element getElementByID(String id, Document doc)
  {
    return doc.getElementById(id);
  }

  /**
   * Figure out whether node2 should be considered as being later
   * in the document than node1, in Document Order as defined
   * by the XPath model. This may not agree with the ordering defined
   * by other XML applications.
   * <p>
   * There are some cases where ordering isn't defined, and neither are
   * the results of this function -- though we'll generally return true.
   * <p>
   * TODO: Make sure this does the right thing with attribute nodes!!!
   *
   * @param node1 DOM Node to perform position comparison on.
   * @param node2 DOM Node to perform position comparison on .
   * 
   * @return false if node2 comes before node1, otherwise return true.
   * You can think of this as 
   * <code>(node1.documentOrderPosition &lt;= node2.documentOrderPosition)</code>.
   */
  public static boolean isNodeAfter(Node node1, Node node2)
  {

    // Assume first that the nodes are DTM nodes, since discovering node 
    // order is massivly faster for the DTM.
    if(node1 instanceof DOMOrder && node2 instanceof DOMOrder)
    {
      int index1 = ((DOMOrder) node1).getUid();
      int index2 = ((DOMOrder) node2).getUid();

      return index1 <= index2;
    }
    else
    {

      // isNodeAfter will return true if node is after countedNode 
      // in document order. The base isNodeAfter is sloooow (relatively).
      return DOMHelper.isNodeAfter(node1, node2);
    }
  }

  /**
   * Get the XPath-model parent of a node.  This version takes advantage
   * of the DOM Level 2 Attr.ownerElement() method; the base version we
   * would otherwise inherit is prepared to fall back on exhaustively
   * walking the document to find an Attr's parent.
   *
   * @param node Node to be examined
   *
   * @return the DOM parent of the input node, if there is one, or the
   * ownerElement if the input node is an Attr, or null if the node is
   * a Document, a DocumentFragment, or an orphan.
   */
  public static Node getParentOfNode(Node node)
  {
          Node parent=node.getParentNode();
          if(parent==null && (Node.ATTRIBUTE_NODE == node.getNodeType()) )
           parent=((Attr) node).getOwnerElement();
          return parent;
  }

  /**
   * Returns the local name of the given node, as defined by the
   * XML Namespaces specification. This is prepared to handle documents
   * built using DOM Level 1 methods by falling back upon explicitly
   * parsing the node name.
   *
   * @param n Node to be examined
   *
   * @return String containing the local name, or null if the node
   * was not assigned a Namespace.
   */
  public String getLocalNameOfNode(Node n)
  {

    String name = n.getLocalName();

    return (null == name) ? super.getLocalNameOfNode(n) : name;
  }

  /**
   * Returns the Namespace Name (Namespace URI) for the given node.
   * In a Level 2 DOM, you can ask the node itself. Note, however, that
   * doing so conflicts with our decision in getLocalNameOfNode not
   * to trust the that the DOM was indeed created using the Level 2
   * methods. If Level 1 methods were used, these two functions will
   * disagree with each other.
   * <p>
   * TODO: Reconcile with getLocalNameOfNode.
   *
   * @param n Node to be examined
   *
   * @return String containing the Namespace URI bound to this DOM node
   * at the time the Node was created.
   */
  public String getNamespaceOfNode(Node n)
  {
    return n.getNamespaceURI();
  }

  /** Field m_useDOM2getNamespaceURI is a compile-time flag which
   *  gates some of the parser options used to build a DOM -- but 
   * that code is commented out at this time and nobody else
   * references it, so I've commented this out as well. */
  //private boolean m_useDOM2getNamespaceURI = false;
}
