/*
 * 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.xpath.xdom;

import java.net.*;
import java.io.*;
import java.util.*;
import org.apache.xerces.dom.*;
import org.apache.xerces.parsers.*;
import org.apache.xerces.framework.*;
import org.xml.sax.*;
import org.w3c.dom.*;
import org.apache.xalan.xpath.xml.*;
import org.apache.xalan.xpath.*;
import org.apache.xpath.res.XPATHErrorResources;
import org.apache.xalan.res.XSLMessages;

import javax.xml.transform.TransformerException;
import javax.xml.parsers.*;


/**
 * <meta name="usage" content="general"/>
 * Provides XSLTProcessor an interface to the Xerces XML parser.  This 
 * liaison should be used if Xerces DOM nodes are being process as 
 * the source tree or as the result tree.
 * @see org.apache.xalan.xslt.XSLTProcessor
 * @see org.apache.xml.parsers
 */
public class XercesLiaison extends XMLParserLiaisonDefault //implements XPathSupport
{
  /**
   * Return a string suitible for telling the user what parser is being used.
   */
  public String getParserDescription()
  {
    return "XML4J Version "+ getXML4JVersionString();
  }

	private org.xml.sax.ErrorHandler m_errorHandler;
  /**
   * Constructor that takes SAX ErrorHandler as an argument. The error handler
   * is registered with the XML Parser. Any XML-related errors will be reported
   * to the calling application using this error handler.
   *
   * @param	errorHandler SAX ErrorHandler instance.
   */
  public XercesLiaison(org.xml.sax.ErrorHandler errorHandler)
  {
    m_errorHandler = errorHandler;
  }

  /**
   * Construct an instance.
   *
  public XercesLiaison(XPathEnvSupport envSupport)
  {
    m_envSupport = envSupport;
  }*/

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

