0N/A/*
2362N/A * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * (C) Copyright Taligent, Inc. 1996-1998 - All Rights Reserved
0N/A * (C) Copyright IBM Corp. 1996-1998 - All Rights Reserved
0N/A *
0N/A * The original version of this source code and documentation is copyrighted
0N/A * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
0N/A * materials are provided under terms of a License Agreement between Taligent
0N/A * and Sun. This technology is protected by multiple US and International
0N/A * patents. This notice and attribution to Taligent may not be removed.
0N/A * Taligent is a registered trademark of Taligent, Inc.
0N/A *
0N/A */
0N/A
0N/Apackage java.text;
0N/A
0N/Aimport java.text.spi.CollatorProvider;
0N/Aimport java.util.Locale;
0N/Aimport java.util.MissingResourceException;
0N/Aimport java.util.ResourceBundle;
0N/Aimport java.util.spi.LocaleServiceProvider;
0N/Aimport sun.misc.SoftCache;
0N/Aimport sun.util.resources.LocaleData;
0N/Aimport sun.util.LocaleServiceProviderPool;
0N/A
0N/A
0N/A/**
0N/A * The <code>Collator</code> class performs locale-sensitive
0N/A * <code>String</code> comparison. You use this class to build
0N/A * searching and sorting routines for natural language text.
0N/A *
0N/A * <p>
0N/A * <code>Collator</code> is an abstract base class. Subclasses
0N/A * implement specific collation strategies. One subclass,
0N/A * <code>RuleBasedCollator</code>, is currently provided with
0N/A * the Java Platform and is applicable to a wide set of languages. Other
0N/A * subclasses may be created to handle more specialized needs.
0N/A *
0N/A * <p>
0N/A * Like other locale-sensitive classes, you can use the static
0N/A * factory method, <code>getInstance</code>, to obtain the appropriate
0N/A * <code>Collator</code> object for a given locale. You will only need
0N/A * to look at the subclasses of <code>Collator</code> if you need
0N/A * to understand the details of a particular collation strategy or
0N/A * if you need to modify that strategy.
0N/A *
0N/A * <p>
0N/A * The following example shows how to compare two strings using
0N/A * the <code>Collator</code> for the default locale.
0N/A * <blockquote>
0N/A * <pre>
0N/A * // Compare two strings in the default locale
0N/A * Collator myCollator = Collator.getInstance();
0N/A * if( myCollator.compare("abc", "ABC") < 0 )
0N/A * System.out.println("abc is less than ABC");
0N/A * else
0N/A * System.out.println("abc is greater than or equal to ABC");
0N/A * </pre>
0N/A * </blockquote>
0N/A *
0N/A * <p>
0N/A * You can set a <code>Collator</code>'s <em>strength</em> property
0N/A * to determine the level of difference considered significant in
0N/A * comparisons. Four strengths are provided: <code>PRIMARY</code>,
0N/A * <code>SECONDARY</code>, <code>TERTIARY</code>, and <code>IDENTICAL</code>.
0N/A * The exact assignment of strengths to language features is
0N/A * locale dependant. For example, in Czech, "e" and "f" are considered
0N/A * primary differences, while "e" and "&#283;" are secondary differences,
0N/A * "e" and "E" are tertiary differences and "e" and "e" are identical.
0N/A * The following shows how both case and accents could be ignored for
0N/A * US English.
0N/A * <blockquote>
0N/A * <pre>
0N/A * //Get the Collator for US English and set its strength to PRIMARY
0N/A * Collator usCollator = Collator.getInstance(Locale.US);
0N/A * usCollator.setStrength(Collator.PRIMARY);
0N/A * if( usCollator.compare("abc", "ABC") == 0 ) {
0N/A * System.out.println("Strings are equivalent");
0N/A * }
0N/A * </pre>
0N/A * </blockquote>
0N/A * <p>
0N/A * For comparing <code>String</code>s exactly once, the <code>compare</code>
0N/A * method provides the best performance. When sorting a list of
0N/A * <code>String</code>s however, it is generally necessary to compare each
0N/A * <code>String</code> multiple times. In this case, <code>CollationKey</code>s
0N/A * provide better performance. The <code>CollationKey</code> class converts
0N/A * a <code>String</code> to a series of bits that can be compared bitwise
0N/A * against other <code>CollationKey</code>s. A <code>CollationKey</code> is
0N/A * created by a <code>Collator</code> object for a given <code>String</code>.
0N/A * <br>
0N/A * <strong>Note:</strong> <code>CollationKey</code>s from different
0N/A * <code>Collator</code>s can not be compared. See the class description
0N/A * for {@link CollationKey}
0N/A * for an example using <code>CollationKey</code>s.
0N/A *
0N/A * @see RuleBasedCollator
0N/A * @see CollationKey
0N/A * @see CollationElementIterator
0N/A * @see Locale
0N/A * @author Helena Shih, Laura Werner, Richard Gillam
0N/A */
0N/A
0N/Apublic abstract class Collator
0N/A implements java.util.Comparator<Object>, Cloneable
0N/A{
0N/A /**
0N/A * Collator strength value. When set, only PRIMARY differences are
0N/A * considered significant during comparison. The assignment of strengths
0N/A * to language features is locale dependant. A common example is for
0N/A * different base letters ("a" vs "b") to be considered a PRIMARY difference.
0N/A * @see java.text.Collator#setStrength
0N/A * @see java.text.Collator#getStrength
0N/A */
0N/A public final static int PRIMARY = 0;
0N/A /**
0N/A * Collator strength value. When set, only SECONDARY and above differences are
0N/A * considered significant during comparison. The assignment of strengths
0N/A * to language features is locale dependant. A common example is for
0N/A * different accented forms of the same base letter ("a" vs "\u00E4") to be
0N/A * considered a SECONDARY difference.
0N/A * @see java.text.Collator#setStrength
0N/A * @see java.text.Collator#getStrength
0N/A */
0N/A public final static int SECONDARY = 1;
0N/A /**
0N/A * Collator strength value. When set, only TERTIARY and above differences are
0N/A * considered significant during comparison. The assignment of strengths
0N/A * to language features is locale dependant. A common example is for
0N/A * case differences ("a" vs "A") to be considered a TERTIARY difference.
0N/A * @see java.text.Collator#setStrength
0N/A * @see java.text.Collator#getStrength
0N/A */
0N/A public final static int TERTIARY = 2;
0N/A
0N/A /**
0N/A * Collator strength value. When set, all differences are
0N/A * considered significant during comparison. The assignment of strengths
0N/A * to language features is locale dependant. A common example is for control
0N/A * characters ("&#092;u0001" vs "&#092;u0002") to be considered equal at the
0N/A * PRIMARY, SECONDARY, and TERTIARY levels but different at the IDENTICAL
0N/A * level. Additionally, differences between pre-composed accents such as
0N/A * "&#092;u00C0" (A-grave) and combining accents such as "A&#092;u0300"
0N/A * (A, combining-grave) will be considered significant at the IDENTICAL
0N/A * level if decomposition is set to NO_DECOMPOSITION.
0N/A */
0N/A public final static int IDENTICAL = 3;
0N/A
0N/A /**
0N/A * Decomposition mode value. With NO_DECOMPOSITION
0N/A * set, accented characters will not be decomposed for collation. This
0N/A * is the default setting and provides the fastest collation but
0N/A * will only produce correct results for languages that do not use accents.
0N/A * @see java.text.Collator#getDecomposition
0N/A * @see java.text.Collator#setDecomposition
0N/A */
0N/A public final static int NO_DECOMPOSITION = 0;
0N/A
0N/A /**
0N/A * Decomposition mode value. With CANONICAL_DECOMPOSITION
0N/A * set, characters that are canonical variants according to Unicode
0N/A * standard will be decomposed for collation. This should be used to get
0N/A * correct collation of accented characters.
0N/A * <p>
0N/A * CANONICAL_DECOMPOSITION corresponds to Normalization Form D as
0N/A * described in
0N/A * <a href="http://www.unicode.org/unicode/reports/tr15/tr15-23.html">Unicode
0N/A * Technical Report #15</a>.
0N/A * @see java.text.Collator#getDecomposition
0N/A * @see java.text.Collator#setDecomposition
0N/A */
0N/A public final static int CANONICAL_DECOMPOSITION = 1;
0N/A
0N/A /**
0N/A * Decomposition mode value. With FULL_DECOMPOSITION
0N/A * set, both Unicode canonical variants and Unicode compatibility variants
0N/A * will be decomposed for collation. This causes not only accented
0N/A * characters to be collated, but also characters that have special formats
0N/A * to be collated with their norminal form. For example, the half-width and
0N/A * full-width ASCII and Katakana characters are then collated together.
0N/A * FULL_DECOMPOSITION is the most complete and therefore the slowest
0N/A * decomposition mode.
0N/A * <p>
0N/A * FULL_DECOMPOSITION corresponds to Normalization Form KD as
0N/A * described in
0N/A * <a href="http://www.unicode.org/unicode/reports/tr15/tr15-23.html">Unicode
0N/A * Technical Report #15</a>.
0N/A * @see java.text.Collator#getDecomposition
0N/A * @see java.text.Collator#setDecomposition
0N/A */
0N/A public final static int FULL_DECOMPOSITION = 2;
0N/A
0N/A /**
0N/A * Gets the Collator for the current default locale.
0N/A * The default locale is determined by java.util.Locale.getDefault.
0N/A * @return the Collator for the default locale.(for example, en_US)
0N/A * @see java.util.Locale#getDefault
0N/A */
0N/A public static synchronized Collator getInstance() {
0N/A return getInstance(Locale.getDefault());
0N/A }
0N/A
0N/A /**
0N/A * Gets the Collator for the desired locale.
0N/A * @param desiredLocale the desired locale.
0N/A * @return the Collator for the desired locale.
0N/A * @see java.util.Locale
0N/A * @see java.util.ResourceBundle
0N/A */
0N/A public static synchronized
0N/A Collator getInstance(Locale desiredLocale)
0N/A {
0N/A Collator result = (Collator) cache.get(desiredLocale);
0N/A if (result != null) {
0N/A return (Collator)result.clone(); // make the world safe
0N/A }
0N/A
0N/A // Check whether a provider can provide an implementation that's closer
0N/A // to the requested locale than what the Java runtime itself can provide.
0N/A LocaleServiceProviderPool pool =
0N/A LocaleServiceProviderPool.getPool(CollatorProvider.class);
0N/A if (pool.hasProviders()) {
0N/A Collator providersInstance = pool.getLocalizedObject(
0N/A CollatorGetter.INSTANCE,
0N/A desiredLocale,
0N/A desiredLocale);
0N/A if (providersInstance != null) {
0N/A return providersInstance;
0N/A }
0N/A }
0N/A
0N/A // Load the resource of the desired locale from resource
0N/A // manager.
0N/A String colString = "";
0N/A try {
0N/A ResourceBundle resource = LocaleData.getCollationData(desiredLocale);
0N/A
0N/A colString = resource.getString("Rule");
0N/A } catch (MissingResourceException e) {
0N/A // Use default values
0N/A }
0N/A try
0N/A {
0N/A result = new RuleBasedCollator( CollationRules.DEFAULTRULES +
0N/A colString,
0N/A CANONICAL_DECOMPOSITION );
0N/A }
0N/A catch(ParseException foo)
0N/A {
0N/A // predefined tables should contain correct grammar
0N/A try {
0N/A result = new RuleBasedCollator( CollationRules.DEFAULTRULES );
0N/A } catch (ParseException bar) {
0N/A // do nothing
0N/A }
0N/A }
0N/A // Now that RuleBasedCollator adds expansions for pre-composed characters
0N/A // into their decomposed equivalents, the default collators don't need
0N/A // to have decomposition turned on. Laura, 5/5/98, bug 4114077
0N/A result.setDecomposition(NO_DECOMPOSITION);
0N/A
0N/A cache.put(desiredLocale,result);
0N/A return (Collator)result.clone();
0N/A }
0N/A
0N/A /**
0N/A * Compares the source string to the target string according to the
0N/A * collation rules for this Collator. Returns an integer less than,
0N/A * equal to or greater than zero depending on whether the source String is
0N/A * less than, equal to or greater than the target string. See the Collator
0N/A * class description for an example of use.
0N/A * <p>
0N/A * For a one time comparison, this method has the best performance. If a
0N/A * given String will be involved in multiple comparisons, CollationKey.compareTo
0N/A * has the best performance. See the Collator class description for an example
0N/A * using CollationKeys.
0N/A * @param source the source string.
0N/A * @param target the target string.
0N/A * @return Returns an integer value. Value is less than zero if source is less than
0N/A * target, value is zero if source and target are equal, value is greater than zero
0N/A * if source is greater than target.
0N/A * @see java.text.CollationKey
0N/A * @see java.text.Collator#getCollationKey
0N/A */
0N/A public abstract int compare(String source, String target);
0N/A
0N/A /**
0N/A * Compares its two arguments for order. Returns a negative integer,
0N/A * zero, or a positive integer as the first argument is less than, equal
0N/A * to, or greater than the second.
0N/A * <p>
0N/A * This implementation merely returns
0N/A * <code> compare((String)o1, (String)o2) </code>.
0N/A *
0N/A * @return a negative integer, zero, or a positive integer as the
0N/A * first argument is less than, equal to, or greater than the
0N/A * second.
0N/A * @exception ClassCastException the arguments cannot be cast to Strings.
0N/A * @see java.util.Comparator
0N/A * @since 1.2
0N/A */
0N/A public int compare(Object o1, Object o2) {
0N/A return compare((String)o1, (String)o2);
0N/A }
0N/A
0N/A /**
0N/A * Transforms the String into a series of bits that can be compared bitwise
0N/A * to other CollationKeys. CollationKeys provide better performance than
0N/A * Collator.compare when Strings are involved in multiple comparisons.
0N/A * See the Collator class description for an example using CollationKeys.
0N/A * @param source the string to be transformed into a collation key.
0N/A * @return the CollationKey for the given String based on this Collator's collation
0N/A * rules. If the source String is null, a null CollationKey is returned.
0N/A * @see java.text.CollationKey
0N/A * @see java.text.Collator#compare
0N/A */
0N/A public abstract CollationKey getCollationKey(String source);
0N/A
0N/A /**
0N/A * Convenience method for comparing the equality of two strings based on
0N/A * this Collator's collation rules.
0N/A * @param source the source string to be compared with.
0N/A * @param target the target string to be compared with.
0N/A * @return true if the strings are equal according to the collation
0N/A * rules. false, otherwise.
0N/A * @see java.text.Collator#compare
0N/A */
0N/A public boolean equals(String source, String target)
0N/A {
0N/A return (compare(source, target) == Collator.EQUAL);
0N/A }
0N/A
0N/A /**
0N/A * Returns this Collator's strength property. The strength property determines
0N/A * the minimum level of difference considered significant during comparison.
0N/A * See the Collator class description for an example of use.
0N/A * @return this Collator's current strength property.
0N/A * @see java.text.Collator#setStrength
0N/A * @see java.text.Collator#PRIMARY
0N/A * @see java.text.Collator#SECONDARY
0N/A * @see java.text.Collator#TERTIARY
0N/A * @see java.text.Collator#IDENTICAL
0N/A */
0N/A public synchronized int getStrength()
0N/A {
0N/A return strength;
0N/A }
0N/A
0N/A /**
0N/A * Sets this Collator's strength property. The strength property determines
0N/A * the minimum level of difference considered significant during comparison.
0N/A * See the Collator class description for an example of use.
0N/A * @param newStrength the new strength value.
0N/A * @see java.text.Collator#getStrength
0N/A * @see java.text.Collator#PRIMARY
0N/A * @see java.text.Collator#SECONDARY
0N/A * @see java.text.Collator#TERTIARY
0N/A * @see java.text.Collator#IDENTICAL
0N/A * @exception IllegalArgumentException If the new strength value is not one of
0N/A * PRIMARY, SECONDARY, TERTIARY or IDENTICAL.
0N/A */
0N/A public synchronized void setStrength(int newStrength) {
0N/A if ((newStrength != PRIMARY) &&
0N/A (newStrength != SECONDARY) &&
0N/A (newStrength != TERTIARY) &&
0N/A (newStrength != IDENTICAL))
0N/A throw new IllegalArgumentException("Incorrect comparison level.");
0N/A strength = newStrength;
0N/A }
0N/A
0N/A /**
0N/A * Get the decomposition mode of this Collator. Decomposition mode
0N/A * determines how Unicode composed characters are handled. Adjusting
0N/A * decomposition mode allows the user to select between faster and more
0N/A * complete collation behavior.
0N/A * <p>The three values for decomposition mode are:
0N/A * <UL>
0N/A * <LI>NO_DECOMPOSITION,
0N/A * <LI>CANONICAL_DECOMPOSITION
0N/A * <LI>FULL_DECOMPOSITION.
0N/A * </UL>
0N/A * See the documentation for these three constants for a description
0N/A * of their meaning.
0N/A * @return the decomposition mode
0N/A * @see java.text.Collator#setDecomposition
0N/A * @see java.text.Collator#NO_DECOMPOSITION
0N/A * @see java.text.Collator#CANONICAL_DECOMPOSITION
0N/A * @see java.text.Collator#FULL_DECOMPOSITION
0N/A */
0N/A public synchronized int getDecomposition()
0N/A {
0N/A return decmp;
0N/A }
0N/A /**
0N/A * Set the decomposition mode of this Collator. See getDecomposition
0N/A * for a description of decomposition mode.
0N/A * @param decompositionMode the new decomposition mode.
0N/A * @see java.text.Collator#getDecomposition
0N/A * @see java.text.Collator#NO_DECOMPOSITION
0N/A * @see java.text.Collator#CANONICAL_DECOMPOSITION
0N/A * @see java.text.Collator#FULL_DECOMPOSITION
0N/A * @exception IllegalArgumentException If the given value is not a valid decomposition
0N/A * mode.
0N/A */
0N/A public synchronized void setDecomposition(int decompositionMode) {
0N/A if ((decompositionMode != NO_DECOMPOSITION) &&
0N/A (decompositionMode != CANONICAL_DECOMPOSITION) &&
0N/A (decompositionMode != FULL_DECOMPOSITION))
0N/A throw new IllegalArgumentException("Wrong decomposition mode.");
0N/A decmp = decompositionMode;
0N/A }
0N/A
0N/A /**
0N/A * Returns an array of all locales for which the
0N/A * <code>getInstance</code> methods of this class can return
0N/A * localized instances.
0N/A * The returned array represents the union of locales supported
0N/A * by the Java runtime and by installed
0N/A * {@link java.text.spi.CollatorProvider CollatorProvider} implementations.
0N/A * It must contain at least a Locale instance equal to
0N/A * {@link java.util.Locale#US Locale.US}.
0N/A *
0N/A * @return An array of locales for which localized
0N/A * <code>Collator</code> instances are available.
0N/A */
0N/A public static synchronized Locale[] getAvailableLocales() {
0N/A LocaleServiceProviderPool pool =
0N/A LocaleServiceProviderPool.getPool(CollatorProvider.class);
0N/A return pool.getAvailableLocales();
0N/A }
0N/A
0N/A /**
0N/A * Overrides Cloneable
0N/A */
0N/A public Object clone()
0N/A {
0N/A try {
0N/A return (Collator)super.clone();
0N/A } catch (CloneNotSupportedException e) {
0N/A throw new InternalError();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Compares the equality of two Collators.
0N/A * @param that the Collator to be compared with this.
0N/A * @return true if this Collator is the same as that Collator;
0N/A * false otherwise.
0N/A */
0N/A public boolean equals(Object that)
0N/A {
0N/A if (this == that) return true;
0N/A if (that == null) return false;
0N/A if (getClass() != that.getClass()) return false;
0N/A Collator other = (Collator) that;
0N/A return ((strength == other.strength) &&
0N/A (decmp == other.decmp));
0N/A }
0N/A
0N/A /**
0N/A * Generates the hash code for this Collator.
0N/A */
0N/A abstract public int hashCode();
0N/A
0N/A /**
0N/A * Default constructor. This constructor is
0N/A * protected so subclasses can get access to it. Users typically create
0N/A * a Collator sub-class by calling the factory method getInstance.
0N/A * @see java.text.Collator#getInstance
0N/A */
0N/A protected Collator()
0N/A {
0N/A strength = TERTIARY;
0N/A decmp = CANONICAL_DECOMPOSITION;
0N/A }
0N/A
0N/A private int strength = 0;
0N/A private int decmp = 0;
0N/A private static SoftCache cache = new SoftCache();
0N/A
0N/A //
0N/A // FIXME: These three constants should be removed.
0N/A //
0N/A /**
0N/A * LESS is returned if source string is compared to be less than target
0N/A * string in the compare() method.
0N/A * @see java.text.Collator#compare
0N/A */
0N/A final static int LESS = -1;
0N/A /**
0N/A * EQUAL is returned if source string is compared to be equal to target
0N/A * string in the compare() method.
0N/A * @see java.text.Collator#compare
0N/A */
0N/A final static int EQUAL = 0;
0N/A /**
0N/A * GREATER is returned if source string is compared to be greater than
0N/A * target string in the compare() method.
0N/A * @see java.text.Collator#compare
0N/A */
0N/A final static int GREATER = 1;
0N/A
0N/A /**
0N/A * Obtains a Collator instance from a CollatorProvider
0N/A * implementation.
0N/A */
0N/A private static class CollatorGetter
0N/A implements LocaleServiceProviderPool.LocalizedObjectGetter<CollatorProvider, Collator> {
0N/A private static final CollatorGetter INSTANCE = new CollatorGetter();
0N/A
0N/A public Collator getObject(CollatorProvider collatorProvider,
0N/A Locale locale,
0N/A String key,
0N/A Object... params) {
0N/A assert params.length == 1;
0N/A Collator result = collatorProvider.getInstance(locale);
0N/A if (result != null) {
0N/A // put this Collator instance in the cache for two locales, one
0N/A // is for the desired locale, and the other is for the actual
0N/A // locale where the provider is found, which may be a fall back locale.
0N/A cache.put((Locale)params[0], result);
0N/A cache.put(locale, result);
0N/A return (Collator)result.clone();
0N/A }
0N/A
0N/A return null;
0N/A }
0N/A }
0N/A }