content: /*
   *  This file is part of AndroidIDE.
   *
   *  AndroidIDE is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  AndroidIDE is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *   along with AndroidIDE.  If not, see <https://www.gnu.org/licenses/>.
   */
  
  /*
   * reserved comment block
   * DO NOT REMOVE OR ALTER!
   */
  /*
   * 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.5 2005/09/28 13:48:36 pvedula Exp $
   */
  
  package jaxp.sun.org.apache.xalan.internal.xsltc.dom;
  
  import java.text.Collator;
  import java.util.Locale;
  
  import jaxp.sun.org.apache.xalan.internal.xsltc.CollatorFactory;
  import jaxp.sun.org.apache.xalan.internal.xsltc.DOM;
  import jaxp.sun.org.apache.xalan.internal.xsltc.TransletException;
  import jaxp.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
  import jaxp.sun.org.apache.xml.internal.utils.StringComparable;
  import jaxp.sun.org.apache.xalan.internal.utils.ObjectFactory;
  import jaxp.sun.org.apache.xalan.internal.utils.SecuritySupport;
  
  /**
   * 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];
  
          String colFactClassname = null;
          try {
              // -- W. Eliot Kimber (eliot@isogen.com)
              colFactClassname =
                  SecuritySupport.getSystemProperty("jaxp.sun.org.apache.xalan.internal.xsltc.COLLATOR_FACTORY");
          }
          catch (SecurityException e) {
              // If we can't read the propery, just use default collator
          }
  
          if (colFactClassname != null) {
              try {
                  Object candObj = ObjectFactory.findProviderClass(colFactClassname, 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);
  
  }
  