nodesorter.java

来自「java jdk 1.4的源码」· Java 代码 · 共 619 行 · 第 1/2 页

JAVA
619
字号
/* * 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.transformer;import java.util.Vector;import java.text.NumberFormat;import java.text.CollationKey;//import org.w3c.dom.Node;//import org.w3c.dom.traversal.NodeIterator;import org.apache.xml.dtm.DTM;import org.apache.xml.dtm.DTMIterator;import org.apache.xpath.axes.ContextNodeList;import org.apache.xpath.XPathContext;import org.apache.xpath.NodeSetDTM;import org.apache.xpath.objects.XObject;import org.apache.xpath.objects.XNodeSet;import org.apache.xml.utils.NodeVector;import javax.xml.transform.TransformerException;/** * <meta name="usage" content="internal"/> * This class can sort vectors of DOM nodes according to a select pattern. */public class NodeSorter{  /** Current XPath context           */  XPathContext m_execContext;  /** Vector of NodeSortKeys          */  Vector m_keys;  // vector of NodeSortKeys//  /**//   * TODO: Adjust this for locale.//   *///  NumberFormat m_formatter = NumberFormat.getNumberInstance();  /**   * Construct a NodeSorter, passing in the XSL TransformerFactory   * so it can know how to get the node data according to   * the proper whitespace rules.   *   * @param p Xpath context to use   */  public NodeSorter(XPathContext p)  {    m_execContext = p;  }  /**   * Given a vector of nodes, sort each node according to   * the criteria in the keys.   * @param v an vector of Nodes.   * @param keys a vector of NodeSortKeys.   * @param support XPath context to use   *   * @throws javax.xml.transform.TransformerException   */  public void sort(DTMIterator v, Vector keys, XPathContext support)          throws javax.xml.transform.TransformerException  {    m_keys = keys;    // QuickSort2(v, 0, v.size() - 1 );    int n = v.getLength();    // %OPT% Change mergesort to just take a DTMIterator?    // We would also have to adapt DTMIterator to have the function     // of NodeCompareElem.        // Create a vector of node compare elements    // based on the input vector of nodes    Vector nodes = new Vector();    for (int i = 0; i < n; i++)    {      NodeCompareElem elem = new NodeCompareElem(v.item(i));      nodes.addElement(elem);    }    Vector scratchVector = new Vector();    mergesort(nodes, scratchVector, 0, n - 1, support);    // return sorted vector of nodes    for (int i = 0; i < n; i++)    {      v.setItem(((NodeCompareElem) nodes.elementAt(i)).m_node, i);    }    v.setCurrentPos(0);    // old code...    //NodeVector scratchVector = new NodeVector(n);    //mergesort(v, scratchVector, 0, n - 1, support);  }  /**   * Return the results of a compare of two nodes.   * TODO: Optimize compare -- cache the getStringExpr results, key by m_selectPat + hash of node.   *   * @param n1 First node to use in compare   * @param n2 Second node to use in compare   * @param kIndex Index of NodeSortKey to use for sort   * @param support XPath context to use   *   * @return The results of the compare of the two nodes.   *   * @throws TransformerException   */  int compare(          NodeCompareElem n1, NodeCompareElem n2, int kIndex, XPathContext support)            throws TransformerException  {    int result = 0;    NodeSortKey k = (NodeSortKey) m_keys.elementAt(kIndex);    if (k.m_treatAsNumbers)    {      double n1Num, n2Num;      if (kIndex == 0)      {        n1Num = ((Double) n1.m_key1Value).doubleValue();        n2Num = ((Double) n2.m_key1Value).doubleValue();      }      else if (kIndex == 1)      {        n1Num = ((Double) n1.m_key2Value).doubleValue();        n2Num = ((Double) n2.m_key2Value).doubleValue();      }      /* Leave this in case we decide to use an array later      if (kIndex < maxkey)      {      double n1Num = (double)n1.m_keyValue[kIndex];      double n2Num = (double)n2.m_keyValue[kIndex];      }*/      else      {        // Get values dynamically        XObject r1 = k.m_selectPat.execute(m_execContext, n1.m_node,                                           k.m_namespaceContext);        XObject r2 = k.m_selectPat.execute(m_execContext, n2.m_node,                                           k.m_namespaceContext);        n1Num = r1.num();        // Can't use NaN for compare. They are never equal. Use zero instead.        // That way we can keep elements in document order.         //n1Num = Double.isNaN(d) ? 0.0 : d;        n2Num = r2.num();        //n2Num = Double.isNaN(d) ? 0.0 : d;      }      if ((n1Num == n2Num) && ((kIndex + 1) < m_keys.size()))      {        result = compare(n1, n2, kIndex + 1, support);      }      else      {        double diff;        if (Double.isNaN(n1Num))        {          if (Double.isNaN(n2Num))            diff = 0.0;          else            diff = -1;        }        else if (Double.isNaN(n2Num))           diff = 1;        else          diff = n1Num - n2Num;        // process order parameter         result = (int) ((diff < 0.0)                        ? (k.m_descending ? 1 : -1)                        : (diff > 0.0) ? (k.m_descending ? -1 : 1) : 0);      }    }  // end treat as numbers     else    {      CollationKey n1String, n2String;      if (kIndex == 0)      {        n1String = (CollationKey) n1.m_key1Value;        n2String = (CollationKey) n2.m_key1Value;      }      else if (kIndex == 1)      {        n1String = (CollationKey) n1.m_key2Value;        n2String = (CollationKey) n2.m_key2Value;      }      /* Leave this in case we decide to use an array later      if (kIndex < maxkey)      {        String n1String = (String)n1.m_keyValue[kIndex];        String n2String = (String)n2.m_keyValue[kIndex];      }*/      else      {        // Get values dynamically        XObject r1 = k.m_selectPat.execute(m_execContext, n1.m_node,                                           k.m_namespaceContext);        XObject r2 = k.m_selectPat.execute(m_execContext, n2.m_node,                                           k.m_namespaceContext);        n1String = k.m_col.getCollationKey(r1.str());        n2String = k.m_col.getCollationKey(r2.str());      }      // Use collation keys for faster compare, but note that whitespaces       // etc... are treated differently from if we were comparing Strings.      result = n1String.compareTo(n2String);      //Process caseOrder parameter      if (k.m_caseOrderUpper)      {        String tempN1 = n1String.getSourceString().toLowerCase();        String tempN2 = n2String.getSourceString().toLowerCase();        if (tempN1.equals(tempN2))        {          //java defaults to upper case is greater.          result = result == 0 ? 0 : -result;        }      }      //Process order parameter      if (k.m_descending)      {        result = -result;      }    }  //end else    if (0 == result)    {      if ((kIndex + 1) < m_keys.size())      {        result = compare(n1, n2, kIndex + 1, support);      }    }    if (0 == result)    {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?