mkwan       2003/01/22 08:08:12

  Added:       java/src/org/apache/xml/utils DOM2Helper.java DOMHelper.java
                        DOMOrder.java Constants.java
                        ThreadControllerWrapper.java
  Log:
  DTM Separation - new files in org.apache.xml.utils
  Move the classes DOMOrder, DOMHelper and DOM2Helper from XPath to xml.utils.
  Add a new Constants class to hold the constants used by XPath.
  The ThreadControllerWrapper class is a container for the nested class
  ThreadController which was originally in 
org.apache.xalan.transformer.TransformerImpl.
  
  Revision  Changes    Path
  1.1                  xml-xalan/java/src/org/apache/xml/utils/DOM2Helper.java
  
  Index: DOM2Helper.java
  ===================================================================
  /*
   * 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 [EMAIL PROTECTED]
   *
   * 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 java.util.StringTokenizer;
  
  import org.w3c.dom.Node;
  import org.w3c.dom.Document;
  import org.w3c.dom.Element;
  import org.w3c.dom.Text;
  import org.w3c.dom.Attr;
  import org.xml.sax.InputSource;
  import org.xml.sax.Parser;
  
  import javax.xml.parsers.*;
  
  import javax.xml.transform.TransformerException;
  
  /**
   * @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(){}
  
    /**
     * <meta name="usage" content="internal"/>
     * 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.
     */
    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;
    }
  
    /**
     * <meta name="usage" content="internal"/>
     * 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.
     */
    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;
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/utils/DOMHelper.java
  
  Index: DOMHelper.java
  ===================================================================
  /*
   * 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 [EMAIL PROTECTED]
   *
   * 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.util.Hashtable;
  import java.util.Vector;
  
  import org.w3c.dom.*;
  
  import javax.xml.transform.TransformerException;
  
  import org.apache.xml.res.XMLErrorResources;
  import org.apache.xml.res.XMLMessages;
  
  // Imported JAVA API for XML Parsing 1.0 classes
  import javax.xml.parsers.DocumentBuilder;
  import javax.xml.parsers.DocumentBuilderFactory;
  import javax.xml.parsers.ParserConfigurationException;
  
  import org.apache.xml.dtm.ref.DTMNodeProxy;
  
  /**
   * @deprecated Since the introduction of the DTM, this class will be removed.
   * This class provides a front-end to DOM implementations, providing
   * a number of utility functions that either aren't yet standardized
   * by the DOM spec or that are defined in optional DOM modules and
   * hence may not be present in all DOMs.
   */
  public class DOMHelper
  {
  
    /**
     * DOM Level 1 did not have a standard mechanism for creating a new
     * Document object. This function provides a DOM-implementation-independent
     * abstraction for that for that concept. It's typically used when 
     * outputting a new DOM as the result of an operation.
     * <p>
     * TODO: This isn't directly compatable with DOM Level 2. 
     * The Level 2 createDocument call also creates the root 
     * element, and thus requires that you know what that element will be
     * before creating the Document. We should think about whether we want
     * to change this code, and the callers, so we can use the DOM's own 
     * method. (It's also possible that DOM Level 3 may relax this
     * sequence, but you may give up some intelligence in the DOM by
     * doing so; the intent was that knowing the document type and root
     * element might let the DOM automatically switch to a specialized
     * subclass for particular kinds of documents.)
     *
     * @return The newly created DOM Document object, with no children, or
     * null if we can't find a DOM implementation that permits creating
     * new empty Documents.
     */
    public static Document createDocument()
    {
  
      try
      {
  
        // Use an implementation of the JAVA API for XML Parsing 1.0 to
        // create a DOM Document node to contain the result.
        DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
  
        dfactory.setNamespaceAware(true);
        dfactory.setValidating(true);
  
        DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
        Document outNode = docBuilder.newDocument();
  
        return outNode;
      }
      catch (ParserConfigurationException pce)
      {
        throw new RuntimeException(
          XMLMessages.createXMLMessage(
            XMLErrorResources.ER_CREATEDOCUMENT_NOT_SUPPORTED, null));  
//"createDocument() not supported in XPathContext!");
  
        // return null;
      }
    }
  
    /**
     * <meta name="usage" content="advanced"/>
     * Tells, through the combination of the default-space attribute
     * on xsl:stylesheet, xsl:strip-space, xsl:preserve-space, and the
     * xml:space attribute, whether or not extra whitespace should be stripped
     * from the node.  Literal elements from template elements should
     * <em>not</em> be tested with this function.
     * @param textNode A text node from the source tree.
     * @return true if the text node should be stripped of extra whitespace.
     *
     * @throws javax.xml.transform.TransformerException
     */
    public boolean shouldStripSourceNode(Node textNode)
            throws javax.xml.transform.TransformerException
    {
  
      // return (null == m_envSupport) ? false : 
m_envSupport.shouldStripSourceNode(textNode);
      return false;
    }
  
    /**
     * Supports the XPath function GenerateID by returning a unique
     * identifier string for any given DOM Node.
     * <p>
     * Warning: The base implementation uses the Node object's hashCode(),
     * which is NOT guaranteed to be unique. If that method hasn't been
     * overridden in this DOM ipmlementation, most Java implementions will
     * derive it from the object's address and should be OK... but if
     * your DOM uses a different definition of hashCode (eg hashing the
     * contents of the subtree), or if your DOM may have multiple objects
     * that represent a single Node in the data structure (eg via proxying),
     * you may need to find another way to assign a unique identifier.
     * <p>
     * Also, be aware that if nodes are destroyed and recreated, there is
     * an open issue regarding whether an ID may be reused. Currently
     * we're assuming that the input document is stable for the duration
     * of the XPath/XSLT operation, so this shouldn't arise in this context.
     * <p>
     * (DOM Level 3 is investigating providing a unique node "key", but
     * that won't help Level 1 and Level 2 implementations.)
     *
     * @param node whose identifier you want to obtain
     *
     * @return a string which should be different for every Node object.
     */
    public String getUniqueID(Node node)
    {
      return "N" + Integer.toHexString(node.hashCode()).toUpperCase();
    }
  
    /**
     * 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.
     * 
     * 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)
    {
      if (node1 == node2 || isNodeTheSame(node1, node2))
        return true;
  
          // Default return value, if there is no defined ordering
      boolean isNodeAfter = true;
          
      Node parent1 = getParentOfNode(node1);
      Node parent2 = getParentOfNode(node2);          
  
      // Optimize for most common case
      if (parent1 == parent2 || isNodeTheSame(parent1, parent2))  // then we 
know they are siblings
      {
        if (null != parent1)
          isNodeAfter = isNodeAfterSibling(parent1, node1, node2);
        else
        {
                    // If both parents are null, ordering is not defined.
                    // We're returning a value in lieu of throwing an exception.
                    // Not a case we expect to arise in XPath, but beware if you
                    // try to reuse this method.
                    
                    // We can just fall through in this case, which allows us
                    // to hit the debugging code at the end of the function.
            //return isNodeAfter;
        }
      }
      else
      {
  
        // General strategy: Figure out the lengths of the two 
        // ancestor chains, reconcile the lengths, and look for
            // the lowest common ancestor. If that ancestor is one of
            // the nodes being compared, it comes before the other.
        // Otherwise perform a sibling compare. 
                  //
                  // NOTE: If no common ancestor is found, ordering is undefined
                  // and we return the default value of isNodeAfter.
                  
        // Count parents in each ancestor chain
        int nParents1 = 2, nParents2 = 2;  // include node & parent obtained 
above
  
        while (parent1 != null)
        {
          nParents1++;
  
          parent1 = getParentOfNode(parent1);
        }
  
        while (parent2 != null)
        {
          nParents2++;
  
          parent2 = getParentOfNode(parent2);
        }
  
            // Initially assume scan for common ancestor starts with
            // the input nodes.
        Node startNode1 = node1, startNode2 = node2;
  
        // If one ancestor chain is longer, adjust its start point
            // so we're comparing at the same depths
        if (nParents1 < nParents2)
        {
          // Adjust startNode2 to depth of startNode1
          int adjust = nParents2 - nParents1;
  
          for (int i = 0; i < adjust; i++)
          {
            startNode2 = getParentOfNode(startNode2);
          }
        }
        else if (nParents1 > nParents2)
        {
          // adjust startNode1 to depth of startNode2
          int adjust = nParents1 - nParents2;
  
          for (int i = 0; i < adjust; i++)
          {
            startNode1 = getParentOfNode(startNode1);
          }
        }
  
        Node prevChild1 = null, prevChild2 = null;  // so we can "back up"
  
        // Loop up the ancestor chain looking for common parent
        while (null != startNode1)
        {
          if (startNode1 == startNode2 || isNodeTheSame(startNode1, 
startNode2))  // common parent?
          {
            if (null == prevChild1)  // first time in loop?
            {
  
              // Edge condition: one is the ancestor of the other.
              isNodeAfter = (nParents1 < nParents2) ? true : false;
  
              break;  // from while loop
            }
            else 
            {
                          // Compare ancestors below lowest-common as siblings
              isNodeAfter = isNodeAfterSibling(startNode1, prevChild1,
                                               prevChild2);
  
              break;  // from while loop
            }
          }  // end if(startNode1 == startNode2)
  
                  // Move up one level and try again
          prevChild1 = startNode1;
          startNode1 = getParentOfNode(startNode1);
          prevChild2 = startNode2;
          startNode2 = getParentOfNode(startNode2);
        }  // end while(parents exist to examine)
      }  // end big else (not immediate siblings)
          
          // WARNING: The following diagnostic won't report the early
          // "same node" case. Fix if/when needed.
          
      /* -- please do not remove... very useful for diagnostics --
      System.out.println("node1 = 
"+node1.getNodeName()+"("+node1.getNodeType()+")"+
      ", node2 = "+node2.getNodeName()
      +"("+node2.getNodeType()+")"+
      ", isNodeAfter = "+isNodeAfter); */
      return isNodeAfter;
    }  // end isNodeAfter(Node node1, Node node2)
  
    /**
     * Use DTMNodeProxy to determine whether two nodes are the same.
     * 
     * @param node1 The first DOM node to compare.
     * @param node2 The second DOM node to compare.
     * @return true if the two nodes are the same.
     */
    public static boolean isNodeTheSame(Node node1, Node node2)
    {
      if (node1 instanceof DTMNodeProxy && node2 instanceof DTMNodeProxy)
        return ((DTMNodeProxy)node1).equals((DTMNodeProxy)node2);
      else
        return (node1 == node2);
    }
  
    /**
     * Figure out if child2 is after child1 in document order.
     * <p>
     * Warning: Some aspects of "document order" are not well defined.
     * For example, the order of attributes is considered
     * meaningless in XML, and the order reported by our model will
     * be consistant for a given invocation but may not 
     * match that of either the source file or the serialized output.
     * 
     * @param parent Must be the parent of both child1 and child2.
     * @param child1 Must be the child of parent and not equal to child2.
     * @param child2 Must be the child of parent and not equal to child1.
     * @return true if child 2 is after child1 in document order.
     */
    private static boolean isNodeAfterSibling(Node parent, Node child1,
                                              Node child2)
    {
  
      boolean isNodeAfterSibling = false;
      short child1type = child1.getNodeType();
      short child2type = child2.getNodeType();
  
      if ((Node.ATTRIBUTE_NODE != child1type)
              && (Node.ATTRIBUTE_NODE == child2type))
      {
  
        // always sort attributes before non-attributes.
        isNodeAfterSibling = false;
      }
      else if ((Node.ATTRIBUTE_NODE == child1type)
               && (Node.ATTRIBUTE_NODE != child2type))
      {
  
        // always sort attributes before non-attributes.
        isNodeAfterSibling = true;
      }
      else if (Node.ATTRIBUTE_NODE == child1type)
      {
        NamedNodeMap children = parent.getAttributes();
        int nNodes = children.getLength();
        boolean found1 = false, found2 = false;
  
            // Count from the start until we find one or the other.
        for (int i = 0; i < nNodes; i++)
        {
          Node child = children.item(i);
  
          if (child1 == child || isNodeTheSame(child1, child))
          {
            if (found2)
            {
              isNodeAfterSibling = false;
  
              break;
            }
  
            found1 = true;
          }
          else if (child2 == child || isNodeTheSame(child2, child))
          {
            if (found1)
            {
              isNodeAfterSibling = true;
  
              break;
            }
  
            found2 = true;
          }
        }
      }
      else
      {
                  // TODO: Check performance of alternate solution:
                  // There are two choices here: Count from the start of
                  // the document until we find one or the other, or count
                  // from one until we find or fail to find the other.
                  // Either can wind up scanning all the siblings in the worst
                  // case, which on a wide document can be a lot of work but
                  // is more typically is a short list. 
                  // Scanning from the start involves two tests per iteration,
                  // but it isn't clear that scanning from the middle doesn't
                  // yield more iterations on average. 
                  // We should run some testcases.
        Node child = parent.getFirstChild();
        boolean found1 = false, found2 = false;
  
        while (null != child)
        {
  
          // Node child = children.item(i);
          if (child1 == child || isNodeTheSame(child1, child))
          {
            if (found2)
            {
              isNodeAfterSibling = false;
  
              break;
            }
  
            found1 = true;
          }
          else if (child2 == child || isNodeTheSame(child2, child))
          {
            if (found1)
            {
              isNodeAfterSibling = true;
  
              break;
            }
  
            found2 = true;
          }
  
          child = child.getNextSibling();
        }
      }
  
      return isNodeAfterSibling;
    }  // end isNodeAfterSibling(Node parent, Node child1, Node child2)
  
    //==========================================================
    // SECTION: Namespace resolution
    //==========================================================
  
    /**
     * <meta name="usage" content="internal"/>
     * Get the depth level of this node in the tree (equals 1 for
     * a parentless node).
     *
     * @param n Node to be examined.
     * @return the number of ancestors, plus one
     */
    public short getLevel(Node n)
    {
  
      short level = 1;
  
      while (null != (n = getParentOfNode(n)))
      {
        level++;
      }
  
      return level;
    }
  
    /**
     * Given an XML Namespace prefix and a context in which the prefix
     * is to be evaluated, return the Namespace Name this prefix was 
     * bound to. Note that DOM Level 3 is expected to provide a version of
     * this which deals with the DOM's "early binding" behavior.
     * 
     * Default handling:
     *
     * @param prefix String containing namespace prefix to be resolved, 
     * without the ':' which separates it from the localname when used 
     * in a Node Name. The empty sting signifies the default namespace
     * at this point in the document.
     * @param namespaceContext Element which provides context for resolution.
     * (We could extend this to work for other nodes by first seeking their
     * nearest Element ancestor.)
     *
     * @return a String containing the Namespace URI which this prefix
     * represents in the specified context.
     */
    public String getNamespaceForPrefix(String prefix, Element namespaceContext)
    {
  
      int type;
      Node parent = namespaceContext;
      String namespace = null;
  
      if (prefix.equals("xml"))
      {
        namespace = QName.S_XMLNAMESPACEURI; // Hardcoded, per Namespace spec
      }
          else if(prefix.equals("xmlns"))
      {
            // Hardcoded in the DOM spec, expected to be adopted by
            // Namespace spec. NOTE: Namespace declarations _must_ use
            // the xmlns: prefix; other prefixes declared as belonging
            // to this namespace will not be recognized and should
            // probably be rejected by parsers as erroneous declarations.
        namespace = "http://www.w3.org/2000/xmlns/";; 
      }
      else
      {
            // Attribute name for this prefix's declaration
            String declname=(prefix=="")
                          ? "xmlns"
                          : "xmlns:"+prefix;
                                             
            // Scan until we run out of Elements or have resolved the namespace
        while ((null != parent) && (null == namespace)
               && (((type = parent.getNodeType()) == Node.ELEMENT_NODE)
                   || (type == Node.ENTITY_REFERENCE_NODE)))
        {
          if (type == Node.ELEMENT_NODE)
          {
                          
                          // Look for the appropriate Namespace Declaration 
attribute,
                          // either "xmlns:prefix" or (if prefix is "") "xmlns".
                          // TODO: This does not handle "implicit declarations"
                          // which may be created when the DOM is edited. DOM 
Level
                          // 3 will define how those should be interpreted. But
                          // this issue won't arise in freshly-parsed DOMs.
                          
                  // NOTE: declname is set earlier, outside the loop.
                          Attr 
attr=((Element)parent).getAttributeNode(declname);
                          if(attr!=null)
                          {
                  namespace = attr.getNodeValue();
                  break;
                          }
                  }
  
          parent = getParentOfNode(parent);
        }
      }
  
      return namespace;
    }
  
    /**
     * An experiment for the moment.
     */
    Hashtable m_NSInfos = new Hashtable();
  
    /** Object to put into the m_NSInfos table that tells that a node has not 
been 
     *  processed, but has xmlns namespace decls.  */
    protected static final NSInfo m_NSInfoUnProcWithXMLNS = new NSInfo(false,
                                                              true);
  
    /** Object to put into the m_NSInfos table that tells that a node has not 
been 
     *  processed, but has no xmlns namespace decls.  */
    protected static final NSInfo m_NSInfoUnProcWithoutXMLNS = new NSInfo(false,
                                                                 false);
  
    /** Object to put into the m_NSInfos table that tells that a node has not 
been 
     *  processed, and has no xmlns namespace decls, and has no ancestor decls. 
 */
    protected static final NSInfo m_NSInfoUnProcNoAncestorXMLNS =
      new NSInfo(false, false, NSInfo.ANCESTORNOXMLNS);
  
    /** Object to put into the m_NSInfos table that tells that a node has been 
     *  processed, and has xmlns namespace decls.  */
    protected static final NSInfo m_NSInfoNullWithXMLNS = new NSInfo(true,
                                                            true);
  
    /** Object to put into the m_NSInfos table that tells that a node has been 
     *  processed, and has no xmlns namespace decls.  */
    protected static final NSInfo m_NSInfoNullWithoutXMLNS = new NSInfo(true,
                                                               false);
  
    /** Object to put into the m_NSInfos table that tells that a node has been 
     *  processed, and has no xmlns namespace decls. and has no ancestor decls. 
 */
    protected static final NSInfo m_NSInfoNullNoAncestorXMLNS =
      new NSInfo(true, false, NSInfo.ANCESTORNOXMLNS);
  
    /** Vector of node (odd indexes) and NSInfos (even indexes) that tell if 
     *  the given node is a candidate for ancestor namespace processing.  */
    protected Vector m_candidateNoAncestorXMLNS = new Vector();
  
    /**
     * Returns the namespace of the given node. Differs from simply getting
     * the node's prefix and using getNamespaceForPrefix in that it attempts
     * to cache some of the data in NSINFO objects, to avoid repeated lookup.
     * TODO: Should we consider moving that logic into getNamespaceForPrefix?
     *
     * @param n Node to be examined.
     *
     * @return String containing the Namespace Name (uri) for this node.
     * Note that this is undefined for any nodes other than Elements and
     * Attributes.
     */
    public String getNamespaceOfNode(Node n)
    {
  
      String namespaceOfPrefix;
      boolean hasProcessedNS;
      NSInfo nsInfo;
      short ntype = n.getNodeType();
  
      if (Node.ATTRIBUTE_NODE != ntype)
      {
        Object nsObj = m_NSInfos.get(n);  // return value
  
        nsInfo = (nsObj == null) ? null : (NSInfo) nsObj;
        hasProcessedNS = (nsInfo == null) ? false : nsInfo.m_hasProcessedNS;
      }
      else
      {
        hasProcessedNS = false;
        nsInfo = null;
      }
  
      if (hasProcessedNS)
      {
        namespaceOfPrefix = nsInfo.m_namespace;
      }
      else
      {
        namespaceOfPrefix = null;
  
        String nodeName = n.getNodeName();
        int indexOfNSSep = nodeName.indexOf(':');
        String prefix;
  
        if (Node.ATTRIBUTE_NODE == ntype)
        {
          if (indexOfNSSep > 0)
          {
            prefix = nodeName.substring(0, indexOfNSSep);
          }
          else
          {
  
            // Attributes don't use the default namespace, so if 
            // there isn't a prefix, we're done.
            return namespaceOfPrefix;
          }
        }
        else
        {
          prefix = (indexOfNSSep >= 0)
                   ? nodeName.substring(0, indexOfNSSep) : "";
        }
  
        boolean ancestorsHaveXMLNS = false;
        boolean nHasXMLNS = false;
  
        if (prefix.equals("xml"))
        {
          namespaceOfPrefix = QName.S_XMLNAMESPACEURI;
        }
        else
        {
          int parentType;
          Node parent = n;
  
          while ((null != parent) && (null == namespaceOfPrefix))
          {
            if ((null != nsInfo)
                    && (nsInfo.m_ancestorHasXMLNSAttrs
                        == nsInfo.ANCESTORNOXMLNS))
            {
              break;
            }
  
            parentType = parent.getNodeType();
  
            if ((null == nsInfo) || nsInfo.m_hasXMLNSAttrs)
            {
              boolean elementHasXMLNS = false;
  
              if (parentType == Node.ELEMENT_NODE)
              {
                NamedNodeMap nnm = parent.getAttributes();
  
                for (int i = 0; i < nnm.getLength(); i++)
                {
                  Node attr = nnm.item(i);
                  String aname = attr.getNodeName();
  
                  if (aname.charAt(0) == 'x')
                  {
                    boolean isPrefix = aname.startsWith("xmlns:");
  
                    if (aname.equals("xmlns") || isPrefix)
                    {
                      if (n == parent)
                        nHasXMLNS = true;
  
                      elementHasXMLNS = true;
                      ancestorsHaveXMLNS = true;
  
                      String p = isPrefix ? aname.substring(6) : "";
  
                      if (p.equals(prefix))
                      {
                        namespaceOfPrefix = attr.getNodeValue();
  
                        break;
                      }
                    }
                  }
                }
              }
  
              if ((Node.ATTRIBUTE_NODE != parentType) && (null == nsInfo)
                      && (n != parent))
              {
                nsInfo = elementHasXMLNS
                         ? m_NSInfoUnProcWithXMLNS : m_NSInfoUnProcWithoutXMLNS;
  
                m_NSInfos.put(parent, nsInfo);
              }
            }
  
            if (Node.ATTRIBUTE_NODE == parentType)
            {
              parent = getParentOfNode(parent);
            }
            else
            {
              m_candidateNoAncestorXMLNS.addElement(parent);
              m_candidateNoAncestorXMLNS.addElement(nsInfo);
  
              parent = parent.getParentNode();
            }
  
            if (null != parent)
            {
              Object nsObj = m_NSInfos.get(parent);  // return value
  
              nsInfo = (nsObj == null) ? null : (NSInfo) nsObj;
            }
          }
  
          int nCandidates = m_candidateNoAncestorXMLNS.size();
  
          if (nCandidates > 0)
          {
            if ((false == ancestorsHaveXMLNS) && (null == parent))
            {
              for (int i = 0; i < nCandidates; i += 2)
              {
                Object candidateInfo = m_candidateNoAncestorXMLNS.elementAt(i
                                         + 1);
  
                if (candidateInfo == m_NSInfoUnProcWithoutXMLNS)
                {
                  m_NSInfos.put(m_candidateNoAncestorXMLNS.elementAt(i),
                                m_NSInfoUnProcNoAncestorXMLNS);
                }
                else if (candidateInfo == m_NSInfoNullWithoutXMLNS)
                {
                  m_NSInfos.put(m_candidateNoAncestorXMLNS.elementAt(i),
                                m_NSInfoNullNoAncestorXMLNS);
                }
              }
            }
  
            m_candidateNoAncestorXMLNS.removeAllElements();
          }
        }
  
        if (Node.ATTRIBUTE_NODE != ntype)
        {
          if (null == namespaceOfPrefix)
          {
            if (ancestorsHaveXMLNS)
            {
              if (nHasXMLNS)
                m_NSInfos.put(n, m_NSInfoNullWithXMLNS);
              else
                m_NSInfos.put(n, m_NSInfoNullWithoutXMLNS);
            }
            else
            {
              m_NSInfos.put(n, m_NSInfoNullNoAncestorXMLNS);
            }
          }
          else
          {
            m_NSInfos.put(n, new NSInfo(namespaceOfPrefix, nHasXMLNS));
          }
        }
      }
  
      return namespaceOfPrefix;
    }
  
    /**
     * Returns the local name of the given node. If the node's name begins
     * with a namespace prefix, this is the part after the colon; otherwise
     * it's the full node name.
     *
     * @param n the node to be examined.
     *
     * @return String containing the Local Name
     */
    public String getLocalNameOfNode(Node n)
    {
  
      String qname = n.getNodeName();
      int index = qname.indexOf(':');
  
      return (index < 0) ? qname : qname.substring(index + 1);
    }
  
    /**
     * Returns the element name with the namespace prefix (if any) replaced
     * by the Namespace URI it was bound to. This is not a standard 
     * representation of a node name, but it allows convenient 
     * single-string comparison of the "universal" names of two nodes.
     *
     * @param elem Element to be examined.
     *
     * @return String in the form "namespaceURI:localname" if the node
     * belongs to a namespace, or simply "localname" if it doesn't.
     * @see #getExpandedAttributeName
     */
    public String getExpandedElementName(Element elem)
    {
  
      String namespace = getNamespaceOfNode(elem);
  
      return (null != namespace)
             ? namespace + ":" + getLocalNameOfNode(elem)
             : getLocalNameOfNode(elem);
    }
  
    /**
     * Returns the attribute name with the namespace prefix (if any) replaced
     * by the Namespace URI it was bound to. This is not a standard 
     * representation of a node name, but it allows convenient 
     * single-string comparison of the "universal" names of two nodes.
     *
     * @param attr Attr to be examined
     *
     * @return String in the form "namespaceURI:localname" if the node
     * belongs to a namespace, or simply "localname" if it doesn't.
     * @see #getExpandedElementName
     */
    public String getExpandedAttributeName(Attr attr)
    {
  
      String namespace = getNamespaceOfNode(attr);
  
      return (null != namespace)
             ? namespace + ":" + getLocalNameOfNode(attr)
             : getLocalNameOfNode(attr);
    }
  
    //==========================================================
    // SECTION: DOM Helper Functions
    //==========================================================
  
    /**
     * Tell if the node is ignorable whitespace. Note that this can
     * be determined only in the context of a DTD or other Schema,
     * and that DOM Level 2 has nostandardized DOM API which can
     * return that information.
     * @deprecated
     *
     * @param node Node to be examined
     *
     * @return CURRENTLY HARDCODED TO FALSE, but should return true if
     * and only if the node is of type Text, contains only whitespace,
     * and does not appear as part of the #PCDATA content of an element.
     * (Note that determining this last may require allowing for 
     * Entity References.)
     */
    public boolean isIgnorableWhitespace(Text node)
    {
  
      boolean isIgnorable = false;  // return value
  
      // TODO: I can probably do something to figure out if this 
      // space is ignorable from just the information in
      // the DOM tree.
          // -- You need to be able to distinguish whitespace
          // that is #PCDATA from whitespace that isn't.  That requires
          // DTD support, which won't be standardized until DOM Level 3.
      return isIgnorable;
    }
  
    /**
     * Get the first unparented node in the ancestor chain.
     * @deprecated
     *
     * @param node Starting node, to specify which chain to chase
     *
     * @return the topmost ancestor.
     */
    public Node getRoot(Node node)
    {
  
      Node root = null;
  
      while (node != null)
      {
        root = node;
        node = getParentOfNode(node);
      }
  
      return root;
    }
  
    /**
     * Get the root node of the document tree, regardless of
     * whether or not the node passed in is a document node.
     * <p>
     * TODO: This doesn't handle DocumentFragments or "orphaned" subtrees
     * -- it's currently returning ownerDocument even when the tree is
     * not actually part of the main Document tree. We should either
     * rewrite the description to say that it finds the Document node,
     * or change the code to walk up the ancestor chain.
  
     *
     * @param n Node to be examined
     *
     * @return the Document node. Note that this is not the correct answer
     * if n was (or was a child of) a DocumentFragment or an orphaned node,
     * as can arise if the DOM has been edited rather than being generated
     * by a parser.
     */
    public Node getRootNode(Node n)
    {
      int nt = n.getNodeType();
      return ( (Node.DOCUMENT_NODE == nt) || (Node.DOCUMENT_FRAGMENT_NODE == 
nt) ) 
             ? n : n.getOwnerDocument();
    }
  
    /**
     * Test whether the given node is a namespace decl node. In DOM Level 2
     * this can be done in a namespace-aware manner, but in Level 1 DOMs
     * it has to be done by testing the node name.
     *
     * @param n Node to be examined.
     *
     * @return boolean -- true iff the node is an Attr whose name is 
     * "xmlns" or has the "xmlns:" prefix.
     */
    public boolean isNamespaceNode(Node n)
    {
  
      if (Node.ATTRIBUTE_NODE == n.getNodeType())
      {
        String attrName = n.getNodeName();
  
        return (attrName.startsWith("xmlns:") || attrName.equals("xmlns"));
      }
  
      return false;
    }
  
    /**
     * Obtain the XPath-model parent of a DOM node -- ownerElement for Attrs,
     * parent for other nodes. 
     * <p>
     * Background: The DOM believes that you must be your Parent's
     * Child, and thus Attrs don't have parents. XPath said that Attrs
     * do have their owning Element as their parent. This function
     * bridges the difference, either by using the DOM Level 2 ownerElement
     * function or by using a "silly and expensive function" in Level 1
     * DOMs.
     * <p>
     * (There's some discussion of future DOMs generalizing ownerElement 
     * into ownerNode and making it work on all types of nodes. This
     * still wouldn't help the users of Level 1 or Level 2 DOMs)
     * <p>
     *
     * @param node Node whose XPath parent we want to obtain
     *
     * @return the parent of the node, or the ownerElement if it's an
     * Attr node, or null if the node is an orphan.
     *
     * @throws RuntimeException if the Document has no root element.
     * This can't arise if the Document was created
     * via the DOM Level 2 factory methods, but is possible if other
     * mechanisms were used to obtain it
     */
    public static Node getParentOfNode(Node node) throws RuntimeException
    {
      Node parent;
      short nodeType = node.getNodeType();
  
      if (Node.ATTRIBUTE_NODE == nodeType)
      {
        Document doc = node.getOwnerDocument();
            /*
        TBD:
        if(null == doc)
        {
          throw new 
RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_CHILD_HAS_NO_OWNER_DOCUMENT,
 null));//"Attribute child does not have an owner document!");
        }
        */
  
            // Given how expensive the tree walk may be, we should first ask 
            // whether this DOM can answer the question for us. The additional
            // test does slow down Level 1 DOMs slightly. DOMHelper2, which
            // is currently specialized for Xerces, assumes it can use the
            // Level 2 solution. We might want to have an intermediate stage,
            // which would assume DOM Level 2 but not assume Xerces.
            //
            // (Shouldn't have to check whether impl is null in a compliant DOM,
            // but let's be paranoid for a moment...)
            DOMImplementation impl=doc.getImplementation();
            if(impl!=null && impl.hasFeature("Core","2.0"))
            {
                    parent=((Attr)node).getOwnerElement();
                    return parent;
            }
  
            // DOM Level 1 solution, as fallback. Hugely expensive. 
  
        Element rootElem = doc.getDocumentElement();
  
        if (null == rootElem)
        {
          throw new RuntimeException(
            XMLMessages.createXMLMessage(
              XMLErrorResources.ER_CHILD_HAS_NO_OWNER_DOCUMENT_ELEMENT,
              null));  //"Attribute child does not have an owner document 
element!");
        }
  
        parent = locateAttrParent(rootElem, node);
  
          }
      else
      {
        parent = node.getParentNode();
  
        // if((Node.DOCUMENT_NODE != nodeType) && (null == parent))
        // {
        //   throw new RuntimeException("Child does not have parent!");
        // }
      }
  
      return parent;
    }
  
    /**
     * Given an ID, return the element. This can work only if the document
     * is interpreted in the context of a DTD or Schema, since otherwise
     * we don't know which attributes are or aren't IDs.
     * <p>
     * Note that DOM Level 1 had no ability to retrieve this information.
     * DOM Level 2 introduced it but does not promise that it will be
     * supported in all DOMs; those which can't support it will always
     * return null.
     * <p>
     * TODO: getElementByID is currently unimplemented. Support DOM Level 2?
     *
     * @param id The unique identifier to be searched for.
     * @param doc The document to search within.
     * @return CURRENTLY HARDCODED TO NULL, but it should be:
     * The node which has this unique identifier, or null if there
     * is no such node or this DOM can't reliably recognize it.
     */
    public Element getElementByID(String id, Document doc)
    {
      return null;
    }
  
    /**
     * The getUnparsedEntityURI function returns the URI of the unparsed
     * entity with the specified name in the same document as the context
     * node (see [3.3 Unparsed Entities]). It returns the empty string if
     * there is no such entity.
     * <p>
     * XML processors may choose to use the System Identifier (if one
     * is provided) to resolve the entity, rather than the URI in the
     * Public Identifier. The details are dependent on the processor, and
     * we would have to support some form of plug-in resolver to handle
     * this properly. Currently, we simply return the System Identifier if
     * present, and hope that it a usable URI or that our caller can
     * map it to one.
     * TODO: Resolve Public Identifiers... or consider changing function name.
     * <p>
     * If we find a relative URI 
     * reference, XML expects it to be resolved in terms of the base URI 
     * of the document. The DOM doesn't do that for us, and it isn't 
     * entirely clear whether that should be done here; currently that's
     * pushed up to a higher levelof our application. (Note that DOM Level 
     * 1 didn't store the document's base URI.)
     * TODO: Consider resolving Relative URIs.
     * <p>
     * (The DOM's statement that "An XML processor may choose to
     * completely expand entities before the structure model is passed
     * to the DOM" refers only to parsed entities, not unparsed, and hence
     * doesn't affect this function.)
     *
     * @param name A string containing the Entity Name of the unparsed
     * entity.
     * @param doc Document node for the document to be searched.
     *
     * @return String containing the URI of the Unparsed Entity, or an
     * empty string if no such entity exists.
     */
    public String getUnparsedEntityURI(String name, Document doc)
    {
  
      String url = "";
      DocumentType doctype = doc.getDoctype();
  
      if (null != doctype)
      {
        NamedNodeMap entities = doctype.getEntities();
        if(null == entities)
          return url;
        Entity entity = (Entity) entities.getNamedItem(name);
        if(null == entity)
          return url;
        
        String notationName = entity.getNotationName();
  
        if (null != notationName)  // then it's unparsed
        {
          // The draft says: "The XSLT processor may use the public 
          // identifier to generate a URI for the entity instead of the URI 
          // specified in the system identifier. If the XSLT processor does 
          // not use the public identifier to generate the URI, it must use 
          // the system identifier; if the system identifier is a relative 
          // URI, it must be resolved into an absolute URI using the URI of 
          // the resource containing the entity declaration as the base 
          // URI [RFC2396]."
          // So I'm falling a bit short here.
          url = entity.getSystemId();
  
          if (null == url)
          {
            url = entity.getPublicId();
          }
          else
          {
            // This should be resolved to an absolute URL, but that's hard 
            // to do from here.
          }        
        }
      }
  
      return url;
    }
  
    /**
     * Support for getParentOfNode; walks a DOM tree until it finds
     * the Element which owns the Attr. This is hugely expensive, and
     * if at all possible you should use the DOM Level 2 Attr.ownerElement()
     * method instead.
     *  <p>
     * The DOM Level 1 developers expected that folks would keep track
     * of the last Element they'd seen and could recover the info from
     * that source. Obviously that doesn't work very well if the only
     * information you've been presented with is the Attr. The DOM Level 2
     * getOwnerElement() method fixes that, but only for Level 2 and
     * later DOMs.
     *
     * @param elem Element whose subtree is to be searched for this Attr
     * @param attr Attr whose owner is to be located.
     *
     * @return the first Element whose attribute list includes the provided
     * attr. In modern DOMs, this will also be the only such Element. (Early
     * DOMs had some hope that Attrs might be sharable, but this idea has
     * been abandoned.)
     */
    private static Node locateAttrParent(Element elem, Node attr)
    {
  
      Node parent = null;
  
          // This should only be called for Level 1 DOMs, so we don't have to
          // worry about namespace issues. In later levels, it's possible
          // for a DOM to have two Attrs with the same NodeName but
          // different namespaces, and we'd need to get getAttributeNodeNS...
          // but later levels also have Attr.getOwnerElement.
          Attr check=elem.getAttributeNode(attr.getNodeName());
          if(check==attr)
                  parent = elem;
  
      if (null == parent)
      {
        for (Node node = elem.getFirstChild(); null != node;
                node = node.getNextSibling())
        {
          if (Node.ELEMENT_NODE == node.getNodeType())
          {
            parent = locateAttrParent((Element) node, attr);
  
            if (null != parent)
              break;
          }
        }
      }
  
      return parent;
    }
  
    /**
     * The factory object used for creating nodes
     * in the result tree.
     */
    protected Document m_DOMFactory = null;
  
    /**
     * Store the factory object required to create DOM nodes
     * in the result tree. In fact, that's just the result tree's
     * Document node...
     *
     * @param domFactory The DOM Document Node within whose context
     * the result tree will be built.
     */
    public void setDOMFactory(Document domFactory)
    {
      this.m_DOMFactory = domFactory;
    }
  
    /**
     * Retrieve the factory object required to create DOM nodes
     * in the result tree.
     *
     * @return The result tree's DOM Document Node.
     */
    public Document getDOMFactory()
    {
  
      if (null == this.m_DOMFactory)
      {
        this.m_DOMFactory = createDocument();
      }
  
      return this.m_DOMFactory;
    }
  
    /**
     * Get the textual contents of the node. See
     * getNodeData(Node,FastStringBuffer) for discussion of how
     * whitespace nodes are handled.
     *
     * @param node DOM Node to be examined
     * @return String containing a concatenation of all the 
     * textual content within that node. 
     * @see #getNodeData(Node,FastStringBuffer)
     * 
     */
    public static String getNodeData(Node node)
    {
  
      FastStringBuffer buf = StringBufferPool.get();
      String s;
  
      try
      {
        getNodeData(node, buf);
  
        s = (buf.length() > 0) ? buf.toString() : "";
      }
      finally
      {
        StringBufferPool.free(buf);
      }
  
      return s;
    }
  
    /**
     * Retrieve the text content of a DOM subtree, appending it into a
     * user-supplied FastStringBuffer object. Note that attributes are
     * not considered part of the content of an element.
     * <p>
     * There are open questions regarding whitespace stripping. 
     * Currently we make no special effort in that regard, since the standard
     * DOM doesn't yet provide DTD-based information to distinguish
     * whitespace-in-element-context from genuine #PCDATA. Note that we
     * should probably also consider xml:space if/when we address this.
     * DOM Level 3 may solve the problem for us.
     *
     * @param node Node whose subtree is to be walked, gathering the
     * contents of all Text or CDATASection nodes.
     * @param buf FastStringBuffer into which the contents of the text
     * nodes are to be concatenated.
     */
    public static void getNodeData(Node node, FastStringBuffer buf)
    {
  
      switch (node.getNodeType())
      {
      case Node.DOCUMENT_FRAGMENT_NODE :
      case Node.DOCUMENT_NODE :
      case Node.ELEMENT_NODE :
      {
        for (Node child = node.getFirstChild(); null != child;
                child = child.getNextSibling())
        {
          getNodeData(child, buf);
        }
      }
      break;
      case Node.TEXT_NODE :
      case Node.CDATA_SECTION_NODE :
        buf.append(node.getNodeValue());
        break;
      case Node.ATTRIBUTE_NODE :
        buf.append(node.getNodeValue());
        break;
      case Node.PROCESSING_INSTRUCTION_NODE :
        // warning(XPATHErrorResources.WG_PARSING_AND_PREPARING);        
        break;
      default :
        // ignore
        break;
      }
    }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/utils/DOMOrder.java
  
  Index: DOMOrder.java
  ===================================================================
  /*
   * 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 [EMAIL PROTECTED]
   *
   * 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;
  
  /**
   * @deprecated Since the introduction of the DTM, this class will be removed.
   * Nodes that implement this index can return a document order index.
   * Eventually, this will be replaced by DOM 3 methods. 
   * (compareDocumentOrder and/or compareTreePosition.)
   */
  public interface DOMOrder
  {
  
    /**
     * Get the UID (document order index).
     *
     * @return integer whose relative value corresponds to document order
     * -- that is, if node1.getUid()<node2.getUid(), node1 comes before
     * node2, and if they're equal node1 and node2 are the same node. No
     * promises are made beyond that.
     */
    public int getUid();
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/utils/Constants.java
  
  Index: Constants.java
  ===================================================================
  /*
   * 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 [EMAIL PROTECTED]
   *
   * 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;
  
  /**
   * <meta name="usage" content="advanced"/>
   * Primary constants used by the XSLT Processor
   */
  public class Constants
  {
  
    /** 
     * Mnemonics for standard XML Namespace URIs, as Java Strings:
     * <ul>
     * <li>S_XMLNAMESPACEURI (http://www.w3.org/XML/1998/namespace) is the
     * URI permanantly assigned to the "xml:" prefix. This is used for some
     * features built into the XML specification itself, such as xml:space 
     * and xml:lang. It was defined by the W3C's XML Namespaces spec.</li>
     * <li>S_XSLNAMESPACEURL (http://www.w3.org/1999/XSL/Transform) is the
     * URI which indicates that a name may be an XSLT directive. In most
     * XSLT stylesheets, this is bound to the "xsl:" prefix. It's defined
     * by the W3C's XSLT Recommendation.</li>
     * <li>S_OLDXSLNAMESPACEURL (http://www.w3.org/XSL/Transform/1.0) was
     * used in early prototypes of XSLT processors for much the same purpose
     * as S_XSLNAMESPACEURL. It is now considered obsolete, and the version
     * of XSLT which it signified is not fully compatable with the final
     * XSLT Recommendation, so what it really signifies is a badly obsolete
     * stylesheet.</li>
     * </ul> */
    public static final String 
        S_XMLNAMESPACEURI = "http://www.w3.org/XML/1998/namespace";, 
        S_XSLNAMESPACEURL = "http://www.w3.org/1999/XSL/Transform";, 
        S_OLDXSLNAMESPACEURL = "http://www.w3.org/XSL/Transform/1.0";;
  
    /** Authorship mnemonics, as Java Strings. Not standardized, 
     * as far as I know.
     * <ul>
     * <li>S_VENDOR -- the name of the organization/individual who published
     * this XSLT processor. </li>
     * <li>S_VENDORURL -- URL where one can attempt to retrieve more
     * information about this publisher and product.</li>
     * </ul>
     */
    public static final String 
        S_VENDOR = "Apache Software Foundation", 
        S_VENDORURL = "http://xml.apache.org";;
  
    /** S_BUILTIN_EXTENSIONS_URL is a mnemonic for the XML Namespace 
     *(http://xml.apache.org/xalan) predefined to signify Xalan's
     * built-in XSLT Extensions. When used in stylesheets, this is often 
     * bound to the "xalan:" prefix.
     */
    public static final String 
      S_BUILTIN_EXTENSIONS_URL = "http://xml.apache.org/xalan";; 
  
    /**
     * The old built-in extension url. It is still supported for
     * backward compatibility.
     */
    public static final String 
      S_BUILTIN_OLD_EXTENSIONS_URL = "http://xml.apache.org/xslt";; 
    
    /**
     * Xalan extension namespaces.
     */
    public static final String 
      // The old namespace for Java extension
      S_EXTENSIONS_OLD_JAVA_URL = "http://xml.apache.org/xslt/java";,
      // The new namespace for Java extension
      S_EXTENSIONS_JAVA_URL = "http://xml.apache.org/xalan/java";,
      S_EXTENSIONS_LOTUSXSL_JAVA_URL = "http://xsl.lotus.com/java";,
      S_EXTENSIONS_XALANLIB_URL = "http://xml.apache.org/xalan";,
      S_EXTENSIONS_REDIRECT_URL = "http://xml.apache.org/xalan/redirect";,
      S_EXTENSIONS_PIPE_URL = "http://xml.apache.org/xalan/PipeDocument";,
      S_EXTENSIONS_SQL_URL = "http://xml.apache.org/xalan/sql";;
    
    /**
     * EXSLT extension namespaces.
     */
    public static final String
      S_EXSLT_COMMON_URL = "http://exslt.org/common";,
      S_EXSLT_MATH_URL = "http://exslt.org/math";,
      S_EXSLT_SETS_URL = "http://exslt.org/sets";,
      S_EXSLT_DATETIME_URL = "http://exslt.org/dates-and-times";,
      S_EXSLT_FUNCTIONS_URL = "http://exslt.org/functions";,
      S_EXSLT_DYNAMIC_URL = "http://exslt.org/dynamic";,
      S_EXSLT_STRINGS_URL = "http://exslt.org/strings";;
      
      
    /**
     * The minimum version of XSLT supported by this processor.
     */
    public static final double XSLTVERSUPPORTED = 1.0;
  }
  
  
  
  1.1                  
xml-xalan/java/src/org/apache/xml/utils/ThreadControllerWrapper.java
  
  Index: ThreadControllerWrapper.java
  ===================================================================
  /*
   * 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 [EMAIL PROTECTED]
   *
   * 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;
  
  /**
   * A utility class that wraps the ThreadController, which is used
   * by IncrementalSAXSource for the incremental building of DTM.
   */
  public class ThreadControllerWrapper
  {
    
    /** The ThreadController pool   */
    static ThreadController m_tpool = new ThreadController();
  
    /**
     * Change the ThreadController that will be used to
     * manage the transform threads.
     *
     * @param tp A ThreadController object
     */
    public static void setThreadController(ThreadController tpool)
    {
      m_tpool = tpool;
    }
    
    public static Thread runThread(Runnable runnable, int priority)
    {
      return m_tpool.run(runnable, priority);
    }
    
    public static void waitThread(Thread worker, Runnable task)
      throws InterruptedException
    {
      m_tpool.waitThread(worker, task);
    }
    
    /**
     * Thread controller utility class for incremental SAX source. Must 
     * be overriden with a derived class to support thread pooling.
     *
     * All thread-related stuff is in this class.
     */
    public static class ThreadController
    {
  
      /**
       * Will get a thread from the pool, execute the task
       *  and return the thread to the pool.
       *
       *  The return value is used only to wait for completion
       *
       *
       * NEEDSDOC @param task
       * @param priority if >0 the task will run with the given priority
       *  ( doesn't seem to be used in xalan, since it's allways the default )
       * @returns The thread that is running the task, can be used
       *          to wait for completion
       *
       * NEEDSDOC ($objectName$) @return
       */
      public Thread run(Runnable task, int priority)
      {
  
        Thread t = new Thread(task);
  
        t.start();
  
        //       if( priority > 0 )
        //      t.setPriority( priority );
        return t;
      }
  
      /**
       *  Wait until the task is completed on the worker
       *  thread.
       *
       * NEEDSDOC @param worker
       * NEEDSDOC @param task
       *
       * @throws InterruptedException
       */
      public void waitThread(Thread worker, Runnable task)
              throws InterruptedException
      {
  
        // This should wait until the transformThread is considered not alive.
        worker.join();
      }
    }
   
  }
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to