1/** 2******************************************************************************* 3* Copyright (C) 1996-2005, International Business Machines Corporation and * 4* others. All Rights Reserved. * 5******************************************************************************* 6* 7* 8******************************************************************************* 9*/ 10 11package com.ibm.icu4jni.text; 12 13import java.util.Locale; 14import java.text.CharacterIterator; 15import java.text.ParseException; 16import com.ibm.icu4jni.common.ErrorCode; 17 18/** 19* Concrete implementation class for Collation. 20* <p> 21* The collation table is composed of a list of collation rules, where each 22* rule is of three forms: 23* <pre> 24* < modifier > 25* < relation > < text-argument > 26* < reset > < text-argument > 27* </pre> 28* <p> 29* <code>RuleBasedCollator</code> has the following restrictions for efficiency 30* (other subclasses may be used for more complex languages) : 31* <ol> 32* <li> If a French secondary ordering is specified it applies to the whole 33* collator object. 34* <li> All non-mentioned Unicode characters are at the end of the collation 35* order. 36* <li> If a character is not located in the RuleBasedCollator, the default 37* Unicode Collation Algorithm (UCA) rulebased table is automatically 38* searched as a backup. 39* </ol> 40* 41* The following demonstrates how to create your own collation rules: 42* <UL Type=disc> 43* <LI><strong>Text-Argument</strong>: A text-argument is any sequence of 44* characters, excluding special characters (that is, common whitespace 45* characters [0009-000D, 0020] and rule syntax characters [0021-002F, 46* 003A-0040, 005B-0060, 007B-007E]). If those characters are desired, 47* you can put them in single quotes (e.g. ampersand => '&'). Note that 48* unquoted white space characters are ignored; e.g. <code>b c</code> is 49* treated as <code>bc</code>. 50* <LI><strong>Modifier</strong>: There is a single modifier which is used 51* to specify that all accents (secondary differences) are backwards. 52* <p>'@' : Indicates that accents are sorted backwards, as in French. 53* <LI><strong>Relation</strong>: The relations are the following: 54* <UL Type=square> 55* <LI>'<' : Greater, as a letter difference (primary) 56* <LI>';' : Greater, as an accent difference (secondary) 57* <LI>',' : Greater, as a case difference (tertiary) 58* <LI>'=' : Equal 59* </UL> 60* <LI><strong>Reset</strong>: There is a single reset which is used 61* primarily for contractions and expansions, but which can also be used 62* to add a modification at the end of a set of rules. 63* <p>'&' : Indicates that the next rule follows the position to where 64* the reset text-argument would be sorted. 65* </UL> 66* 67* <p> 68* This sounds more complicated than it is in practice. For example, the 69* following are equivalent ways of expressing the same thing: 70* <blockquote> 71* <pre> 72* a < b < c 73* a < b & b < c 74* a < c & a < b 75* </pre> 76* </blockquote> 77* Notice that the order is important, as the subsequent item goes immediately 78* after the text-argument. The following are not equivalent: 79* <blockquote> 80* <pre> 81* a < b & a < c 82* a < c & a < b 83* </pre> 84* </blockquote> 85* Either the text-argument must already be present in the sequence, or some 86* initial substring of the text-argument must be present. (e.g. "a < b & ae < 87* e" is valid since "a" is present in the sequence before "ae" is reset). In 88* this latter case, "ae" is not entered and treated as a single character; 89* instead, "e" is sorted as if it were expanded to two characters: "a" 90* followed by an "e". This difference appears in natural languages: in 91* traditional Spanish "ch" is treated as though it contracts to a single 92* character (expressed as "c < ch < d"), while in traditional German a-umlaut 93* is treated as though it expanded to two characters (expressed as "a,A < b,B 94* ... & ae;? & AE;?"). [? and ? are, of course, the escape sequences for 95* a-umlaut.] 96* <p> 97* <strong>Ignorable Characters</strong> 98* <p> 99* For ignorable characters, the first rule must start with a relation (the 100* examples we have used above are really fragments; "a < b" really should be 101* "< a < b"). If, however, the first relation is not "<", then all the all 102* text-arguments up to the first "<" are ignorable. For example, ", - < a < b" 103* makes "-" an ignorable character, as we saw earlier in the word 104* "black-birds". In the samples for different languages, you see that most 105* accents are ignorable. 106* 107* <p><strong>Normalization and Accents</strong> 108* <p> 109* <code>RuleBasedCollator</code> automatically processes its rule table to 110* include both pre-composed and combining-character versions of accented 111* characters. Even if the provided rule string contains only base characters 112* and separate combining accent characters, the pre-composed accented 113* characters matching all canonical combinations of characters from the rule 114* string will be entered in the table. 115* <p> 116* This allows you to use a RuleBasedCollator to compare accented strings even 117* when the collator is set to NO_DECOMPOSITION. However, if the strings to be 118* collated contain combining sequences that may not be in canonical order, you 119* should set the collator to CANONICAL_DECOMPOSITION to enable sorting of 120* combining sequences. 121* For more information, see 122* <A HREF="http://www.aw.com/devpress">The Unicode Standard, Version 3.0</A>.) 123* 124* <p><strong>Errors</strong> 125* <p> 126* The following are errors: 127* <UL Type=disc> 128* <LI>A text-argument contains unquoted punctuation symbols 129* (e.g. "a < b-c < d"). 130* <LI>A relation or reset character not followed by a text-argument 131* (e.g. "a < , b"). 132* <LI>A reset where the text-argument (or an initial substring of the 133* text-argument) is not already in the sequence or allocated in the 134* default UCA table. 135* (e.g. "a < b & e < f") 136* </UL> 137* If you produce one of these errors, a <code>RuleBasedCollator</code> throws 138* a <code>ParseException</code>. 139* 140* <p><strong>Examples</strong> 141* <p>Simple: "< a < b < c < d" 142* <p>Norwegian: "< a,A< b,B< c,C< d,D< e,E< f,F< g,G< h,H< i,I< j,J 143* < k,K< l,L< m,M< n,N< o,O< p,P< q,Q< r,R< s,S< t,T 144* < u,U< v,V< w,W< x,X< y,Y< z,Z 145* < ?=a?,?=A? 146* ;aa,AA< ?,?< ?,?" 147* 148* <p> 149* Normally, to create a rule-based Collator object, you will use 150* <code>Collator</code>'s factory method <code>getInstance</code>. 151* However, to create a rule-based Collator object with specialized rules 152* tailored to your needs, you construct the <code>RuleBasedCollator</code> 153* with the rules contained in a <code>String</code> object. For example: 154* <blockquote> 155* <pre> 156* String Simple = "< a < b < c < d"; 157* RuleBasedCollator mySimple = new RuleBasedCollator(Simple); 158* </pre> 159* </blockquote> 160* Or: 161* <blockquote> 162* <pre> 163* String Norwegian = "< a,A< b,B< c,C< d,D< e,E< f,F< g,G< h,H< i,I< j,J" + 164* "< k,K< l,L< m,M< n,N< o,O< p,P< q,Q< r,R< s,S< t,T" + 165* "< u,U< v,V< w,W< x,X< y,Y< z,Z" + 166* "< ?=a?,?=A?" + 167* ";aa,AA< ?,?< ?,?"; 168* RuleBasedCollator myNorwegian = new RuleBasedCollator(Norwegian); 169* </pre> 170* </blockquote> 171* 172* <p> 173* Combining <code>Collator</code>s is as simple as concatenating strings. 174* Here's an example that combines two <code>Collator</code>s from two 175* different locales: 176* <blockquote> 177* <pre> 178* // Create an en_US Collator object 179* RuleBasedCollator en_USCollator = (RuleBasedCollator) 180* Collator.getInstance(new Locale("en", "US", "")); 181* // Create a da_DK Collator object 182* RuleBasedCollator da_DKCollator = (RuleBasedCollator) 183* Collator.getInstance(new Locale("da", "DK", "")); 184* // Combine the two 185* // First, get the collation rules from en_USCollator 186* String en_USRules = en_USCollator.getRules(); 187* // Second, get the collation rules from da_DKCollator 188* String da_DKRules = da_DKCollator.getRules(); 189* RuleBasedCollator newCollator = 190* new RuleBasedCollator(en_USRules + da_DKRules); 191* // newCollator has the combined rules 192* </pre> 193* </blockquote> 194* 195* <p> 196* Another more interesting example would be to make changes on an existing 197* table to create a new <code>Collator</code> object. For example, add 198* "& C < ch, cH, Ch, CH" to the <code>en_USCollator</code> object to create 199* your own: 200* <blockquote> 201* <pre> 202* // Create a new Collator object with additional rules 203* String addRules = "& C < ch, cH, Ch, CH"; 204* RuleBasedCollator myCollator = 205* new RuleBasedCollator(en_USCollator + addRules); 206* // myCollator contains the new rules 207* </pre> 208* </blockquote> 209* 210* <p> 211* The following example demonstrates how to change the order of 212* non-spacing accents, 213* <blockquote> 214* <pre> 215* // old rule 216* String oldRules = "=?;?;?" // main accents Diaeresis 00A8, Macron 00AF 217* // Acute 00BF 218* + "< a , A ; ae, AE ; ? , ?" 219* + "< b , B < c, C < e, E & C < d, D"; 220* // change the order of accent characters 221* String addOn = "& ?;?;?;"; // Acute 00BF, Macron 00AF, Diaeresis 00A8 222* RuleBasedCollator myCollator = new RuleBasedCollator(oldRules + addOn); 223* </pre> 224* </blockquote> 225* 226* <p> 227* The last example shows how to put new primary ordering in before the 228* default setting. For example, in Japanese <code>Collator</code>, you 229* can either sort English characters before or after Japanese characters, 230* <blockquote> 231* <pre> 232* // get en_US Collator rules 233* RuleBasedCollator en_USCollator = 234* (RuleBasedCollator)Collator.getInstance(Locale.US); 235* // add a few Japanese character to sort before English characters 236* // suppose the last character before the first base letter 'a' in 237* // the English collation rule is ? 238* String jaString = "& \\u30A2 , \\u30FC < \\u30C8"; 239* RuleBasedCollator myJapaneseCollator = new 240* RuleBasedCollator(en_USCollator.getRules() + jaString); 241* </pre> 242* </blockquote> 243* <P> 244* @author syn wee quek 245* @stable ICU 2.4 246*/ 247 248public final class RuleBasedCollator extends Collator 249{ 250 // public constructors ------------------------------------------ 251 252 /** 253 * RuleBasedCollator constructor. This takes the table rules and builds a 254 * collation table out of them. Please see RuleBasedCollator class 255 * description for more details on the collation rule syntax. 256 * @param rules the collation rules to build the collation table from. 257 * @exception ParseException thrown if rules are empty or a Runtime error 258 * if collator can not be created. 259 * @stable ICU 2.4 260 */ 261 public RuleBasedCollator(String rules) throws ParseException 262 { 263 // BEGIN android-changed 264 if (rules == null) { 265 throw new NullPointerException(); 266 } 267 // if (rules.length() == 0) 268 // throw new ParseException("Build rules empty.", 0); 269 // END android-changed 270 m_collator_ = NativeCollation.openCollatorFromRules(rules, 271 CollationAttribute.VALUE_OFF, 272 CollationAttribute.VALUE_DEFAULT_STRENGTH); 273 } 274 275 /** 276 * RuleBasedCollator constructor. This takes the table rules and builds a 277 * collation table out of them. Please see RuleBasedCollator class 278 * description for more details on the collation rule syntax. 279 * @param rules the collation rules to build the collation table from. 280 * @param strength collation strength 281 * @exception ParseException thrown if rules are empty or a Runtime error 282 * if collator can not be created. 283 * @see #PRIMARY 284 * @see #SECONDARY 285 * @see #TERTIARY 286 * @see #QUATERNARY 287 * @see #IDENTICAL 288 * @stable ICU 2.4 289 */ 290 public RuleBasedCollator(String rules, int strength) throws ParseException 291 { 292 // BEGIN android-changed 293 if (rules == null) { 294 throw new NullPointerException(); 295 } 296 // if (rules.length() == 0) 297 // throw new ParseException("Build rules empty.", 0); 298 // END android-changed 299 if (!CollationAttribute.checkStrength(strength)) 300 throw ErrorCode.getException(ErrorCode.U_ILLEGAL_ARGUMENT_ERROR); 301 302 m_collator_ = NativeCollation.openCollatorFromRules(rules, 303 CollationAttribute.VALUE_OFF, 304 strength); 305 } 306 307 /** 308 * RuleBasedCollator constructor. This takes the table rules and builds a 309 * collation table out of them. Please see RuleBasedCollator class 310 * description for more details on the collation rule syntax. 311 * <p>Note API change starting from release 2.4. Prior to release 2.4, the 312 * normalizationmode argument values are from the class 313 * com.ibm.icu4jni.text.Normalization. In 2.4, 314 * the valid normalizationmode arguments for this API are 315 * CollationAttribute.VALUE_ON and CollationAttribute.VALUE_OFF. 316 * </p> 317 * @param rules the collation rules to build the collation table from. 318 * @param strength collation strength 319 * @param normalizationmode normalization mode 320 * @exception IllegalArgumentException thrown when constructor error occurs 321 * @see #PRIMARY 322 * @see #SECONDARY 323 * @see #TERTIARY 324 * @see #QUATERNARY 325 * @see #IDENTICAL 326 * @see #CANONICAL_DECOMPOSITION 327 * @see #NO_DECOMPOSITION 328 * @stable ICU 2.4 329 */ 330 public RuleBasedCollator(String rules, int normalizationmode, int strength) 331 { 332 // BEGIN android-added 333 if (rules == null) { 334 throw new NullPointerException(); 335 } 336 // END android-added 337 if (!CollationAttribute.checkStrength(strength) || 338 !CollationAttribute.checkNormalization(normalizationmode)) { 339 throw ErrorCode.getException(ErrorCode.U_ILLEGAL_ARGUMENT_ERROR); 340 } 341 342 m_collator_ = NativeCollation.openCollatorFromRules(rules, 343 normalizationmode, strength); 344 } 345 346 // public methods ----------------------------------------------- 347 348 /** 349 * Makes a complete copy of the current object. 350 * @return a copy of this object if data clone is a success, otherwise null 351 * @stable ICU 2.4 352 */ 353 public Object clone() 354 { 355 RuleBasedCollator result = null; 356 int collatoraddress = NativeCollation.safeClone(m_collator_); 357 result = new RuleBasedCollator(collatoraddress); 358 return (Collator)result; 359 } 360 361 /** 362 * The comparison function compares the character data stored in two 363 * different strings. Returns information about whether a string is less 364 * than, greater than or equal to another string. 365 * <p>Example of use: 366 * <br> 367 * <code> 368 * Collator myCollation = Collator.createInstance(Locale::US); 369 * myCollation.setStrength(CollationAttribute.VALUE_PRIMARY); 370 * // result would be Collator.RESULT_EQUAL ("abc" == "ABC") 371 * // (no primary difference between "abc" and "ABC") 372 * int result = myCollation.compare("abc", "ABC",3); 373 * myCollation.setStrength(CollationAttribute.VALUE_TERTIARY); 374 * // result would be Collation::LESS (abc" <<< "ABC") 375 * // (with tertiary difference between "abc" and "ABC") 376 * int result = myCollation.compare("abc", "ABC",3); 377 * </code> 378 * @param source The source string. 379 * @param target The target string. 380 * @return result of the comparison, Collator.RESULT_EQUAL, 381 * Collator.RESULT_GREATER or Collator.RESULT_LESS 382 * @stable ICU 2.4 383 */ 384 public int compare(String source, String target) 385 { 386 return NativeCollation.compare(m_collator_, source, target); 387 } 388 389 /** 390 * Get the normalization mode for this object. 391 * The normalization mode influences how strings are compared. 392 * @see #CANONICAL_DECOMPOSITION 393 * @see #NO_DECOMPOSITION 394 * @stable ICU 2.4 395 */ 396 public int getDecomposition() 397 { 398 return NativeCollation.getNormalization(m_collator_); 399 } 400 401 /** 402 * <p>Sets the decomposition mode of the Collator object on or off. 403 * If the decomposition mode is set to on, string would be decomposed into 404 * NFD format where necessary before sorting.</p> 405 * </p> 406 * @param decompositionmode the new decomposition mode 407 * @see #CANONICAL_DECOMPOSITION 408 * @see #NO_DECOMPOSITION 409 * @stable ICU 2.4 410 */ 411 public void setDecomposition(int decompositionmode) 412 { 413 if (!CollationAttribute.checkNormalization(decompositionmode)) 414 throw ErrorCode.getException(ErrorCode.U_ILLEGAL_ARGUMENT_ERROR); 415 NativeCollation.setAttribute(m_collator_, 416 CollationAttribute.NORMALIZATION_MODE, 417 decompositionmode); 418 } 419 420 /** 421 * Determines the minimum strength that will be use in comparison or 422 * transformation. 423 * <p> 424 * E.g. with strength == CollationAttribute.VALUE_SECONDARY, the tertiary difference 425 * is ignored 426 * </p> 427 * <p> 428 * E.g. with strength == PRIMARY, the secondary and tertiary difference are 429 * ignored. 430 * </p> 431 * @return the current comparison level. 432 * @see #PRIMARY 433 * @see #SECONDARY 434 * @see #TERTIARY 435 * @see #QUATERNARY 436 * @see #IDENTICAL 437 * @stable ICU 2.4 438 */ 439 public int getStrength() 440 { 441 return NativeCollation.getAttribute(m_collator_, 442 CollationAttribute.STRENGTH); 443 } 444 445 /** 446 * Sets the minimum strength to be used in comparison or transformation. 447 * <p>Example of use: 448 * <br> 449 * <code> 450 * Collator myCollation = Collator.createInstance(Locale::US); 451 * myCollation.setStrength(PRIMARY); 452 * // result will be "abc" == "ABC" 453 * // tertiary differences will be ignored 454 * int result = myCollation->compare("abc", "ABC"); 455 * </code> 456 * @param strength the new comparison level. 457 * @exception IllegalArgumentException when argument does not belong to any collation strength 458 * mode or error occurs while setting data. 459 * @see #PRIMARY 460 * @see #SECONDARY 461 * @see #TERTIARY 462 * @see #QUATERNARY 463 * @see #IDENTICAL 464 * @stable ICU 2.4 465 */ 466 public void setStrength(int strength) 467 { 468 if (!CollationAttribute.checkStrength(strength)) 469 throw ErrorCode.getException(ErrorCode.U_ILLEGAL_ARGUMENT_ERROR); 470 NativeCollation.setAttribute(m_collator_, CollationAttribute.STRENGTH, 471 strength); 472 } 473 474 /** 475 * Sets the attribute to be used in comparison or transformation. 476 * <p>Example of use: 477 * <br> 478 * <code> 479 * Collator myCollation = Collator.createInstance(Locale::US); 480 * myCollation.setAttribute(CollationAttribute.CASE_LEVEL, 481 * CollationAttribute.VALUE_ON); 482 * int result = myCollation->compare("\\u30C3\\u30CF", 483 * "\\u30C4\\u30CF"); 484 * // result will be Collator.RESULT_LESS. 485 * </code> 486 * @param type the attribute to be set from CollationAttribute 487 * @param value attribute value from CollationAttribute 488 * @stable ICU 2.4 489 */ 490 public void setAttribute(int type, int value) 491 { 492 if (!CollationAttribute.checkAttribute(type, value)) 493 throw ErrorCode.getException(ErrorCode.U_ILLEGAL_ARGUMENT_ERROR); 494 NativeCollation.setAttribute(m_collator_, type, value); 495 } 496 497 /** 498 * Gets the attribute to be used in comparison or transformation. 499 * @param type the attribute to be set from CollationAttribute 500 * @return value attribute value from CollationAttribute 501 * @stable ICU 2.4 502 */ 503 public int getAttribute(int type) 504 { 505 if (!CollationAttribute.checkType(type)) 506 throw ErrorCode.getException(ErrorCode.U_ILLEGAL_ARGUMENT_ERROR); 507 return NativeCollation.getAttribute(m_collator_, type); 508 } 509 510 /** 511 * Get the sort key as an CollationKey object from the argument string. 512 * To retrieve sort key in terms of byte arrays, use the method as below<br> 513 * <br> 514 * <code> 515 * Collator collator = Collator.getInstance(); 516 * byte[] array = collator.getSortKey(source); 517 * </code><br> 518 * Byte array result are zero-terminated and can be compared using 519 * java.util.Arrays.equals(); 520 * @param source string to be processed. 521 * @return the sort key 522 * @stable ICU 2.4 523 */ 524 public CollationKey getCollationKey(String source) 525 { 526 // BEGIN android-removed 527 // return new CollationKey(NativeCollation.getSortKey(m_collator_, source)); 528 // END android-removed 529 // BEGIN android-added 530 if(source == null) { 531 return null; 532 } 533 byte[] key = NativeCollation.getSortKey(m_collator_, source); 534 if(key == null) { 535 return null; 536 } 537 return new CollationKey(key); 538 // END android-added 539 } 540 541 /** 542 * Get a sort key for the argument string 543 * Sort keys may be compared using java.util.Arrays.equals 544 * @param source string for key to be generated 545 * @return sort key 546 * @stable ICU 2.4 547 */ 548 public byte[] getSortKey(String source) 549 { 550 return NativeCollation.getSortKey(m_collator_, source); 551 } 552 553 /** 554 * Get the collation rules of this Collation object 555 * The rules will follow the rule syntax. 556 * @return collation rules. 557 * @stable ICU 2.4 558 */ 559 public String getRules() 560 { 561 return NativeCollation.getRules(m_collator_); 562 } 563 564 /** 565 * Create a CollationElementIterator object that will iterator over the 566 * elements in a string, using the collation rules defined in this 567 * RuleBasedCollator 568 * @param source string to iterate over 569 * @return address of C collationelement 570 * @exception IllegalArgumentException thrown when error occurs 571 * @stable ICU 2.4 572 */ 573 public CollationElementIterator getCollationElementIterator(String source) 574 { 575 CollationElementIterator result = new CollationElementIterator( 576 NativeCollation.getCollationElementIterator(m_collator_, source)); 577 // result.setOwnCollationElementIterator(true); 578 return result; 579 } 580 581 // BEGIN android-added 582 /** 583 * Create a CollationElementIterator object that will iterator over the 584 * elements in a string, using the collation rules defined in this 585 * RuleBasedCollator 586 * @param source string to iterate over 587 * @return address of C collationelement 588 * @exception IllegalArgumentException thrown when error occurs 589 * @stable ICU 2.4 590 */ 591 public CollationElementIterator getCollationElementIterator( 592 CharacterIterator source) 593 { 594 CollationElementIterator result = new CollationElementIterator( 595 NativeCollation.getCollationElementIterator(m_collator_, 596 source.toString())); 597 // result.setOwnCollationElementIterator(true); 598 return result; 599 } 600 // END android-added 601 602 /** 603 * Returns a hash of this collation object 604 * Note this method is not complete, it only returns 0 at the moment. 605 * @return hash of this collation object 606 * @stable ICU 2.4 607 */ 608 public int hashCode() 609 { 610 // since rules do not change once it is created, we can cache the hash 611 if (m_hashcode_ == 0) { 612 m_hashcode_ = NativeCollation.hashCode(m_collator_); 613 if (m_hashcode_ == 0) 614 m_hashcode_ = 1; 615 } 616 return m_hashcode_; 617 } 618 619 /** 620 * Checks if argument object is equals to this object. 621 * @param target object 622 * @return true if source is equivalent to target, false otherwise 623 * @stable ICU 2.4 624 */ 625 public boolean equals(Object target) 626 { 627 if (this == target) 628 return true; 629 if (target == null) 630 return false; 631 if (getClass() != target.getClass()) 632 return false; 633 634 RuleBasedCollator tgtcoll = (RuleBasedCollator)target; 635 return getRules().equals(tgtcoll.getRules()) && 636 getStrength() == tgtcoll.getStrength() && 637 getDecomposition() == tgtcoll.getDecomposition(); 638 } 639 640 // package constructor ---------------------------------------- 641 642 /** 643 * RuleBasedCollator default constructor. This constructor takes the default 644 * locale. The only caller of this class should be Collator.getInstance(). 645 * Current implementation createInstance() returns a RuleBasedCollator(Locale) 646 * instance. The RuleBasedCollator will be created in the following order, 647 * <ul> 648 * <li> Data from argument locale resource bundle if found, otherwise 649 * <li> Data from parent locale resource bundle of arguemtn locale if found, 650 * otherwise 651 * <li> Data from built-in default collation rules if found, other 652 * <li> null is returned 653 * </ul> 654 */ 655 RuleBasedCollator() 656 { 657 m_collator_ = NativeCollation.openCollator(); 658 } 659 660 /** 661 * RuleBasedCollator constructor. This constructor takes a locale. The 662 * only caller of this class should be Collator.createInstance(). 663 * Current implementation createInstance() returns a RuleBasedCollator(Locale) 664 * instance. The RuleBasedCollator will be created in the following order, 665 * <ul> 666 * <li> Data from argument locale resource bundle if found, otherwise 667 * <li> Data from parent locale resource bundle of arguemtn locale if found, 668 * otherwise 669 * <li> Data from built-in default collation rules if found, other 670 * <li> null is returned 671 * </ul> 672 * @param locale locale used 673 */ 674 RuleBasedCollator(Locale locale) 675 { 676 if (locale == null) { 677 m_collator_ = NativeCollation.openCollator(); 678 } 679 else { 680 m_collator_ = NativeCollation.openCollator(locale.toString()); 681 } 682 } 683 684 // protected methods -------------------------------------------- 685 686 /** 687 * Garbage collection. 688 * Close C collator and reclaim memory. 689 */ 690 protected void finalize() 691 { 692 NativeCollation.closeCollator(m_collator_); 693 } 694 695 // private data members ----------------------------------------- 696 697 /** 698 * C collator 699 */ 700 private int m_collator_; 701 702 /** 703 * Hash code for rules 704 */ 705 private int m_hashcode_ = 0; 706 707 // private constructor ----------------------------------------- 708 709 /** 710 * Private use constructor. 711 * Does not create any instance of the C collator. Accepts argument as the 712 * C collator for new instance. 713 * @param collatoraddress address of C collator 714 */ 715 private RuleBasedCollator(int collatoraddress) 716 { 717 m_collator_ = collatoraddress; 718 } 719} 720