/* CollationKey.java -- Precomputed collation value
   Copyright (C) 1998, 1999, 2000, 2003, 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 java.util.Arrays;

/* 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 represents a pre-computed series of bits representing a
 * <code>String</code> for under a particular <code>Collator</code>.  This
 * value may be compared bitwise against another <code>CollationKey</code>
 * representing a different <code>String</code> under the same
 * <code>Collator</code> in a manner than is usually more efficient than
 * using the raw <code>Collator</code> compare methods.  There is overhead
 * associated with calculating this value, so it is generally not
 * advisable to compute <code>CollationKey</code>'s unless multiple
 * comparisons against a <code>String</code> will be done.  (For example,
 * in a sort routine).
 * <p>
 * This class cannot be instantiated directly.  Instead, a
 * <code>CollationKey</code> is created by calling the
 * <code>getCollationKey</code> method on an instance of <code>Collator</code>.
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Tom Tromey (tromey@cygnus.com)
 * @date March 25, 1999
 */
public class CollationKey implements Comparable<CollationKey>
{
  /**
   * This is the <code>Collator</code> this object was created from.
   */
  private Collator collator;

  /**
   * This is the <code>String</code> this object represents.
   */
  private String originalText;

  /**
   * This is the bit value for this key.
   */
  private byte[] key;

  CollationKey (Collator collator, String originalText, byte[] key)
  {
    this.collator = collator;
    this.originalText = originalText;
    this.key = key;
  }

  /**
   * This method compares the specified object to this one.  An integer is
   * returned which indicates whether the specified object is less than,
   * greater than, or equal to this object.
   *
   * @param ck The <code>CollationKey</code> to compare against this one.
   *
   * @return A negative integer if this object is less than the specified object, 0 if it is equal or a positive integer if it is greater than the specified object.
   */
  public int compareTo (CollationKey ck)
  {
    int max = Math.min (key.length, ck.key.length);

    for (int i = 0; i < max; ++i)
      {
        if (key[i] != ck.key[i])
          return key[i] - ck.key[i];
      }

    return key.length - ck.key.length;
  }

  /**
   * This method tests the specified <code>Object</code> for equality with
   * this object.  This will be true if and only if:
   * <p>
   * <ul>
   * <li>The specified object must not be <code>null</code></li>
   * <li>The specified object is an instance of <code>CollationKey</code>.</li>
   * <li>The specified object was created from the same <code>Collator</code>
   * as this object.</li>
   * <li>The specified object has the same source string and bit key as
   * this object.</li>
   * </ul>
   *
   * @param obj The <code>Object</code> to test for equality.
   *
   * @return <code>true</code> if the specified object is equal to this one, <code>false</code> otherwise.
   */
  public boolean equals (Object obj)
  {
    if (! (obj instanceof CollationKey))
      return false;

    CollationKey ck = (CollationKey) obj;

    if (ck.collator != collator)
      return false;

    if (!ck.getSourceString ().equals (getSourceString ()))
      return false;

    if (! Arrays.equals (ck.toByteArray (), toByteArray ()))
      return false;

    return true;
  }

  /**
   * This method returns the <code>String</code> that this object was created
   * from.
   *
   * @return The source <code>String</code> for this object.
   */
  public String getSourceString()
  {
    return originalText;
  }

  /**
   * This method returns a hash value for this object.  The hash value
   * returned will be the hash code of the bit key so that identical bit
   * keys will return the same value.
   *
   * @return A hash value for this object.
   */
  public int hashCode()
  {
    // We just follow BitSet instead of thinking up something new.
    long h = originalText.hashCode();
    for (int i = key.length - 1; i >= 0; --i)
      h ^= key[i] * (i + 1);
    return (int) ((h >> 32) ^ h);
  }

  /**
   * This method returns the collation bit sequence as a byte array.
   *
   * @return A byte array containing the collation bit sequence.
   */
  public byte[] toByteArray()
  {
    return key;
  }
}
