001/* Collator.java -- Perform locale dependent String comparisons. 002 Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc. 003 004This file is part of GNU Classpath. 005 006GNU Classpath is free software; you can redistribute it and/or modify 007it under the terms of the GNU General Public License as published by 008the Free Software Foundation; either version 2, or (at your option) 009any later version. 010 011GNU Classpath is distributed in the hope that it will be useful, but 012WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014General Public License for more details. 015 016You should have received a copy of the GNU General Public License 017along with GNU Classpath; see the file COPYING. If not, write to the 018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 01902110-1301 USA. 020 021Linking this library statically or dynamically with other modules is 022making a combined work based on this library. Thus, the terms and 023conditions of the GNU General Public License cover the whole 024combination. 025 026As a special exception, the copyright holders of this library give you 027permission to link this library with independent modules to produce an 028executable, regardless of the license terms of these independent 029modules, and to copy and distribute the resulting executable under 030terms of your choice, provided that you also meet, for each linked 031independent module, the terms and conditions of the license of that 032module. An independent module is a module which is not derived from 033or based on this library. If you modify this library, you may extend 034this exception to your version of the library, but you are not 035obligated to do so. If you do not wish to do so, delete this 036exception statement from your version. */ 037 038 039package java.text; 040 041import gnu.java.locale.LocaleHelper; 042 043import java.text.spi.CollatorProvider; 044 045import java.util.Comparator; 046import java.util.Locale; 047import java.util.MissingResourceException; 048import java.util.ResourceBundle; 049import java.util.ServiceLoader; 050 051/** 052 * This class is the abstract superclass of classes which perform 053 * locale dependent <code>String</code> comparisons. A caller requests 054 * an instance of <code>Collator</code> for a particular locale using 055 * the <code>getInstance()</code> static method in this class. That method 056 * will return a locale specific subclass of <code>Collator</code> which 057 * can be used to perform <code>String</code> comparisons for that locale. 058 * If a subclass of <code>Collator</code> cannot be located for a particular 059 * locale, a default instance for the current locale will be returned. 060 * 061 * In addition to setting the correct locale, there are two additional 062 * settings that can be adjusted to affect <code>String</code> comparisons: 063 * strength and decomposition. The strength value determines the level 064 * of signficance of character differences required for them to sort 065 * differently. (For example, whether or not capital letters are considered 066 * different from lower case letters). The decomposition value affects how 067 * variants of the same character are treated for sorting purposes. (For 068 * example, whether or not an accent is signficant or not). These settings 069 * are described in detail in the documentation for the methods and values 070 * that are related to them. 071 * 072 * @author Tom Tromey (tromey@cygnus.com) 073 * @author Aaron M. Renn (arenn@urbanophile.com) 074 * @date March 18, 1999 075 */ 076public abstract class Collator implements Comparator<Object>, Cloneable 077{ 078 /** 079 * This constant is a strength value which indicates that only primary 080 * differences between characters will be considered signficant. As an 081 * example, two completely different English letters such as 'a' and 'b' 082 * are considered to have a primary difference. 083 */ 084 public static final int PRIMARY = 0; 085 086 /** 087 * This constant is a strength value which indicates that only secondary 088 * or primary differences between characters will be considered 089 * significant. An example of a secondary difference between characters 090 * are instances of the same letter with different accented forms. 091 */ 092 public static final int SECONDARY = 1; 093 094 /** 095 * This constant is a strength value which indicates that tertiary, 096 * secondary, and primary differences will be considered during sorting. 097 * An example of a tertiary difference is capitalization of a given letter. 098 * This is the default value for the strength setting. 099 */ 100 public static final int TERTIARY = 2; 101 102 /** 103 * This constant is a strength value which indicates that any difference 104 * at all between character values are considered significant. 105 */ 106 public static final int IDENTICAL = 3; 107 108 /** 109 * This constant indicates that accented characters won't be decomposed 110 * when performing comparisons. This will yield the fastest results, but 111 * will only work correctly in call cases for languages which do not 112 * use accents such as English. 113 */ 114 public static final int NO_DECOMPOSITION = 0; 115 116 /** 117 * This constant indicates that only characters which are canonical variants 118 * in Unicode 2.0 will be decomposed prior to performing comparisons. This 119 * will cause accented languages to be sorted correctly. This is the 120 * default decomposition value. 121 */ 122 public static final int CANONICAL_DECOMPOSITION = 1; 123 124 /** 125 * This constant indicates that both canonical variants and compatibility 126 * variants in Unicode 2.0 will be decomposed prior to performing 127 * comparisons. This is the slowest mode, but is required to get the 128 * correct sorting for certain languages with certain special formats. 129 */ 130 public static final int FULL_DECOMPOSITION = 2; 131 132 /** 133 * This method initializes a new instance of <code>Collator</code> to have 134 * the default strength (TERTIARY) and decomposition 135 * (CANONICAL_DECOMPOSITION) settings. This constructor is protected and 136 * is for use by subclasses only. Non-subclass callers should use the 137 * static <code>getInstance()</code> methods of this class to instantiate 138 * <code>Collation</code> objects for the desired locale. 139 */ 140 protected Collator () 141 { 142 strength = TERTIARY; 143 decmp = CANONICAL_DECOMPOSITION; 144 } 145 146 /** 147 * This method compares the two <code>String</code>'s and returns an 148 * integer indicating whether or not the first argument is less than, 149 * equal to, or greater than the second argument. The comparison is 150 * performed according to the rules of the locale for this 151 * <code>Collator</code> and the strength and decomposition rules in 152 * effect. 153 * 154 * @param source The first object to compare 155 * @param target The second object to compare 156 * 157 * @return A negative integer if str1 < str2, 0 if str1 == str2, or 158 * a positive integer if str1 > str2. 159 */ 160 public abstract int compare (String source, String target); 161 162 /** 163 * This method compares the two <code>Object</code>'s and returns an 164 * integer indicating whether or not the first argument is less than, 165 * equal to, or greater than the second argument. These two objects 166 * must be <code>String</code>'s or an exception will be thrown. 167 * 168 * @param o1 The first object to compare 169 * @param o2 The second object to compare 170 * 171 * @return A negative integer if obj1 < obj2, 0 if obj1 == obj2, or 172 * a positive integer if obj1 > obj2. 173 * 174 * @exception ClassCastException If the arguments are not instances 175 * of <code>String</code>. 176 */ 177 public int compare (Object o1, Object o2) 178 { 179 return compare ((String) o1, (String) o2); 180 } 181 182 /** 183 * This method tests the specified object for equality against this 184 * object. This will be true if and only if the following conditions are 185 * met: 186 * <ul> 187 * <li>The specified object is not <code>null</code>.</li> 188 * <li>The specified object is an instance of <code>Collator</code>.</li> 189 * <li>The specified object has the same strength and decomposition 190 * settings as this object.</li> 191 * </ul> 192 * 193 * @param obj The <code>Object</code> to test for equality against 194 * this object. 195 * 196 * @return <code>true</code> if the specified object is equal to 197 * this one, <code>false</code> otherwise. 198 */ 199 public boolean equals (Object obj) 200 { 201 if (! (obj instanceof Collator)) 202 return false; 203 Collator c = (Collator) obj; 204 return decmp == c.decmp && strength == c.strength; 205 } 206 207 /** 208 * This method tests whether the specified <code>String</code>'s are equal 209 * according to the collation rules for the locale of this object and 210 * the current strength and decomposition settings. 211 * 212 * @param source The first <code>String</code> to compare 213 * @param target The second <code>String</code> to compare 214 * 215 * @return <code>true</code> if the two strings are equal, 216 * <code>false</code> otherwise. 217 */ 218 public boolean equals (String source, String target) 219 { 220 return compare (source, target) == 0; 221 } 222 223 /** 224 * This method returns a copy of this <code>Collator</code> object. 225 * 226 * @return A duplicate of this object. 227 */ 228 public Object clone () 229 { 230 try 231 { 232 return super.clone (); 233 } 234 catch (CloneNotSupportedException _) 235 { 236 return null; 237 } 238 } 239 240 /** 241 * This method returns an array of <code>Locale</code> objects which is 242 * the list of locales for which <code>Collator</code> objects exist. 243 * 244 * @return The list of locales for which <code>Collator</code>'s exist. 245 */ 246 public static synchronized Locale[] getAvailableLocales () 247 { 248 return LocaleHelper.getCollatorLocales(); 249 } 250 251 /** 252 * This method transforms the specified <code>String</code> into a 253 * <code>CollationKey</code> for faster comparisons. This is useful when 254 * comparisons against a string might be performed multiple times, such 255 * as during a sort operation. 256 * 257 * @param source The <code>String</code> to convert. 258 * 259 * @return A <code>CollationKey</code> for the specified <code>String</code>. 260 */ 261 public abstract CollationKey getCollationKey (String source); 262 263 /** 264 * This method returns the current decomposition setting for this 265 * object. This * will be one of NO_DECOMPOSITION, 266 * CANONICAL_DECOMPOSITION, or * FULL_DECOMPOSITION. See the 267 * documentation for those constants for an * explanation of this 268 * setting. 269 * 270 * @return The current decomposition setting. 271 */ 272 public synchronized int getDecomposition () 273 { 274 return decmp; 275 } 276 277 /** 278 * This method returns an instance of <code>Collator</code> for the 279 * default locale. 280 * 281 * @return A <code>Collator</code> for the default locale. 282 */ 283 public static Collator getInstance () 284 { 285 return getInstance (Locale.getDefault()); 286 } 287 288 /** 289 * This method returns an instance of <code>Collator</code> for the 290 * specified locale. If no <code>Collator</code> exists for the desired 291 * locale, the fallback procedure described in 292 * {@link java.util.spi.LocaleServiceProvider} is invoked. 293 * 294 * @param loc The desired locale to load a <code>Collator</code> for. 295 * 296 * @return A <code>Collator</code> for the requested locale 297 */ 298 public static Collator getInstance (Locale loc) 299 { 300 String pattern; 301 try 302 { 303 ResourceBundle res = 304 ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", 305 loc, ClassLoader.getSystemClassLoader()); 306 return new RuleBasedCollator(res.getString("collation_rules")); 307 } 308 catch (MissingResourceException x) 309 { 310 /* This means runtime support for the locale 311 * is not available, so we check providers. */ 312 } 313 catch (ParseException x) 314 { 315 throw (InternalError)new InternalError().initCause(x); 316 } 317 for (CollatorProvider p : ServiceLoader.load(CollatorProvider.class)) 318 { 319 for (Locale l : p.getAvailableLocales()) 320 { 321 if (l.equals(loc)) 322 { 323 Collator c = p.getInstance(loc); 324 if (c != null) 325 return c; 326 break; 327 } 328 } 329 } 330 if (loc.equals(Locale.ROOT)) 331 { 332 try 333 { 334 return new RuleBasedCollator("<0<1<2<3<4<5<6<7<8<9<A,a<b,B<c," + 335 "C<d,D<e,E<f,F<g,G<h,H<i,I<j,J<k,K" + 336 "<l,L<m,M<n,N<o,O<p,P<q,Q<r,R<s,S<t,"+ 337 "T<u,U<v,V<w,W<x,X<y,Y<z,Z"); 338 } 339 catch (ParseException x) 340 { 341 throw (InternalError)new InternalError().initCause(x); 342 } 343 } 344 return getInstance(LocaleHelper.getFallbackLocale(loc)); 345 } 346 347 /** 348 * This method returns the current strength setting for this object. This 349 * will be one of PRIMARY, SECONDARY, TERTIARY, or IDENTICAL. See the 350 * documentation for those constants for an explanation of this setting. 351 * 352 * @return The current strength setting. 353 */ 354 public synchronized int getStrength () 355 { 356 return strength; 357 } 358 359 /** 360 * This method returns a hash code value for this object. 361 * 362 * @return A hash value for this object. 363 */ 364 public abstract int hashCode (); 365 366 /** 367 * This method sets the decomposition setting for this object to the 368 * specified value. This must be one of NO_DECOMPOSITION, 369 * CANONICAL_DECOMPOSITION, or FULL_DECOMPOSITION. Otherwise an 370 * exception will be thrown. See the documentation for those 371 * contants for an explanation of this setting. 372 * 373 * @param mode The new decomposition setting. 374 * 375 * @exception IllegalArgumentException If the requested 376 * decomposition setting is not valid. 377 */ 378 public synchronized void setDecomposition (int mode) 379 { 380 if (mode != NO_DECOMPOSITION 381 && mode != CANONICAL_DECOMPOSITION 382 && mode != FULL_DECOMPOSITION) 383 throw new IllegalArgumentException (); 384 decmp = mode; 385 } 386 387 /** 388 * This method sets the strength setting for this object to the specified 389 * value. This must be one of PRIMARY, SECONDARY, TERTIARY, or IDENTICAL. 390 * Otherwise an exception is thrown. See the documentation for these 391 * constants for an explanation of this setting. 392 * 393 * @param strength The new strength setting. 394 * 395 * @exception IllegalArgumentException If the requested strength 396 * setting value is not valid. 397 */ 398 public synchronized void setStrength (int strength) 399 { 400 if (strength != PRIMARY && strength != SECONDARY 401 && strength != TERTIARY && strength != IDENTICAL) 402 throw new IllegalArgumentException (); 403 this.strength = strength; 404 } 405 406 // Decompose a single character and append results to the buffer. 407 // FIXME: for libgcj this is a native method which handles 408 // decomposition. For Classpath, for now, it does nothing. 409 /* 410 final void decomposeCharacter (char c, StringBuffer buf) 411 { 412 buf.append (c); 413 } 414 */ 415 416 /** 417 * This is the current collation decomposition setting. 418 */ 419 int decmp; 420 421 /** 422 * This is the current collation strength setting. 423 */ 424 int strength; 425}