/* RuleBasedCollator.java -- Concrete Collator Class
   Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath 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 2, or (at your option)
any later version.

GNU Classpath 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 GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.text;

import gnu.classpath.NotImplementedException;

import java.util.ArrayList;
import java.util.HashMap;

/* Written using "Java Class Libraries", 2nd edition, plus online
 * API docs for JDK 1.2 from http://www.javasoft.com.
 * Status: Believed complete and correct
 */

/**
 * This class is a concrete subclass of <code>Collator</code> suitable
 * for string collation in a wide variety of languages.  An instance of
 * this class is normally returned by the <code>getInstance</code> method
 * of <code>Collator</code> with rules predefined for the requested
 * locale.  However, an instance of this class can be created manually
 * with any desired rules.
 * <p>
 * Rules take the form of a <code>String</code> with the following syntax
 * <ul>
 * <li> Modifier: '@'</li>
 * <li> Relation: '&lt;' | ';' | ',' | '=' : &lt;text&gt;</li>
 * <li> Reset: '&amp;' : &lt;text&gt;</li>
 * </ul>
 * The modifier character indicates that accents sort backward as is the
 * case with French.  The modifier applies to all rules <b>after</b>
 * the modifier but before the next primary sequence. If placed at the end
 * of the sequence if applies to all unknown accented character.
 * The relational operators specify how the text
 * argument relates to the previous term.  The relation characters have
 * the following meanings:
 * <ul>
 * <li>'&lt;' - The text argument is greater than the prior term at the primary
 * difference level.</li>
 * <li>';' - The text argument is greater than the prior term at the secondary
 * difference level.</li>
 * <li>',' - The text argument is greater than the prior term at the tertiary
 * difference level.</li>
 * <li>'=' - The text argument is equal to the prior term</li>
 * </ul>
 * <p>
 * As for the text argument itself, this is any sequence of Unicode
 * characters not in the following ranges: 0x0009-0x000D, 0x0020-0x002F,
 * 0x003A-0x0040, 0x005B-0x0060, and 0x007B-0x007E. If these characters are
 * desired, they must be enclosed in single quotes.  If any whitespace is
 * encountered, it is ignored.  (For example, "a b" is equal to "ab").
 * <p>
 * The reset operation inserts the following rule at the point where the
 * text argument to it exists in the previously declared rule string.  This
 * makes it easy to add new rules to an existing string by simply including
 * them in a reset sequence at the end.  Note that the text argument, or
 * at least the first character of it, must be present somewhere in the
 * previously declared rules in order to be inserted properly.  If this
 * is not satisfied, a <code>ParseException</code> will be thrown.
 * <p>
 * This system of configuring <code>RuleBasedCollator</code> is needlessly
 * complex and the people at Taligent who developed it (along with the folks
 * at Sun who accepted it into the Java standard library) deserve a slow
 * and agonizing death.
 * <p>
 * Here are a couple of example of rule strings:
 * <p>
 * "&lt; a &lt; b &lt; c" - This string says that a is greater than b which is
 * greater than c, with all differences being primary differences.
 * <p>
 * "&lt; a,A &lt; b,B &lt; c,C" - This string says that 'A' is greater than 'a' with
 * a tertiary strength comparison.  Both 'b' and 'B' are greater than 'a' and
 * 'A' during a primary strength comparison.  But 'B' is greater than 'b'
 * under a tertiary strength comparison.
 * <p>
 * "&lt; a &lt; c &amp; a &lt; b " - This sequence is identical in function to the
 * "&lt; a &lt; b &lt; c" rule string above.  The '&amp;' reset symbol indicates that
 * the rule "&lt; b" is to be inserted after the text argument "a" in the
 * previous rule string segment.
 * <p>
 * "&lt; a &lt; b &amp; y &lt; z" - This is an error.  The character 'y' does not appear
 * anywhere in the previous rule string segment so the rule following the
 * reset rule cannot be inserted.
 * <p>
 * "&lt; a &amp; A @ &lt; e &amp; E &lt; f&amp; F" - This sequence is equivalent to the following
 * "&lt; a &amp; A &lt; E &amp; e &lt; f &amp; F".
 * <p>
 * For a description of the various comparison strength types, see the
 * documentation for the <code>Collator</code> class.
 * <p>
 * As an additional complication to this already overly complex rule scheme,
 * if any characters precede the first rule, these characters are considered
 * ignorable.  They will be treated as if they did not exist during
 * comparisons.  For example, "- &lt; a &lt; b ..." would make '-' an ignorable
 * character such that the strings "high-tech" and "hightech" would
 * be considered identical.
 * <p>
 * A <code>ParseException</code> will be thrown for any of the following
 * conditions:
 * <ul>
 * <li>Unquoted punctuation characters in a text argument.</li>
 * <li>A relational or reset operator not followed by a text argument</li>
 * <li>A reset operator where the text argument is not present in
 * the previous rule string section.</li>
 * </ul>
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Tom Tromey (tromey@cygnus.com)
 * @author Guilhem Lavaux (guilhem@kaffe.org)
 */
