/* Collator.java -- Perform locale dependent String comparisons.
   Copyright (C) 1998, 1999, 2000, 2001, 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.java.locale.LocaleHelper;

import java.util.Comparator;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

/**
 * This class is the abstract superclass of classes which perform 
 * locale dependent <code>String</code> comparisons.  A caller requests
 * an instance of <code>Collator</code> for a particular locale using
 * the <code>getInstance()</code> static method in this class.  That method
 * will return a locale specific subclass of <code>Collator</code> which
 * can be used to perform <code>String</code> comparisons for that locale.
 * If a subclass of <code>Collator</code> cannot be located for a particular
 * locale, a default instance for the current locale will be returned.  
 *
 * In addition to setting the correct locale, there are two additional
 * settings that can be adjusted to affect <code>String</code> comparisons:
 * strength and decomposition.  The strength value determines the level
 * of signficance of character differences required for them to sort
 * differently.  (For example, whether or not capital letters are considered
 * different from lower case letters).  The decomposition value affects how
 * variants of the same character are treated for sorting purposes.  (For
 * example, whether or not an accent is signficant or not).  These settings
 * are described in detail in the documentation for the methods and values
 * that are related to them.
 *
 * @author Tom Tromey (tromey@cygnus.com)
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @date March 18, 1999
 */
public abstract class Collator implements Comparator, Cloneable
{
  /**
   * This constant is a strength value which indicates that only primary
   * differences between characters will be considered signficant.  As an
   * example, two completely different English letters such as 'a' and 'b'
   * are considered to have a primary difference.
   */
  public static final int PRIMARY = 0;
  
  /**
   * This constant is a strength value which indicates that only secondary
   * or primary differences between characters will be considered
   * significant.  An example of a secondary difference between characters
   * are instances of the same letter with different accented forms.
   */
  public static final int SECONDARY = 1;
  
  /**
   * This constant is a strength value which indicates that tertiary,
   * secondary, and primary differences will be considered during sorting.
   * An example of a tertiary difference is capitalization of a given letter.
   * This is the default value for the strength setting.
   */
  public static final int TERTIARY = 2;
  
  /**
   * This constant is a strength value which indicates that any difference
   * at all between character values are considered significant.
   */
  public static final int IDENTICAL = 3;
  
  /**
   * This constant indicates that accented characters won't be decomposed
   * when performing comparisons.  This will yield the fastest results, but
   * will only work correctly in call cases for languages which do not
   * use accents such as English.
   */
  public static final int NO_DECOMPOSITION = 0;
  
  /**
   * This constant indicates that only characters which are canonical variants
   * in Unicode 2.0 will be decomposed prior to performing comparisons.  This
   * will cause accented languages to be sorted correctly.  This is the
   * default decomposition value.
   */
  public static final int CANONICAL_DECOMPOSITION = 1;
  
  /**
   * This constant indicates that both canonical variants and compatibility
   * variants in Unicode 2.0 will be decomposed prior to performing
   * comparisons.  This is the slowest mode, but is required to get the
   * correct sorting for certain languages with certain special formats.
   */
  public static final int FULL_DECOMPOSITION = 2;

  /**
   * This method initializes a new instance of <code>Collator</code> to have
   * the default strength (TERTIARY) and decomposition 
   * (CANONICAL_DECOMPOSITION) settings.  This constructor is protected and
   * is for use by subclasses only.  Non-subclass callers should use the
   * static <code>getInstance()</code> methods of this class to instantiate
   * <code>Collation</code> objects for the desired locale.
   */
  protected Collator ()
  {
    strength = TERTIARY;
    decmp = CANONICAL_DECOMPOSITION;
  }

  /**
   * This method compares the two <code>String</code>'s and returns an
   * integer indicating whether or not the first argument is less than,
   * equal to, or greater than the second argument.  The comparison is
   * performed according to the rules of the locale for this 
   * <code>Collator</code> and the strength and decomposition rules in
   * effect.
   *
   * @param source The first object to compare
   * @param target The second object to compare
   *
   * @return A negative integer if str1 &lt; str2, 0 if str1 == str2, or
   * a positive integer if str1 &gt; str2. 
   */
  public abstract int compare (String source, String target);

  /**
   * This method compares the two <code>Object</code>'s and returns an
   * integer indicating whether or not the first argument is less than,
   * equal to, or greater than the second argument.  These two objects
   * must be <code>String</code>'s or an exception will be thrown.
   *
   * @param o1 The first object to compare
   * @param o2 The second object to compare
   *
   * @return A negative integer if obj1 &lt; obj2, 0 if obj1 == obj2, or
   * a positive integer if obj1 &gt; obj2. 
   *
   * @exception ClassCastException If the arguments are not instances
   * of <code>String</code>. 
   */
  public int compare (Object o1, Object o2)
  {
    return compare ((String) o1, (String) o2);
  }

  /**
   * This method tests the specified object for equality against this
   * object.  This will be true if and only if the following conditions are
   * met:
   * <ul>
   * <li>The specified object is not <code>null</code>.</li>
   * <li>The specified object is an instance of <code>Collator</code>.</li>
   * <li>The specified object has the same strength and decomposition
   * settings as this object.</li>
   * </ul>
   *
   * @param obj The <code>Object</code> to test for equality against
   *            this object. 
   *
   * @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 Collator))
      return false;
    Collator c = (Collator) obj;
    return decmp == c.decmp && strength == c.strength;
  }

  /**
   * This method tests whether the specified <code>String</code>'s are equal
   * according to the collation rules for the locale of this object and
   * the current strength and decomposition settings.
   *
   * @param source The first <code>String</code> to compare
   * @param target The second <code>String</code> to compare
   *
   * @return <code>true</code> if the two strings are equal,
   * <code>false</code> otherwise. 
   */
  public boolean equals (String source, String target)
  {
    return compare (source, target) == 0;
  }