  /**
   * <meta name="usage" content="internal"/>
   * Check node to see if it matches this liaison.
   */
  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()})); //"XercesLiaison can not handle nodes of type"
        //+((Object)node).getClass());
  }

  /**
   * Returns true that this implementation does support
   * the SAX DocumentHandler interface.
   */
  public boolean supportsSAX()
  {
    return true;
  }

  /**
   * <meta name="usage" content="internal"/>
   * Get Xerces version field... we have to do this 'cause
   * the "public static final" fields seem to get bound
   * at compile time otherwise.
   */
  private String getXML4JVersionString()
  {
    // return Version.fVersion;
    String version = "";
    try
    {
      java.lang.reflect.Field versionField = Version.class.getField("fVersion");
      version = (String)versionField.get(null);
    }
    catch(Exception e)
    {
    }
    return version;
  }

  /**
   * <meta name="usage" content="internal"/>
   * Get one of the Xerces version numbers...
   * we have to do this 'cause the "public static final"
   * fields seem to get bound at compile time otherwise.
   */
  private int getXML4JVersionNum(int field)
  {
    int versionNum = 0;
    String ver = getXML4JVersionString();
    StringTokenizer tokenizer = new StringTokenizer(ver, " .");
    for(int i = 0; tokenizer.hasMoreTokens(); i++)
    {
      String tok = tokenizer.nextToken();
      if(field == i)
      {
        versionNum = Integer.parseInt(tok);
      }
    }
    return versionNum;
  }
  
  /**
   * Pool the DOM parsers for reuse.
   *
  private ObjectPool m_domParserPool = new ObjectPool(DOMParser.class);
  
  /**
   * Pool the SAX parsers for reuse.
   *
  private ObjectPool m_saxParserPool = new ObjectPool(SAXParser.class);
 
  /**
   * Count the parses since the last garbage collection.  GC every 
   * 10 parses or so.  (This might be a bad idea, but it seems to 
   * help...)
   *
  protected int m_parseCountSinceGC = 0;
*/

  /**
   * <meta name="usage" content="internal"/>
   * Parse an XML document.
   *
   * <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.
   * @exception org.xml.sax.SAXException Any SAX exception, possibly
   *            wrapping another exception.
   * @exception java.io.IOException An IO exception from the parser,
   *            possibly from a byte stream or character stream
   *            supplied by the application.
   * @see org.xml.sax.InputSource
   * @see #parse(java.lang.String)
   * @see #setEntityResolver
   * @see #setDTDHandler
   * @see #setDocumentHandler
   * @see #setErrorHandler
   */
  public void parse (InputSource source)
    throws javax.xml.transform.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);      

      DocumentBuilder parser = builderFactory.newDocumentBuilder();
			if (m_errorHandler == null)
				parser.setErrorHandler(new org.apache.xml.utils.DefaultErrorHandler());
			else
				parser.setErrorHandler(m_errorHandler);

      // 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);
    }
  }
  
  public void copyFromOtherLiaison(XMLParserLiaisonDefault from)
    throws SAXException
  {
    //super.copyFromOtherLiaison(from);
    if(null != from) // defensive
    {
      if(from instanceof XercesLiaison)
        this.m_useDOM2getNamespaceURI = ((XercesLiaison)from).m_useDOM2getNamespaceURI;
    }
 }


  /**
   * Create an empty DOM Document.  Mainly used for creating an
   * output document.  Implementation of XMLParserLiaison
   * interface method.
   */
  static public Document createDocument()
  {
    org.apache.xerces.dom.DocumentImpl doc = new org.apache.xerces.dom.DocumentImpl();
    return doc;
  }

  /**
   * Given an ID, return the element.
   */
  public Element getElementByID(String id, Document doc)
  {
    return ((DocumentImpl)doc).getIdentifier(id);
  }

  /**
   * Tell if the node is ignorable whitespace.
   * @deprecated
   */
  public boolean isIgnorableWhitespace(Text node)
  {
    boolean isIgnorable;
    if( node instanceof org.apache.xerces.dom.TextImpl)
    {
      isIgnorable = ((org.apache.xerces.dom.TextImpl)node).isIgnorableWhitespace();
    }
    else
    {
      isIgnorable = false;
    }
    return isIgnorable;
  }
  
  protected boolean m_useDOM2getNamespaceURI = true;
  
  /**
   * Set whether or not getNamespaceOfNode should use the Xerces/DOM2
   * getNamespaceURI.  This has to be set to true if the 
   * http://xml.org/sax/features/namespaces is set to false, or if 
   * the tree is mutated.
   */
  public void setUseDOM2getNamespaceURI(boolean b)
  {
    m_useDOM2getNamespaceURI = b;
  }

  
  /**
   * Get the namespace of the node.  Calls org.apache.xerces.dom.NodeImpl's
   * getNamespaceURI() if setUseDOM2getNamespaceURI(true) has been called.
   */
  public String getNamespaceOfNode(Node n)
  {
    return(m_useDOM2getNamespaceURI) ?
          ((org.apache.xerces.dom.NodeImpl)n).getNamespaceURI()
          : super.getNamespaceOfNode(n);
  }
  

  /**
  * Returns the local name of the given node.
  */
  // public String getLocalNameOfNode(Node n)
  // {
  //   return ((org.apache.xerces.dom.NodeImpl)n).getLocalName();
  // }

  /**
  * Returns the element name with the namespace expanded.
  */
  // public String getExpandedElementName(Element elem)
  // {
  //  String namespace = getNamespaceOfNode(elem);
  //   return (null != namespace) ? namespace+":"+ getLocalNameOfNode(elem)
  //                                : getLocalNameOfNode(elem);
  // }

  /**
  * Returns the attribute name with the namespace expanded.
  */
  // public String getExpandedAttributeName(Attr attr)
  // {
  //  String namespace = getNamespaceOfNode(attr);
  //   return (null != namespace) ? namespace+":"+ getLocalNameOfNode(attr)
  //                               : getLocalNameOfNode(attr);
  // }

  /**
   * Get the parent of a node.
   */
  public Node getParentOfNode(Node node)
    throws RuntimeException
  {
    return (Node.ATTRIBUTE_NODE == node.getNodeType())
           ? ((Attr)node).getOwnerElement() : node.getParentNode();
  }

}