public class RuleBasedCollator extends Collator
{
  /**
   * This class describes what rank has a character (or a sequence of characters)
   * in the lexicographic order. Each element in a rule has a collation element.
   */
  static final class CollationElement
  {
    final String key;
    final int primary;
    final short secondary;
    final short tertiary;
    final short equality;
    final boolean ignore;
    final String expansion;

    CollationElement(String key, int primary, short secondary, short tertiary,
                     short equality, String expansion, boolean ignore)
    {
      this.key = key;
      this.primary = primary;
      this.secondary = secondary;
      this.tertiary = tertiary;
      this.equality = equality;
      this.ignore = ignore;
      this.expansion = expansion;
    }

    int getValue()
    {
      return (primary << 16) + (secondary << 8) + tertiary;
    }
  }

  /**
   * Basic collation instruction (internal format) to build the series of
   * collation elements. It contains an instruction which specifies the new
   * state of the generator. The sequence of instruction should not contain
   * RESET (it is used by
   * {@link #mergeRules(int,java.lang.String,java.util.ArrayList,java.util.ArrayList)})
   * as a temporary state while merging two sets of instructions.
   */
  private static final class CollationSorter
  {
    static final int GREATERP = 0;
    static final int GREATERS = 1;
    static final int GREATERT = 2;
    static final int EQUAL = 3;
    static final int RESET = 4;
    static final int INVERSE_SECONDARY = 5;

    final int comparisonType;
    final String textElement;
    final int hashText;
    final int offset;
    final boolean ignore;

    String expansionOrdering;

    private CollationSorter(final int comparisonType, final String textElement,
                            final int offset, final boolean ignore)
    {
      this.comparisonType = comparisonType;
      this.textElement = textElement;
      this.offset = offset;
      this.ignore = ignore;
      hashText = textElement.hashCode();
    }
  }

  /**
   * This is the original rule string.
   */
  private String rules;

  /**
   * This is the table of collation element values
   */
  private CollationElement[] ce_table;

  /**
   * Quick-prefix finder.
   */
  HashMap<String,CollationElement> prefix_tree;

  /**
   * This is the value of the last sequence entered into
   * <code>ce_table</code>. It is used to compute the
   * ordering value of unspecified character.
   */
  private int last_primary_value;

  /**
   * This is the value of the last secondary sequence of the
   * primary 0, entered into
   * <code>ce_table</code>. It is used to compute the
   * ordering value of an unspecified accented character.
   */
  private int last_tertiary_value;

  /**
   * This variable is true if accents need to be sorted
   * in the other direction.
   */
  private boolean inverseAccentComparison;

  /**
   * This collation element is special to unknown sequence.
   * The JDK uses it to mark and sort the characters which has
   * no collation rules.
   */
  static final CollationElement SPECIAL_UNKNOWN_SEQ =
    new CollationElement("", (short) 32767, (short) 0, (short) 0,
                         (short) 0, null, false);