  /**
   * This method returns a copy of this <code>Collator</code> object.
   *
   * @return A duplicate of this object.
   */
  public Object clone ()
  {
    try
      {
	return super.clone ();
      }
    catch (CloneNotSupportedException _)
      {
	return null;
      }
  }

  /**
   * This method returns an array of <code>Locale</code> objects which is
   * the list of locales for which <code>Collator</code> objects exist.
   *
   * @return The list of locales for which <code>Collator</code>'s exist.
   */
  public static synchronized Locale[] getAvailableLocales ()
  {
    return LocaleHelper.getCollatorLocales();
  }

  /**
   * This method transforms the specified <code>String</code> into a
   * <code>CollationKey</code> for faster comparisons.  This is useful when
   * comparisons against a string might be performed multiple times, such
   * as during a sort operation.
   *
   * @param source The <code>String</code> to convert.
   *
   * @return A <code>CollationKey</code> for the specified <code>String</code>.
   */
  public abstract CollationKey getCollationKey (String source);

  /**
   * This method returns the current decomposition setting for this
   * object.  This * will be one of NO_DECOMPOSITION,
   * CANONICAL_DECOMPOSITION, or * FULL_DECOMPOSITION.  See the
   * documentation for those constants for an * explanation of this
   * setting.
   *
   * @return The current decomposition setting.
   */
  public synchronized int getDecomposition ()
  {
    return decmp;
  }

  /**
   * This method returns an instance of <code>Collator</code> for the
   * default locale.
   *
   * @return A <code>Collator</code> for the default locale.
   */
  public static Collator getInstance ()
  {
    return getInstance (Locale.getDefault());
  }

  /**
   * This method returns an instance of <code>Collator</code> for the
   * specified locale.  If no <code>Collator</code> exists for the desired
   * locale, a <code>Collator</code> for the default locale will be returned.
   *
   * @param loc The desired locale to load a <code>Collator</code> for.
   *
   * @return A <code>Collator</code> for the requested locale
   */
  public static Collator getInstance (Locale loc)
  {
    ResourceBundle res;
    String pattern;
    try
      {
	res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
				       loc, ClassLoader.getSystemClassLoader());
	pattern = res.getString("collation_rules");
      }
    catch (MissingResourceException x)
      {
	pattern = "<0<1<2<3<4<5<6<7<8<9<A,a<b,B<c,C<d,D<e,E<f,F<g,G<h,H<i,I<j,J<k,K" +
		"<l,L<m,M<n,N<o,O<p,P<q,Q<r,R<s,S<t,T<u,U<v,V<w,W<x,X<y,Y<z,Z";
      }
    try
      {
	return new RuleBasedCollator (pattern);
      }
    catch (ParseException x)
      {
	throw (InternalError)new InternalError().initCause(x);
      }
  }

  /**
   * This method returns the current strength setting for this object.  This
   * will be one of PRIMARY, SECONDARY, TERTIARY, or IDENTICAL.  See the
   * documentation for those constants for an explanation of this setting.
   *
   * @return The current strength setting.
   */
  public synchronized int getStrength ()
  {
    return strength;
  }

  /**
   * This method returns a hash code value for this object.
   *
   * @return A hash value for this object.
   */
  public abstract int hashCode ();

  /**
   * This method sets the decomposition setting for this object to the
   * specified value.  This must be one of NO_DECOMPOSITION,
   * CANONICAL_DECOMPOSITION, or FULL_DECOMPOSITION.  Otherwise an
   * exception will be thrown.  See the documentation for those
   * contants for an explanation of this setting.
   *
   * @param mode The new decomposition setting.
   *
   * @exception IllegalArgumentException If the requested
   * decomposition setting is not valid.
   */
  public synchronized void setDecomposition (int mode)
  {
    if (mode != NO_DECOMPOSITION
	&& mode != CANONICAL_DECOMPOSITION
	&& mode != FULL_DECOMPOSITION)
      throw new IllegalArgumentException ();
    decmp = mode;
  }

  /**
   * This method sets the strength setting for this object to the specified
   * value.  This must be one of PRIMARY, SECONDARY, TERTIARY, or IDENTICAL.
   * Otherwise an exception is thrown. See the documentation for these
   * constants for an explanation of this setting.
   * 
   * @param strength The new strength setting.
   *
   * @exception IllegalArgumentException If the requested strength
   * setting value is not valid.
   */
  public synchronized void setStrength (int strength)
  {
    if (strength != PRIMARY && strength != SECONDARY
	&& strength != TERTIARY && strength != IDENTICAL)
      throw new IllegalArgumentException ();
    this.strength = strength;
  }

  // Decompose a single character and append results to the buffer.
  // FIXME: for libgcj this is a native method which handles
  // decomposition.  For Classpath, for now, it does nothing.
  final void decomposeCharacter (char c, StringBuffer buf)
  {
    buf.append (c);
  }

  /**
   * This is the current collation decomposition setting.
   */
  int decmp;

  /**
   * This is the current collation strength setting.
   */
  int strength;
}
