- /*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /*
- * $Id: NodeSortRecord.java,v 1.19 2004/02/27 01:58:29 zongaro Exp $
- */
-
- package com.sun.org.apache.xalan.internal.xsltc.dom;
-
- import java.text.CollationKey;
- import java.text.Collator;
- import java.util.Locale;
-
- import com.sun.org.apache.xalan.internal.xsltc.CollatorFactory;
- import com.sun.org.apache.xalan.internal.xsltc.DOM;
- import com.sun.org.apache.xalan.internal.xsltc.TransletException;
- import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
- import com.sun.org.apache.xml.internal.utils.StringComparable;
-
- /**
- * Base class for sort records containing application specific sort keys
- */
- public abstract class NodeSortRecord {
- public static final int COMPARE_STRING = 0;
- public static final int COMPARE_NUMERIC = 1;
-
- public static final int COMPARE_ASCENDING = 0;
- public static final int COMPARE_DESCENDING = 1;
-
- /**
- * A reference to a collator. May be updated by subclass if the stylesheet
- * specifies a different language (will be updated iff _locale is updated).
- * @deprecated This field continues to exist for binary compatibility.
- * New code should not refer to it.
- */
- private static final Collator DEFAULT_COLLATOR = Collator.getInstance();
-
- /**
- * A reference to the first Collator
- * @deprecated This field continues to exist for binary compatibility.
- * New code should not refer to it.
- */
- protected Collator _collator = DEFAULT_COLLATOR;
- protected Collator[] _collators;
-
- /**
- * A locale field that might be set by an instance of a subclass.
- * @deprecated This field continues to exist for binary compatibility.
- * New code should not refer to it.
- */
- protected Locale _locale;
-
- protected CollatorFactory _collatorFactory;
-
- protected SortSettings _settings;
-
- private DOM _dom = null;
- private int _node; // The position in the current iterator
- private int _last = 0; // Number of nodes in the current iterator
- private int _scanned = 0; // Number of key levels extracted from DOM
-
- private Object[] _values; // Contains Comparable objects
-
- /**
- * This constructor is run by a call to ClassLoader in the
- * makeNodeSortRecord method in the NodeSortRecordFactory class. Since we
- * cannot pass any parameters to the constructor in that case we just set
- * the default values here and wait for new values through initialize().
- */
- public NodeSortRecord(int node) {
- _node = node;
- }
-
- public NodeSortRecord() {
- this(0);
- }
-
- /**
- * This method allows the caller to set the values that could not be passed
- * to the default constructor.
- */
- public final void initialize(int node, int last, DOM dom,
- SortSettings settings)
- throws TransletException
- {
- _dom = dom;
- _node = node;
- _last = last;
- _settings = settings;
-
- int levels = settings.getSortOrders().length;
- _values = new Object[levels];
-
- // -- W. Eliot Kimber (eliot@isogen.com)
- String colFactClassname =
- System.getProperty("com.sun.org.apache.xalan.internal.xsltc.COLLATOR_FACTORY");
-
- if (colFactClassname != null) {
- try {
- Object candObj = ObjectFactory.findProviderClass(
- colFactClassname, ObjectFactory.findClassLoader(), true);
- _collatorFactory = (CollatorFactory)candObj;
- } catch (ClassNotFoundException e) {
- throw new TransletException(e);
- }
- Locale[] locales = settings.getLocales();
- _collators = new Collator[levels];
- for (int i = 0; i < levels; i++){
- _collators[i] = _collatorFactory.getCollator(locales[i]);
- }
- _collator = _collators[0];
- } else {
- _collators = settings.getCollators();
- _collator = _collators[0];
- }
- }
-
- /**
- * Returns the node for this sort object
- */
- public final int getNode() {
- return _node;
- }
-
- /**
- *
- */
- public final int compareDocOrder(NodeSortRecord other) {
- return _node - other._node;
- }
-
- /**
- * Get the string or numeric value of a specific level key for this sort
- * element. The value is extracted from the DOM if it is not already in
- * our sort key vector.
- */
- private final Comparable stringValue(int level) {
- // Get value from our array if possible
- if (_scanned <= level) {
- AbstractTranslet translet = _settings.getTranslet();
- Locale[] locales = _settings.getLocales();
- String[] caseOrder = _settings.getCaseOrders();
-
- // Get value from DOM if accessed for the first time
- final String str = extractValueFromDOM(_dom, _node, level,
- translet, _last);
- final Comparable key =
- StringComparable.getComparator(str, locales[level],
- _collators[level],
- caseOrder[level]);
- _values[_scanned++] = key;
- return(key);
- }
- return((Comparable)_values[level]);
- }
-
- private final Double numericValue(int level) {
- // Get value from our vector if possible
- if (_scanned <= level) {
- AbstractTranslet translet = _settings.getTranslet();
-
- // Get value from DOM if accessed for the first time
- final String str = extractValueFromDOM(_dom, _node, level,
- translet, _last);
- Double num;
- try {
- num = new Double(str);
- }
- // Treat number as NaN if it cannot be parsed as a double
- catch (NumberFormatException e) {
- num = new Double(Double.NEGATIVE_INFINITY);
- }
- _values[_scanned++] = num;
- return(num);
- }
- return((Double)_values[level]);
- }
-
- /**
- * Compare this sort element to another. The first level is checked first,
- * and we proceed to the next level only if the first level keys are
- * identical (and so the key values may not even be extracted from the DOM)
- *
- * !!!!MUST OPTIMISE - THIS IS REALLY, REALLY SLOW!!!!
- */
- public int compareTo(NodeSortRecord other) {
- int cmp, level;
- int[] sortOrder = _settings.getSortOrders();
- int levels = _settings.getSortOrders().length;
- int[] compareTypes = _settings.getTypes();
-
- for (level = 0; level < levels; level++) {
- // Compare the two nodes either as numeric or text values
- if (compareTypes[level] == COMPARE_NUMERIC) {
- final Double our = numericValue(level);
- final Double their = other.numericValue(level);
- cmp = our.compareTo(their);
- }
- else {
- final Comparable our = stringValue(level);
- final Comparable their = other.stringValue(level);
- cmp = our.compareTo(their);
- }
-
- // Return inverse compare value if inverse sort order
- if (cmp != 0) {
- return sortOrder[level] == COMPARE_DESCENDING ? 0 - cmp : cmp;
- }
- }
- // Compare based on document order if all sort keys are equal
- return(_node - other._node);
- }
-
- /**
- * Returns the array of Collators used for text comparisons in this object.
- * May be overridden by inheriting classes
- */
- public Collator[] getCollator() {
- return _collators;
- }
-
- /**
- * Extract the sort value for a level of this key.
- */
- public abstract String extractValueFromDOM(DOM dom, int current, int level,
- AbstractTranslet translet,
- int last);
-
- }