  /**
   * This method initializes a new instance of <code>RuleBasedCollator</code>
   * with the specified collation rules.  Note that an application normally
   * obtains an instance of <code>RuleBasedCollator</code> by calling the
   * <code>getInstance</code> method of <code>Collator</code>.  That method
   * automatically loads the proper set of rules for the desired locale.
   *
   * @param rules The collation rule string.
   *
   * @exception ParseException If the rule string contains syntax errors.
   */
  public RuleBasedCollator(String rules) throws ParseException
  {
    if (rules.equals(""))
      throw new ParseException("empty rule set", 0);

    this.rules = rules;

    buildCollationVector(parseString(rules));
    buildPrefixAccess();
  }

  /**
   * This method returns the number of common characters at the beginning
   * of the string of the two parameters.
   *
   * @param prefix A string considered as a prefix to test against
   * the other string.
   * @param s A string to test the prefix against.
   * @return The number of common characters.
   */
  static int findPrefixLength(String prefix, String s)
  {
    int index;
    int len = prefix.length();

    for (index = 0; index < len && index < s.length(); ++index)
      {
        if (prefix.charAt(index) != s.charAt(index))
          return index;
      }


    return index;
  }

  /**
   * Here we are merging two sets of sorting instructions: 'patch' into 'main'. This methods
   * checks whether it is possible to find an anchor point for the rules to be merged and
   * then insert them at that precise point.
   *
   * @param offset Offset in the string containing rules of the beginning of the rules
   * being merged in.
   * @param starter Text of the rules being merged.
   * @param main Repository of all already parsed rules.
   * @param patch Rules to be merged into the repository.
   * @throws ParseException if it is impossible to find an anchor point for the new rules.
   */
  private void mergeRules(int offset, String starter, ArrayList<CollationSorter> main,
                          ArrayList<CollationSorter> patch)
    throws ParseException
  {
    int insertion_point = -1;
    int max_length = 0;

    /* We must check that no rules conflict with another already present. If it
     * is the case delete the old rule.
     */

    /* For the moment good old O(N^2) algorithm.
     */
    for (int i = 0; i < patch.size(); i++)
      {
        int j = 0;

        while (j < main.size())
          {
            CollationSorter rule1 = patch.get(i);
            CollationSorter rule2 = main.get(j);

            if (rule1.textElement.equals(rule2.textElement))
              main.remove(j);
            else
              j++;
          }
      }

    // Find the insertion point... O(N)
    for (int i = 0; i < main.size(); i++)
      {
        CollationSorter sorter = main.get(i);
        int length = findPrefixLength(starter, sorter.textElement);

        if (length > max_length)
          {
            max_length = length;
            insertion_point = i+1;
          }
      }

    if (insertion_point < 0)
      throw new ParseException("no insertion point found for " + starter, offset);

    if (max_length < starter.length())
      {
        /*
         * We need to expand the first entry. It must be sorted
         * like if it was the reference key itself (like the spec
         * said. So the first entry is special: the element is
         * replaced by the specified text element for the sorting.
         * This text replace the old one for comparisons. However
         * to preserve the behaviour we replace the first key (corresponding
         * to the found prefix) by a new code rightly ordered in the
         * sequence. The rest of the subsequence must be appended
         * to the end of the sequence.
         */
        CollationSorter sorter = patch.get(0);

        sorter.expansionOrdering = starter.substring(max_length); // Skip the first good prefix element

        main.add(insertion_point, sorter);

        /*
         * This is a new set of rules. Append to the list.
         */
        patch.remove(0);
        insertion_point++;
      }

    // Now insert all elements of patch at the insertion point.
    for (int i = 0; i < patch.size(); i++)
      main.add(i+insertion_point, patch.get(i));
  }

  /**
   * This method parses a string and build a set of sorting instructions. The parsing
   * may only be partial on the case the rules are to be merged sometime later.
   *
   * @param stop_on_reset If this parameter is true then the parser stops when it
   * encounters a reset instruction. In the other case, it tries to parse the subrules
   * and merged it in the same repository.
   * @param v Output vector for the set of instructions.
   * @param base_offset Offset in the string to begin parsing.
   * @param rules Rules to be parsed.
   * @return -1 if the parser reached the end of the string, an integer representing the
   * offset in the string at which it stopped parsing.
   * @throws ParseException if something turned wrong during the parsing. To get details
   * decode the message.
   */
  private int subParseString(boolean stop_on_reset, ArrayList<CollationSorter> v,
                             int base_offset, String rules)
    throws ParseException
  {
    boolean ignoreChars = (base_offset == 0);
    int operator = -1;
    StringBuilder sb = new StringBuilder();
    boolean doubleQuote = false;
    boolean eatingChars = false;
    boolean nextIsModifier = false;
    boolean isModifier = false;
    int i;

main_parse_loop:
    for (i = 0; i < rules.length(); i++)
      {
        char c = rules.charAt(i);
        int type = -1;

        if (!eatingChars &&
            ((c >= 0x09 && c <= 0x0D) || (c == 0x20)))
              continue;

        isModifier = nextIsModifier;
        nextIsModifier = false;

        if (eatingChars && c != '\'')
          {
            doubleQuote = false;
            sb.append(c);
            continue;
          }
        if (doubleQuote && eatingChars)
          {
            sb.append(c);
            doubleQuote = false;
            continue;
          }

        switch (c)
          {
          case '!':
            throw new ParseException
              ("Modifier '!' is not yet supported by Classpath", i + base_offset);
          case '<':
            type = CollationSorter.GREATERP;
            break;
          case ';':
            type = CollationSorter.GREATERS;
            break;
          case ',':
            type = CollationSorter.GREATERT;
            break;
          case '=':
            type = CollationSorter.EQUAL;
            break;
          case '\'':
            eatingChars = !eatingChars;
            doubleQuote = true;
            break;
          case '@':
            if (ignoreChars)
              throw new ParseException
                ("comparison list has not yet been started. You may only use"
                 + "(<,;=&)", i + base_offset);
            // Inverse the order of secondaries from now on.
            nextIsModifier = true;
            type = CollationSorter.INVERSE_SECONDARY;
            break;
          case '&':
            type = CollationSorter.RESET;
            if (stop_on_reset)
              break main_parse_loop;
            break;
          default:
            if (operator < 0)
              throw new ParseException
                ("operator missing at " + (i + base_offset), i + base_offset);
            if (! eatingChars
                && ((c >= 0x21 && c <= 0x2F)
                    || (c >= 0x3A && c <= 0x40)
                    || (c >= 0x5B && c <= 0x60)
                    || (c >= 0x7B && c <= 0x7E)))
              throw new ParseException
                ("unquoted punctuation character '" + c + "'", i + base_offset);

            //type = ignoreChars ? CollationSorter.IGNORE : -1;
            sb.append(c);
            break;
          }

        if (type  < 0)
          continue;

        if (operator < 0)
          {
            operator = type;
            continue;
          }

        if (sb.length() == 0 && !isModifier)
          throw new ParseException
            ("text element empty at " + (i+base_offset), i+base_offset);

        if (operator == CollationSorter.RESET)
          {
            /* Reposition in the sorting list at the position
             * indicated by the text element.
             */
            String subrules = rules.substring(i);
            ArrayList<CollationSorter> sorted_rules = new ArrayList<CollationSorter>();
            int idx;

            // Parse the subrules but do not iterate through all
            // sublist. This is the privilege of the first call.
            idx = subParseString(true, sorted_rules, base_offset+i, subrules);

            // Merge new parsed rules into the list.
            mergeRules(base_offset+i, sb.toString(), v, sorted_rules);
            sb.setLength(0);

            // Reset state to none.
            operator = -1;
            type = -1;
            // We have found a new subrule at 'idx' but it has not been parsed.
            if (idx >= 0)
              {
                i += idx-1;
                continue main_parse_loop;
              }
            else
                // No more rules.
                break main_parse_loop;
          }

        String textElement = sb.toString();
        if (operator == CollationSorter.GREATERP)
          ignoreChars = false;
        CollationSorter sorter = new CollationSorter(operator, textElement,
                                                     base_offset + rules.length(),
                                                     ignoreChars);
        sb.setLength(0);

        v.add(sorter);
        operator = type;
      }

    if (operator >= 0)
      {
        int pos = rules.length() + base_offset;

        if ((sb.length() != 0 && nextIsModifier)
            || (sb.length() == 0 && !nextIsModifier && !eatingChars))
          throw new ParseException("text element empty at " + pos, pos);

        if (operator == CollationSorter.GREATERP)
          ignoreChars = false;

        CollationSorter sorter = new CollationSorter(operator, sb.toString(),
                                                     base_offset+pos, ignoreChars);
        v.add(sorter);
      }

    if (i == rules.length())
      return -1;
    else
      return i;
  }

  /**
   * This method creates a copy of this object.
   *
   * @return A copy of this object.
   */
  public Object clone()
  {
    return super.clone();
  }

  /**
   * This method completely parses a string 'rules' containing sorting rules.
   *
   * @param rules String containing the rules to be parsed.
   * @return A set of sorting instructions stored in a Vector.
   * @throws ParseException if something turned wrong during the parsing. To get details
   * decode the message.
   */
  private ArrayList<CollationSorter> parseString(String rules)
    throws ParseException
  {
    ArrayList<CollationSorter> v = new ArrayList<CollationSorter>();

    // result of the first subParseString is not absolute (may be -1 or a
    // positive integer). But we do not care.
    subParseString(false, v, 0, rules);

    return v;
  }

  /**
   * This method uses the sorting instructions built by {@link #parseString}
   * to build collation elements which can be directly used to sort strings.
   *
   * @param parsedElements Parsed instructions stored in a ArrayList.
   * @throws ParseException if the order of the instructions are not valid.
   */
  private void buildCollationVector(ArrayList<CollationSorter> parsedElements)
    throws ParseException
  {
    int primary_seq = 0;
    int last_tertiary_seq = 0;
    short secondary_seq = 0;
    short tertiary_seq = 0;
    short equality_seq = 0;
    boolean inverseComparisons = false;
    final boolean DECREASING = false;
    final boolean INCREASING = true;
    boolean secondaryType = INCREASING;
    ArrayList<CollationElement> v = new ArrayList<CollationElement>();

    // elts is completely sorted.
element_loop:
    for (int i = 0; i < parsedElements.size(); i++)
      {
        CollationSorter elt = parsedElements.get(i);

        switch (elt.comparisonType)
          {
          case CollationSorter.GREATERP:
            primary_seq++;
            if (inverseComparisons)
              {
                secondary_seq = Short.MAX_VALUE;
                secondaryType = DECREASING;
              }
            else
              {
                secondary_seq = 0;
                secondaryType = INCREASING;
              }
            tertiary_seq = 0;
            equality_seq = 0;
            inverseComparisons = false;
            break;
          case CollationSorter.GREATERS:
            if (secondaryType == DECREASING)
              secondary_seq--;
            else
              secondary_seq++;
            tertiary_seq = 0;
            equality_seq = 0;
            break;
          case CollationSorter.INVERSE_SECONDARY:
            inverseComparisons = true;
            continue element_loop;
          case CollationSorter.GREATERT:
            tertiary_seq++;
            if (primary_seq == 0)
              last_tertiary_seq = tertiary_seq;
            equality_seq = 0;
            break;
          case CollationSorter.EQUAL:
            equality_seq++;
            break;
          case CollationSorter.RESET:
            throw new ParseException
              ("Invalid reached state 'RESET'. Internal error", elt.offset);
          default:
            throw new ParseException
              ("Invalid unknown state '" + elt.comparisonType + "'", elt.offset);
          }

        v.add(new CollationElement(elt.textElement, primary_seq,
                                   secondary_seq, tertiary_seq,
                                   equality_seq, elt.expansionOrdering, elt.ignore));
      }

    this.inverseAccentComparison = inverseComparisons;

    ce_table = v.toArray(new CollationElement[v.size()]);

    last_primary_value = primary_seq+1;
    last_tertiary_value = last_tertiary_seq+1;
  }

  /**
   * Build a tree where all keys are the texts of collation elements and data is
   * the collation element itself. The tree is used when extracting all prefix
   * for a given text.
   */
  private void buildPrefixAccess()
  {
    prefix_tree = new HashMap<String,CollationElement>();

    for (int i = 0; i < ce_table.length; i++)
      {
        CollationElement e = ce_table[i];

        prefix_tree.put(e.key, e);
      }
  }

  /**
   * This method returns an integer which indicates whether the first
   * specified <code>String</code> is less than, greater than, or equal to
   * the second.  The value depends not only on the collation rules in
   * effect, but also the strength and decomposition settings of this object.
   *
   * @param source The first <code>String</code> to compare.
   * @param target A second <code>String</code> to compare to the first.
   *
   * @return A negative integer if source &lt; target, a positive integer
   * if source &gt; target, or 0 if source == target.
   */
  public int compare(String source, String target)
  {
    CollationElementIterator cs, ct;
    CollationElement ord1block = null;
    CollationElement ord2block = null;
    boolean advance_block_1 = true;
    boolean advance_block_2 = true;

    cs = getCollationElementIterator(source);
    ct = getCollationElementIterator(target);

    for(;;)
      {
        int ord1;
        int ord2;

        /*
         * We have to check whether the characters are ignorable.
         * If it is the case then forget them.
         */
        if (advance_block_1)
          {
            ord1block = cs.nextBlock();
            if (ord1block != null && ord1block.ignore)
              continue;
          }

        if (advance_block_2)
          {
            ord2block = ct.nextBlock();
            if (ord2block != null && ord2block.ignore)
              {
                advance_block_1 = false;
                continue;
              }
         }
        else
          advance_block_2 = true;

        if (!advance_block_1)
          advance_block_1 = true;

        if (ord1block != null)
          ord1 = ord1block.getValue();
        else
          {
            if (ord2block == null)
              return 0;
            return -1;
          }

        if (ord2block == null)
          return 1;

        ord2 = ord2block.getValue();

        // We know chars are totally equal, so skip
        if (ord1 == ord2)
          {
            if (getStrength() == IDENTICAL)
              if (!ord1block.key.equals(ord2block.key))
                return ord1block.key.compareTo(ord2block.key);
            continue;
          }

        // Check for primary strength differences
        int prim1 = CollationElementIterator.primaryOrder(ord1);
        int prim2 = CollationElementIterator.primaryOrder(ord2);

        if (prim1 == 0 && getStrength() < TERTIARY)
          {
            advance_block_2 = false;
            continue;
          }
        else if (prim2 == 0 && getStrength() < TERTIARY)
          {
            advance_block_1 = false;
            continue;
          }

        if (prim1 < prim2)
          return -1;
        else if (prim1 > prim2)
          return 1;
        else if (getStrength() == PRIMARY)
          continue;

        // Check for secondary strength differences
        int sec1 = CollationElementIterator.secondaryOrder(ord1);
        int sec2 = CollationElementIterator.secondaryOrder(ord2);

        if (sec1 < sec2)
          return -1;
        else if (sec1 > sec2)
          return 1;
        else if (getStrength() == SECONDARY)
          continue;

        // Check for tertiary differences
        int tert1 = CollationElementIterator.tertiaryOrder(ord1);
        int tert2 = CollationElementIterator.tertiaryOrder(ord2);

        if (tert1 < tert2)
          return -1;
        else if (tert1 > tert2)
          return 1;
        else if (getStrength() == TERTIARY)
          continue;

        // Apparently JDK does this (at least for my test case).
        return ord1block.key.compareTo(ord2block.key);
      }
  }

  /**
   * This method tests this object for equality against the specified
   * object.  This will be true if and only if the specified object is
   * another reference to this object.
   *
   * @param obj The <code>Object</code> to compare against this object.
   *
   * @return <code>true</code> if the specified object is equal to this object,
   * <code>false</code> otherwise.
   */
  public boolean equals(Object obj)
  {
    if (obj == this)
      return true;
    else
      return false;
  }

  /**
   * This method builds a default collation element without invoking
   * the database created from the rules passed to the constructor.
   *
   * @param c Character which needs a collation element.
   * @return A valid brand new CollationElement instance.
   */
  CollationElement getDefaultElement(char c)
  {
    int v;

    // Preliminary support for generic accent sorting inversion (I don't know if all
    // characters in the range should be sorted backward). This is the place
    // to fix this if needed.
    if (inverseAccentComparison && (c >= 0x02B9 && c <= 0x0361))
      v = 0x0361 - ((int) c - 0x02B9);
    else
      v = (short) c;
    return new CollationElement("" + c, last_primary_value + v,
                                (short) 0, (short) 0, (short) 0, null, false);
  }

  /**
   * This method builds a default collation element for an accented character
   * without invoking the database created from the rules passed to the constructor.
   *
   * @param c Character which needs a collation element.
   * @return A valid brand new CollationElement instance.
   */
  CollationElement getDefaultAccentedElement(char c)
  {
    int v;

    // Preliminary support for generic accent sorting inversion (I don't know if all
    // characters in the range should be sorted backward). This is the place
    // to fix this if needed.
    if (inverseAccentComparison && (c >= 0x02B9 && c <= 0x0361))
      v = 0x0361 - ((int) c - 0x02B9);
    else
      v = (short) c;
    return new CollationElement("" + c, (short) 0,
                                (short) 0, (short) (last_tertiary_value + v), (short) 0, null, false);
  }

  /**
   * This method returns an instance for <code>CollationElementIterator</code>
   * for the specified <code>String</code> under the collation rules for this
   * object.
   *
   * @param source The <code>String</code> to return the
   * <code>CollationElementIterator</code> instance for.
   *
   * @return A <code>CollationElementIterator</code> for the specified
   * <code>String</code>.
   */
  public CollationElementIterator getCollationElementIterator(String source)
  {
    return new CollationElementIterator(this, source);
  }

  /**
   * This method returns an instance of <code>CollationElementIterator</code>
   * for the <code>String</code> represented by the specified
   * <code>CharacterIterator</code>.
   *
   * @param source The <code>CharacterIterator</code> with the desired <code>String</code>.
   *
   * @return A <code>CollationElementIterator</code> for the specified <code>String</code>.
   */
  public CollationElementIterator getCollationElementIterator(CharacterIterator source)
  {
    return new CollationElementIterator(this, source);
  }

  /**
   * This method returns an instance of <code>CollationKey</code> for the
   * specified <code>String</code>.  The object returned will have a
   * more efficient mechanism for its comparison function that could
   * provide speed benefits if multiple comparisons are performed, such
   * as during a sort.
   *
   * @param source The <code>String</code> to create a <code>CollationKey</code> for.
   *
   * @return A <code>CollationKey</code> for the specified <code>String</code>.
   */
  public CollationKey getCollationKey(String source)
  {
    CollationElementIterator cei = getCollationElementIterator(source);
    ArrayList<Integer> vect = new ArrayList<Integer>();

    int ord = cei.next();
    cei.reset(); //set to start of string

    while (ord != CollationElementIterator.NULLORDER)
      {
        // If the primary order is null, it means this is an ignorable
        // character.
        if (CollationElementIterator.primaryOrder(ord) == 0)
          {
            ord = cei.next();
            continue;
          }
        switch (getStrength())
          {
            case PRIMARY:
              ord = CollationElementIterator.primaryOrder(ord);
              break;

            case SECONDARY:
              ord = CollationElementIterator.primaryOrder(ord) << 8;
              ord |= CollationElementIterator.secondaryOrder(ord);

            default:
               break;
          }

        vect.add(Integer.valueOf(ord));
        ord = cei.next(); //increment to next key
      }

    Integer[] objarr = vect.toArray(new Integer[vect.size()]);
    byte[] key = new byte[objarr.length * 4];

    for (int i = 0; i < objarr.length; i++)
      {
        int j = objarr[i].intValue();
        key [i * 4] = (byte) ((j & 0xFF000000) >> 24);
        key [i * 4 + 1] = (byte) ((j & 0x00FF0000) >> 16);
        key [i * 4 + 2] = (byte) ((j & 0x0000FF00) >> 8);
        key [i * 4 + 3] = (byte) (j & 0x000000FF);
      }

    return new CollationKey(this, source, key);
  }

  /**
   * This method returns a <code>String</code> containing the collation rules
   * for this object.
   *
   * @return The collation rules for this object.
   */
  public String getRules()
  {
    return rules;
  }

  /**
   * This method returns a hash value for this object.
   *
   * @return A hash value for this object.
   */
  public int hashCode()
  {
    return System.identityHashCode(this);
  }
}
