1 /* 2 ******************************************************************************* 3 * Copyright (C) 1996-2014, International Business Machines Corporation and * 4 * others. All Rights Reserved. * 5 ******************************************************************************* 6 */ 7 package com.ibm.icu.text; 8 9 import java.io.IOException; 10 import java.io.ObjectInputStream; 11 import java.io.Serializable; 12 import java.text.ChoiceFormat; 13 import java.util.Arrays; 14 import java.util.Locale; 15 import java.util.MissingResourceException; 16 17 import com.ibm.icu.impl.CurrencyData; 18 import com.ibm.icu.impl.CurrencyData.CurrencyDisplayInfo; 19 import com.ibm.icu.impl.CurrencyData.CurrencyFormatInfo; 20 import com.ibm.icu.impl.CurrencyData.CurrencySpacingInfo; 21 import com.ibm.icu.impl.ICUCache; 22 import com.ibm.icu.impl.ICUResourceBundle; 23 import com.ibm.icu.impl.SimpleCache; 24 import com.ibm.icu.util.Currency; 25 import com.ibm.icu.util.ICUCloneNotSupportedException; 26 import com.ibm.icu.util.ULocale; 27 import com.ibm.icu.util.ULocale.Category; 28 import com.ibm.icu.util.UResourceBundle; 29 30 /** 31 * {@icuenhanced java.text.DecimalFormatSymbols}.{@icu _usage_} 32 * 33 * This class represents the set of symbols (such as the decimal separator, the grouping 34 * separator, and so on) needed by <code>DecimalFormat</code> to format 35 * numbers. <code>DecimalFormat</code> creates for itself an instance of 36 * <code>DecimalFormatSymbols</code> from its locale data. If you need to change any of 37 * these symbols, you can get the <code>DecimalFormatSymbols</code> object from your 38 * <code>DecimalFormat</code> and modify it. 39 * 40 * @see java.util.Locale 41 * @see DecimalFormat 42 * @author Mark Davis 43 * @author Alan Liu 44 * @stable ICU 2.0 45 */ 46 public class DecimalFormatSymbols implements Cloneable, Serializable { 47 /** 48 * Creates a DecimalFormatSymbols object for the default <code>FORMAT</code> locale. 49 * @see Category#FORMAT 50 * @stable ICU 2.0 51 */ DecimalFormatSymbols()52 public DecimalFormatSymbols() { 53 initialize(ULocale.getDefault(Category.FORMAT)); 54 } 55 56 /** 57 * Creates a DecimalFormatSymbols object for the given locale. 58 * @param locale the locale 59 * @stable ICU 2.0 60 */ DecimalFormatSymbols(Locale locale)61 public DecimalFormatSymbols(Locale locale) { 62 initialize(ULocale.forLocale(locale)); 63 } 64 65 /** 66 * {@icu} Creates a DecimalFormatSymbols object for the given locale. 67 * @param locale the locale 68 * @stable ICU 3.2 69 */ DecimalFormatSymbols(ULocale locale)70 public DecimalFormatSymbols(ULocale locale) { 71 initialize(locale); 72 } 73 74 /** 75 * Returns a DecimalFormatSymbols instance for the default locale. 76 * 77 * <p><strong>Note:</strong> Unlike 78 * <code>java.text.DecimalFormatSymbols#getInstance</code>, this method simply returns 79 * <code>new com.ibm.icu.text.DecimalFormatSymbols()</code>. ICU currently does not 80 * support <code>DecimalFormatSymbolsProvider</code>, which was introduced in Java 6. 81 * 82 * @return A DecimalFormatSymbols instance. 83 * @stable ICU 3.8 84 */ getInstance()85 public static DecimalFormatSymbols getInstance() { 86 return new DecimalFormatSymbols(); 87 } 88 89 /** 90 * Returns a DecimalFormatSymbols instance for the given locale. 91 * 92 * <p><strong>Note:</strong> Unlike 93 * <code>java.text.DecimalFormatSymbols#getInstance</code>, this method simply returns 94 * <code>new com.ibm.icu.text.DecimalFormatSymbols(locale)</code>. ICU currently does 95 * not support <code>DecimalFormatSymbolsProvider</code>, which was introduced in Java 96 * 6. 97 * 98 * @param locale the locale. 99 * @return A DecimalFormatSymbols instance. 100 * @stable ICU 3.8 101 */ getInstance(Locale locale)102 public static DecimalFormatSymbols getInstance(Locale locale) { 103 return new DecimalFormatSymbols(locale); 104 } 105 106 /** 107 * Returns a DecimalFormatSymbols instance for the given locale. 108 * 109 * <p><strong>Note:</strong> Unlike 110 * <code>java.text.DecimalFormatSymbols#getInstance</code>, this method simply returns 111 * <code>new com.ibm.icu.text.DecimalFormatSymbols(locale)</code>. ICU currently does 112 * not support <code>DecimalFormatSymbolsProvider</code>, which was introduced in Java 113 * 6. 114 * 115 * @param locale the locale. 116 * @return A DecimalFormatSymbols instance. 117 * @stable ICU 3.8 118 */ getInstance(ULocale locale)119 public static DecimalFormatSymbols getInstance(ULocale locale) { 120 return new DecimalFormatSymbols(locale); 121 } 122 123 /** 124 * Returns an array of all locales for which the <code>getInstance</code> methods of 125 * this class can return localized instances. 126 * 127 * <p><strong>Note:</strong> Unlike 128 * <code>java.text.DecimalFormatSymbols#getAvailableLocales</code>, this method simply 129 * returns the array of <code>Locale</code>s available for this class. ICU currently 130 * does not support <code>DecimalFormatSymbolsProvider</code>, which was introduced in 131 * Java 6. 132 * 133 * @return An array of <code>Locale</code>s for which localized 134 * <code>DecimalFormatSymbols</code> instances are available. 135 * @stable ICU 3.8 136 */ getAvailableLocales()137 public static Locale[] getAvailableLocales() { 138 return ICUResourceBundle.getAvailableLocales(); 139 } 140 141 /** 142 * {@icu} Returns an array of all locales for which the <code>getInstance</code> 143 * methods of this class can return localized instances. 144 * 145 * <p><strong>Note:</strong> Unlike 146 * <code>java.text.DecimalFormatSymbols#getAvailableLocales</code>, this method simply 147 * returns the array of <code>ULocale</code>s available in this class. ICU currently 148 * does not support <code>DecimalFormatSymbolsProvider</code>, which was introduced in 149 * Java 6. 150 * 151 * @return An array of <code>ULocale</code>s for which localized 152 * <code>DecimalFormatSymbols</code> instances are available. 153 * @stable ICU 3.8 (retain) 154 * @provisional This API might change or be removed in a future release. 155 */ getAvailableULocales()156 public static ULocale[] getAvailableULocales() { 157 return ICUResourceBundle.getAvailableULocales(); 158 } 159 160 161 /** 162 * Returns the character used for zero. Different for Arabic, etc. 163 * @return the character 164 * @stable ICU 2.0 165 */ getZeroDigit()166 public char getZeroDigit() { 167 if ( digits != null ) { 168 return digits[0]; 169 } else { 170 return zeroDigit; 171 } 172 } 173 /** 174 * Returns the array of characters used as digits, in order from 0 through 9 175 * @return The array 176 * @stable ICU 4.6 177 */ getDigits()178 public char[] getDigits() { 179 if ( digits != null ) { 180 return digits.clone(); 181 } else { 182 char [] digitArray = new char[10]; 183 for ( int i = 0 ; i < 10 ; i++ ) { 184 digitArray[i] = (char) (zeroDigit + i); 185 } 186 return digitArray; 187 } 188 } 189 190 /** 191 * Returns the array of characters used as digits, in order from 0 through 9 192 * Package private method - don't need to defensively copy. 193 * @return The array 194 */ getDigitsLocal()195 char[] getDigitsLocal() { 196 if ( digits != null ) { 197 return digits; 198 } else { 199 char [] digitArray = new char[10]; 200 for ( int i = 0 ; i < 10 ; i++ ) { 201 digitArray[i] = (char) (zeroDigit + i); 202 } 203 return digitArray; 204 } 205 } 206 207 /** 208 * Sets the character used for zero. 209 * @param zeroDigit the zero character. 210 * @stable ICU 2.0 211 */ setZeroDigit(char zeroDigit)212 public void setZeroDigit(char zeroDigit) { 213 if ( digits != null ) { 214 this.digits[0] = zeroDigit; 215 if (Character.digit(zeroDigit,10) == 0) { 216 for ( int i = 1 ; i < 10 ; i++ ) { 217 this.digits[i] = (char)(zeroDigit+i); 218 } 219 } 220 } else { 221 this.zeroDigit = zeroDigit; 222 } 223 } 224 225 /** 226 * Returns the character used to represent a significant digit in a pattern. 227 * @return the significant digit pattern character 228 * @stable ICU 3.0 229 */ getSignificantDigit()230 public char getSignificantDigit() { 231 return sigDigit; 232 } 233 234 /** 235 * Sets the character used to represent a significant digit in a pattern. 236 * @param sigDigit the significant digit pattern character 237 * @stable ICU 3.0 238 */ setSignificantDigit(char sigDigit)239 public void setSignificantDigit(char sigDigit) { 240 this.sigDigit = sigDigit; 241 } 242 243 /** 244 * Returns the character used for thousands separator. Different for French, etc. 245 * @return the thousands character 246 * @stable ICU 2.0 247 */ getGroupingSeparator()248 public char getGroupingSeparator() { 249 return groupingSeparator; 250 } 251 252 /** 253 * Sets the character used for thousands separator. Different for French, etc. 254 * @param groupingSeparator the thousands character 255 * @stable ICU 2.0 256 */ setGroupingSeparator(char groupingSeparator)257 public void setGroupingSeparator(char groupingSeparator) { 258 this.groupingSeparator = groupingSeparator; 259 } 260 261 /** 262 * Returns the character used for decimal sign. Different for French, etc. 263 * @return the decimal character 264 * @stable ICU 2.0 265 */ getDecimalSeparator()266 public char getDecimalSeparator() { 267 return decimalSeparator; 268 } 269 270 /** 271 * Sets the character used for decimal sign. Different for French, etc. 272 * @param decimalSeparator the decimal character 273 * @stable ICU 2.0 274 */ setDecimalSeparator(char decimalSeparator)275 public void setDecimalSeparator(char decimalSeparator) { 276 this.decimalSeparator = decimalSeparator; 277 } 278 279 /** 280 * Returns the character used for mille percent sign. Different for Arabic, etc. 281 * @return the mille percent character 282 * @stable ICU 2.0 283 */ getPerMill()284 public char getPerMill() { 285 return perMill; 286 } 287 288 /** 289 * Sets the character used for mille percent sign. Different for Arabic, etc. 290 * @param perMill the mille percent character 291 * @stable ICU 2.0 292 */ setPerMill(char perMill)293 public void setPerMill(char perMill) { 294 this.perMill = perMill; 295 } 296 297 /** 298 * Returns the character used for percent sign. Different for Arabic, etc. 299 * @return the percent character 300 * @stable ICU 2.0 301 */ getPercent()302 public char getPercent() { 303 return percent; 304 } 305 306 /** 307 * Sets the character used for percent sign. Different for Arabic, etc. 308 * @param percent the percent character 309 * @stable ICU 2.0 310 */ setPercent(char percent)311 public void setPercent(char percent) { 312 this.percent = percent; 313 } 314 315 /** 316 * Returns the character used for a digit in a pattern. 317 * @return the digit pattern character 318 * @stable ICU 2.0 319 */ getDigit()320 public char getDigit() { 321 return digit; 322 } 323 324 /** 325 * Sets the character used for a digit in a pattern. 326 * @param digit the digit pattern character 327 * @stable ICU 2.0 328 */ setDigit(char digit)329 public void setDigit(char digit) { 330 this.digit = digit; 331 } 332 333 /** 334 * Returns the character used to separate positive and negative subpatterns 335 * in a pattern. 336 * @return the pattern separator character 337 * @stable ICU 2.0 338 */ getPatternSeparator()339 public char getPatternSeparator() { 340 return patternSeparator; 341 } 342 343 /** 344 * Sets the character used to separate positive and negative subpatterns 345 * in a pattern. 346 * @param patternSeparator the pattern separator character 347 * @stable ICU 2.0 348 */ setPatternSeparator(char patternSeparator)349 public void setPatternSeparator(char patternSeparator) { 350 this.patternSeparator = patternSeparator; 351 } 352 353 /** 354 * Returns the String used to represent infinity. Almost always left 355 * unchanged. 356 * @return the Infinity string 357 * @stable ICU 2.0 358 */ 359 //Bug 4194173 [Richard/GCL] 360 getInfinity()361 public String getInfinity() { 362 return infinity; 363 } 364 365 /** 366 * Sets the String used to represent infinity. Almost always left 367 * unchanged. 368 * @param infinity the Infinity String 369 * @stable ICU 2.0 370 */ setInfinity(String infinity)371 public void setInfinity(String infinity) { 372 this.infinity = infinity; 373 } 374 375 /** 376 * Returns the String used to represent NaN. Almost always left 377 * unchanged. 378 * @return the NaN String 379 * @stable ICU 2.0 380 */ 381 //Bug 4194173 [Richard/GCL] getNaN()382 public String getNaN() { 383 return NaN; 384 } 385 386 /** 387 * Sets the String used to represent NaN. Almost always left 388 * unchanged. 389 * @param NaN the NaN String 390 * @stable ICU 2.0 391 */ setNaN(String NaN)392 public void setNaN(String NaN) { 393 this.NaN = NaN; 394 } 395 396 /** 397 * Returns the character used to represent minus sign. If no explicit 398 * negative format is specified, one is formed by prefixing 399 * minusSign to the positive format. 400 * @return the minus sign character 401 * @stable ICU 2.0 402 */ getMinusSign()403 public char getMinusSign() { 404 return minusSign; 405 } 406 407 /** 408 * Returns the string used to represent minus sign. 409 * @return the minus sign string 410 * @internal 411 * @deprecated This API is ICU internal only. 412 */ 413 @Deprecated getMinusString()414 public String getMinusString() { 415 return minusString; 416 } 417 418 /** 419 * Sets the character used to represent minus sign. If no explicit 420 * negative format is specified, one is formed by prefixing 421 * minusSign to the positive format. 422 * @param minusSign the minus sign character 423 * @stable ICU 2.0 424 */ setMinusSign(char minusSign)425 public void setMinusSign(char minusSign) { 426 this.minusSign = minusSign; 427 // Also updates minusString 428 char[] minusArray = { minusSign }; 429 minusString = new String(minusArray); 430 } 431 432 /** 433 * Returns the string denoting the local currency. 434 * @return the local currency String. 435 * @stable ICU 2.0 436 */ getCurrencySymbol()437 public String getCurrencySymbol() { 438 return currencySymbol; 439 } 440 441 /** 442 * Sets the string denoting the local currency. 443 * @param currency the local currency String. 444 * @stable ICU 2.0 445 */ setCurrencySymbol(String currency)446 public void setCurrencySymbol(String currency) { 447 currencySymbol = currency; 448 } 449 450 /** 451 * Returns the international string denoting the local currency. 452 * @return the international string denoting the local currency 453 * @stable ICU 2.0 454 */ getInternationalCurrencySymbol()455 public String getInternationalCurrencySymbol() { 456 return intlCurrencySymbol; 457 } 458 459 /** 460 * Sets the international string denoting the local currency. 461 * @param currency the international string denoting the local currency. 462 * @stable ICU 2.0 463 */ setInternationalCurrencySymbol(String currency)464 public void setInternationalCurrencySymbol(String currency) { 465 intlCurrencySymbol = currency; 466 } 467 468 /** 469 * Returns the currency symbol, for JDK 1.4 compatibility only. 470 * ICU clients should use the Currency API directly. 471 * @return the currency used, or null 472 * @stable ICU 3.4 473 */ getCurrency()474 public Currency getCurrency() { 475 return currency; 476 } 477 478 /** 479 * Sets the currency. 480 * 481 * <p><strong>Note:</strong> ICU does not use the DecimalFormatSymbols for the currency 482 * any more. This API is present for API compatibility only. 483 * 484 * <p>This also sets the currency symbol attribute to the currency's symbol 485 * in the DecimalFormatSymbols' locale, and the international currency 486 * symbol attribute to the currency's ISO 4217 currency code. 487 * 488 * @param currency the new currency to be used 489 * @throws NullPointerException if <code>currency</code> is null 490 * @see #setCurrencySymbol 491 * @see #setInternationalCurrencySymbol 492 * 493 * @stable ICU 3.4 494 */ setCurrency(Currency currency)495 public void setCurrency(Currency currency) { 496 if (currency == null) { 497 throw new NullPointerException(); 498 } 499 this.currency = currency; 500 intlCurrencySymbol = currency.getCurrencyCode(); 501 currencySymbol = currency.getSymbol(requestedLocale); 502 } 503 504 /** 505 * Returns the monetary decimal separator. 506 * @return the monetary decimal separator character 507 * @stable ICU 2.0 508 */ getMonetaryDecimalSeparator()509 public char getMonetaryDecimalSeparator() { 510 return monetarySeparator; 511 } 512 513 /** 514 * {@icu} Returns the monetary grouping separator. 515 * @return the monetary grouping separator character 516 * @stable ICU 3.6 517 */ getMonetaryGroupingSeparator()518 public char getMonetaryGroupingSeparator() { 519 return monetaryGroupingSeparator; 520 } 521 522 /** 523 * Internal API for NumberFormat 524 * @return String currency pattern string 525 */ getCurrencyPattern()526 String getCurrencyPattern() { 527 return currencyPattern; 528 } 529 530 /** 531 * Sets the monetary decimal separator. 532 * @param sep the monetary decimal separator character 533 * @stable ICU 2.0 534 */ setMonetaryDecimalSeparator(char sep)535 public void setMonetaryDecimalSeparator(char sep) { 536 monetarySeparator = sep; 537 } 538 539 /** 540 * Sets the monetary decimal separator. 541 * @param sep the monetary decimal separator character 542 * @stable ICU 3.6 543 */ setMonetaryGroupingSeparator(char sep)544 public void setMonetaryGroupingSeparator(char sep) { 545 monetaryGroupingSeparator = sep; 546 } 547 548 /** 549 * Returns the multiplication sign 550 * @draft ICU 54 551 * @provisional This API might change or be removed in a future release. 552 */ getExponentMultiplicationSign()553 public String getExponentMultiplicationSign() { 554 return exponentMultiplicationSign; 555 } 556 557 /** 558 * Sets the multiplication sign 559 * @draft ICU 54 560 * @provisional This API might change or be removed in a future release. 561 */ setExponentMultiplicationSign(String exponentMultiplicationSign)562 public void setExponentMultiplicationSign(String exponentMultiplicationSign) { 563 this.exponentMultiplicationSign = exponentMultiplicationSign; 564 } 565 566 /** 567 * {@icu} Returns the string used to separate the mantissa from the exponent. 568 * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4. 569 * @return the localized exponent symbol, used in localized patterns 570 * and formatted strings 571 * @see #setExponentSeparator 572 * @stable ICU 2.0 573 */ getExponentSeparator()574 public String getExponentSeparator() { 575 return exponentSeparator; 576 } 577 578 /** 579 * {@icu} Sets the string used to separate the mantissa from the exponent. 580 * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4. 581 * @param exp the localized exponent symbol, used in localized patterns 582 * and formatted strings 583 * @see #getExponentSeparator 584 * @stable ICU 2.0 585 */ setExponentSeparator(String exp)586 public void setExponentSeparator(String exp) { 587 exponentSeparator = exp; 588 } 589 590 /** 591 * {@icu} Returns the localized plus sign. 592 * @return the plus sign, used in localized patterns and formatted 593 * strings 594 * @see #setPlusSign 595 * @see #setMinusSign 596 * @see #getMinusSign 597 * @stable ICU 2.0 598 */ getPlusSign()599 public char getPlusSign() { 600 return plusSign; 601 } 602 603 /** 604 * Returns the string used to represent plus sign. 605 * @return the plus sign string 606 * @internal 607 * @deprecated This API is ICU internal only. 608 */ 609 @Deprecated getPlusString()610 public String getPlusString() { 611 return plusString; 612 } 613 614 /** 615 * {@icu} Sets the localized plus sign. 616 * @param plus the plus sign, used in localized patterns and formatted 617 * strings 618 * @see #getPlusSign 619 * @see #setMinusSign 620 * @see #getMinusSign 621 * @stable ICU 2.0 622 */ setPlusSign(char plus)623 public void setPlusSign(char plus) { 624 plusSign = plus; 625 // Also updates plusString 626 char[] plusArray = { plusSign }; 627 plusString = new String(plusArray); 628 } 629 630 /** 631 * {@icu} Returns the character used to pad numbers out to a specified width. This is 632 * not the pad character itself; rather, it is the special pattern character 633 * <em>preceding</em> the pad character. In the pattern "*_#,##0", '*' is the pad 634 * escape, and '_' is the pad character. 635 * @return the character 636 * @see #setPadEscape 637 * @see DecimalFormat#getFormatWidth 638 * @see DecimalFormat#getPadPosition 639 * @see DecimalFormat#getPadCharacter 640 * @stable ICU 2.0 641 */ getPadEscape()642 public char getPadEscape() { 643 return padEscape; 644 } 645 646 /** 647 * {@icu} Sets the character used to pad numbers out to a specified width. This is not 648 * the pad character itself; rather, it is the special pattern character 649 * <em>preceding</em> the pad character. In the pattern "*_#,##0", '*' is the pad 650 * escape, and '_' is the pad character. 651 * @see #getPadEscape 652 * @see DecimalFormat#setFormatWidth 653 * @see DecimalFormat#setPadPosition 654 * @see DecimalFormat#setPadCharacter 655 * @stable ICU 2.0 656 */ setPadEscape(char c)657 public void setPadEscape(char c) { 658 padEscape = c; 659 } 660 661 /** 662 * {@icu} Indicates the currency match pattern used in {@link #getPatternForCurrencySpacing}. 663 * @stable ICU 4.2 664 */ 665 public static final int CURRENCY_SPC_CURRENCY_MATCH = 0; 666 667 /** 668 * {@icu} Indicates the surrounding match pattern used in {@link 669 * #getPatternForCurrencySpacing}. 670 * @stable ICU 4.2 671 */ 672 public static final int CURRENCY_SPC_SURROUNDING_MATCH = 1; 673 674 /** 675 * {@icu} Indicates the insertion value used in {@link #getPatternForCurrencySpacing}. 676 * @stable ICU 4.4 677 */ 678 public static final int CURRENCY_SPC_INSERT = 2; 679 680 private String[] currencySpcBeforeSym; 681 private String[] currencySpcAfterSym; 682 683 /** 684 * {@icu} Returns the desired currency spacing value. Original values come from ICU's 685 * CLDR data based on the locale provided during construction, and can be null. These 686 * values govern what and when text is inserted between a currency code/name/symbol 687 * and the currency amount when formatting money. 688 * 689 * <p>For more information, see <a href="http://www.unicode.org/reports/tr35/#Currencies" 690 * >UTS#35 section 5.10.2</a>. 691 * 692 * <p><strong>Note:</strong> ICU4J does not currently use this information. 693 * 694 * @param itemType one of CURRENCY_SPC_CURRENCY_MATCH, CURRENCY_SPC_SURROUNDING_MATCH 695 * or CURRENCY_SPC_INSERT 696 * @param beforeCurrency true to get the <code>beforeCurrency</code> values, false 697 * to get the <code>afterCurrency</code> values. 698 * @return the value, or null. 699 * @see #setPatternForCurrencySpacing(int, boolean, String) 700 * @stable ICU 4.2 701 */ getPatternForCurrencySpacing(int itemType, boolean beforeCurrency)702 public String getPatternForCurrencySpacing(int itemType, boolean beforeCurrency) { 703 if (itemType < CURRENCY_SPC_CURRENCY_MATCH || 704 itemType > CURRENCY_SPC_INSERT ) { 705 throw new IllegalArgumentException("unknown currency spacing: " + itemType); 706 } 707 if (beforeCurrency) { 708 return currencySpcBeforeSym[itemType]; 709 } 710 return currencySpcAfterSym[itemType]; 711 } 712 713 /** 714 * {@icu} Sets the indicated currency spacing pattern or value. See {@link 715 * #getPatternForCurrencySpacing} for more information. 716 * 717 * <p>Values for currency match and surrounding match must be {@link 718 * com.ibm.icu.text.UnicodeSet} patterns. Values for insert can be any string. 719 * 720 * <p><strong>Note:</strong> ICU4J does not currently use this information. 721 * 722 * @param itemType one of CURRENCY_SPC_CURRENCY_MATCH, CURRENCY_SPC_SURROUNDING_MATCH 723 * or CURRENCY_SPC_INSERT 724 * @param beforeCurrency true if the pattern is for before the currency symbol. 725 * false if the pattern is for after it. 726 * @param pattern string to override current setting; can be null. 727 * @see #getPatternForCurrencySpacing(int, boolean) 728 * @stable ICU 4.2 729 */ setPatternForCurrencySpacing(int itemType, boolean beforeCurrency, String pattern)730 public void setPatternForCurrencySpacing(int itemType, boolean beforeCurrency, String pattern) { 731 if (itemType < CURRENCY_SPC_CURRENCY_MATCH || 732 itemType > CURRENCY_SPC_INSERT ) { 733 throw new IllegalArgumentException("unknown currency spacing: " + itemType); 734 } 735 if (beforeCurrency) { 736 currencySpcBeforeSym[itemType] = pattern; 737 } else { 738 currencySpcAfterSym[itemType] = pattern; 739 } 740 } 741 742 /** 743 * Returns the locale for which this object was constructed. 744 * @return the locale for which this object was constructed 745 * @stable ICU 2.0 746 */ getLocale()747 public Locale getLocale() { 748 return requestedLocale; 749 } 750 751 /** 752 * Returns the locale for which this object was constructed. 753 * @return the locale for which this object was constructed 754 * @stable ICU 3.2 755 */ getULocale()756 public ULocale getULocale() { 757 return ulocale; 758 } 759 760 /** 761 * {@inheritDoc} 762 * @stable ICU 2.0 763 */ clone()764 public Object clone() { 765 try { 766 return (DecimalFormatSymbols) super.clone(); 767 // other fields are bit-copied 768 } catch (CloneNotSupportedException e) { 769 ///CLOVER:OFF 770 throw new ICUCloneNotSupportedException(e); 771 ///CLOVER:ON 772 } 773 } 774 775 /** 776 * {@inheritDoc} 777 * @stable ICU 2.0 778 */ equals(Object obj)779 public boolean equals(Object obj) { 780 if (!(obj instanceof DecimalFormatSymbols)) { 781 return false; 782 } 783 if (this == obj) { 784 return true; 785 } 786 DecimalFormatSymbols other = (DecimalFormatSymbols) obj; 787 for (int i = 0; i <= CURRENCY_SPC_INSERT; i++) { 788 if (!currencySpcBeforeSym[i].equals(other.currencySpcBeforeSym[i])) { 789 return false; 790 } 791 if (!currencySpcAfterSym[i].equals(other.currencySpcAfterSym[i])) { 792 return false; 793 } 794 } 795 796 if ( other.digits == null ) { 797 for (int i = 0 ; i < 10 ; i++) { 798 if (digits[i] != other.zeroDigit + i) { 799 return false; 800 } 801 } 802 } else if (!Arrays.equals(digits,other.digits)) { 803 return false; 804 } 805 806 return ( 807 groupingSeparator == other.groupingSeparator && 808 decimalSeparator == other.decimalSeparator && 809 percent == other.percent && 810 perMill == other.perMill && 811 digit == other.digit && 812 minusSign == other.minusSign && 813 minusString.equals(other.minusString) && 814 patternSeparator == other.patternSeparator && 815 infinity.equals(other.infinity) && 816 NaN.equals(other.NaN) && 817 currencySymbol.equals(other.currencySymbol) && 818 intlCurrencySymbol.equals(other.intlCurrencySymbol) && 819 padEscape == other.padEscape && 820 plusSign == other.plusSign && 821 plusString.equals(other.plusString) && 822 exponentSeparator.equals(other.exponentSeparator) && 823 monetarySeparator == other.monetarySeparator && 824 monetaryGroupingSeparator == other.monetaryGroupingSeparator && 825 exponentMultiplicationSign.equals(other.exponentMultiplicationSign)); 826 } 827 828 /** 829 * {@inheritDoc} 830 * @stable ICU 2.0 831 */ hashCode()832 public int hashCode() { 833 int result = digits[0]; 834 result = result * 37 + groupingSeparator; 835 result = result * 37 + decimalSeparator; 836 return result; 837 } 838 839 /** 840 * Check for bidi marks: LRM, RLM, ALM 841 */ isBidiMark(char c)842 private static boolean isBidiMark(char c) { 843 return (c=='\u200E' || c=='\u200F' || c=='\u061C'); 844 } 845 846 /** 847 * Initializes the symbols from the LocaleElements resource bundle. 848 * Note: The organization of LocaleElements badly needs to be 849 * cleaned up. 850 */ initialize( ULocale locale )851 private void initialize( ULocale locale ) { 852 this.requestedLocale = locale.toLocale(); 853 this.ulocale = locale; 854 855 String nsName; 856 // Attempt to set the zero digit based on the numbering system for the locale requested 857 NumberingSystem ns = NumberingSystem.getInstance(locale); 858 digits = new char[10]; 859 if ( ns != null && ns.getRadix() == 10 && !ns.isAlgorithmic() && 860 NumberingSystem.isValidDigitString(ns.getDescription())) { 861 String digitString = ns.getDescription(); 862 digits[0] = digitString.charAt(0); 863 digits[1] = digitString.charAt(1); 864 digits[2] = digitString.charAt(2); 865 digits[3] = digitString.charAt(3); 866 digits[4] = digitString.charAt(4); 867 digits[5] = digitString.charAt(5); 868 digits[6] = digitString.charAt(6); 869 digits[7] = digitString.charAt(7); 870 digits[8] = digitString.charAt(8); 871 digits[9] = digitString.charAt(9); 872 nsName = ns.getName(); 873 } else { 874 digits[0] = DecimalFormat.PATTERN_ZERO_DIGIT; 875 digits[1] = DecimalFormat.PATTERN_ONE_DIGIT; 876 digits[2] = DecimalFormat.PATTERN_TWO_DIGIT; 877 digits[3] = DecimalFormat.PATTERN_THREE_DIGIT; 878 digits[4] = DecimalFormat.PATTERN_FOUR_DIGIT; 879 digits[5] = DecimalFormat.PATTERN_FIVE_DIGIT; 880 digits[6] = DecimalFormat.PATTERN_SIX_DIGIT; 881 digits[7] = DecimalFormat.PATTERN_SEVEN_DIGIT; 882 digits[8] = DecimalFormat.PATTERN_EIGHT_DIGIT; 883 digits[9] = DecimalFormat.PATTERN_NINE_DIGIT; 884 nsName = "latn"; // Default numbering system 885 } 886 887 /* try the cache first */ 888 String[][] data = cachedLocaleData.get(locale); 889 String[] numberElements; 890 if (data == null) { /* cache miss */ 891 data = new String[1][]; 892 ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle. 893 getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale); 894 boolean isLatn = nsName.equals("latn"); 895 String baseKey = "NumberElements/" + nsName + "/symbols/"; 896 String latnKey = "NumberElements/latn/symbols/"; 897 String[] symbolKeys = { "decimal", "group", "list", "percentSign", "minusSign", "plusSign", "exponential", "perMille", "infinity", "nan", "currencyDecimal", "currencyGroup", "superscriptingExponent" }; 898 String[] fallbackElements = { ".", ",", ";", "%", "-", "+", "E", "\u2030", "\u221e", "NaN", null, null }; 899 String[] symbolsArray = new String[symbolKeys.length]; 900 for ( int i = 0 ; i < symbolKeys.length; i++ ) { 901 try { 902 symbolsArray[i] = rb.getStringWithFallback(baseKey+symbolKeys[i]); 903 } catch (MissingResourceException ex) { 904 if (!isLatn) { // Fall back to latn numbering system for symbols if desired symbol isn't found. 905 try { 906 symbolsArray[i] = rb.getStringWithFallback(latnKey+symbolKeys[i]); 907 } catch (MissingResourceException ex1) { 908 symbolsArray[i] = fallbackElements[i]; 909 } 910 } else { 911 symbolsArray[i] = fallbackElements[i]; 912 } 913 } 914 } 915 916 data[0] = symbolsArray; 917 /* update cache */ 918 cachedLocaleData.put(locale, data); 919 } 920 numberElements = data[0]; 921 922 ICUResourceBundle r = (ICUResourceBundle)UResourceBundle. 923 getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale); 924 925 // TODO: Determine actual and valid locale correctly. 926 ULocale uloc = r.getULocale(); 927 setLocale(uloc, uloc); 928 929 930 decimalSeparator = numberElements[0].charAt(0); 931 groupingSeparator = numberElements[1].charAt(0); 932 patternSeparator = numberElements[2].charAt(0); 933 percent = numberElements[3].charAt(0); 934 minusString = numberElements[4]; 935 minusSign = (minusString.length() > 1 && isBidiMark(minusString.charAt(0)))? minusString.charAt(1): minusString.charAt(0); 936 plusString = numberElements[5]; 937 plusSign = (plusString.length() > 1 && isBidiMark(plusString.charAt(0)))? plusString.charAt(1): plusString.charAt(0); 938 exponentSeparator = numberElements[6]; 939 perMill = numberElements[7].charAt(0); 940 infinity = numberElements[8]; 941 NaN = numberElements[9]; 942 943 if ( numberElements[10] != null) { 944 monetarySeparator = numberElements[10].charAt(0); 945 } else { 946 monetarySeparator = decimalSeparator; 947 } 948 949 if ( numberElements[11] != null) { 950 monetaryGroupingSeparator = numberElements[11].charAt(0); 951 } else { 952 monetaryGroupingSeparator = groupingSeparator; 953 } 954 955 if ( numberElements[12] != null) { 956 exponentMultiplicationSign = numberElements[12]; 957 } else { 958 exponentMultiplicationSign = "\u00D7"; 959 } 960 961 digit = DecimalFormat.PATTERN_DIGIT; // Localized pattern character no longer in CLDR 962 padEscape = DecimalFormat.PATTERN_PAD_ESCAPE; 963 sigDigit = DecimalFormat.PATTERN_SIGNIFICANT_DIGIT; 964 965 966 CurrencyDisplayInfo info = CurrencyData.provider.getInstance(locale, true); 967 968 // Obtain currency data from the currency API. This is strictly 969 // for backward compatibility; we don't use DecimalFormatSymbols 970 // for currency data anymore. 971 String currname = null; 972 currency = Currency.getInstance(locale); 973 if (currency != null) { 974 intlCurrencySymbol = currency.getCurrencyCode(); 975 boolean[] isChoiceFormat = new boolean[1]; 976 currname = currency.getName(locale, Currency.SYMBOL_NAME, isChoiceFormat); 977 // If this is a ChoiceFormat currency, then format an 978 // arbitrary value; pick something != 1; more common. 979 currencySymbol = isChoiceFormat[0] 980 ? new ChoiceFormat(currname).format(2.0) 981 : currname; 982 CurrencyFormatInfo fmtInfo = info.getFormatInfo(intlCurrencySymbol); 983 if (fmtInfo != null) { 984 currencyPattern = fmtInfo.currencyPattern; 985 monetarySeparator = fmtInfo.monetarySeparator; 986 monetaryGroupingSeparator = fmtInfo.monetaryGroupingSeparator; 987 } 988 } else { 989 intlCurrencySymbol = "XXX"; 990 currencySymbol = "\u00A4"; // 'OX' currency symbol 991 } 992 993 994 // Get currency spacing data. 995 currencySpcBeforeSym = new String[3]; 996 currencySpcAfterSym = new String[3]; 997 initSpacingInfo(info.getSpacingInfo()); 998 } 999 initSpacingInfo(CurrencySpacingInfo spcInfo)1000 private void initSpacingInfo(CurrencySpacingInfo spcInfo) { 1001 currencySpcBeforeSym[CURRENCY_SPC_CURRENCY_MATCH] = spcInfo.beforeCurrencyMatch; 1002 currencySpcBeforeSym[CURRENCY_SPC_SURROUNDING_MATCH] = spcInfo.beforeContextMatch; 1003 currencySpcBeforeSym[CURRENCY_SPC_INSERT] = spcInfo.beforeInsert; 1004 currencySpcAfterSym[CURRENCY_SPC_CURRENCY_MATCH] = spcInfo.afterCurrencyMatch; 1005 currencySpcAfterSym[CURRENCY_SPC_SURROUNDING_MATCH] = spcInfo.afterContextMatch; 1006 currencySpcAfterSym[CURRENCY_SPC_INSERT] = spcInfo.afterInsert; 1007 } 1008 1009 /** 1010 * Reads the default serializable fields, then if <code>serialVersionOnStream</code> 1011 * is less than 1, initialize <code>monetarySeparator</code> to be 1012 * the same as <code>decimalSeparator</code> and <code>exponential</code> 1013 * to be 'E'. 1014 * Finally, sets serialVersionOnStream back to the maximum allowed value so that 1015 * default serialization will work properly if this object is streamed out again. 1016 */ readObject(ObjectInputStream stream)1017 private void readObject(ObjectInputStream stream) 1018 throws IOException, ClassNotFoundException { 1019 1020 // TODO: it looks to me {dlf} that the serialization code was never updated 1021 // to handle the actual/valid ulocale fields. 1022 1023 stream.defaultReadObject(); 1024 ///CLOVER:OFF 1025 // we don't have data for these old serialized forms any more 1026 if (serialVersionOnStream < 1) { 1027 // Didn't have monetarySeparator or exponential field; 1028 // use defaults. 1029 monetarySeparator = decimalSeparator; 1030 exponential = 'E'; 1031 } 1032 if (serialVersionOnStream < 2) { 1033 padEscape = DecimalFormat.PATTERN_PAD_ESCAPE; 1034 plusSign = DecimalFormat.PATTERN_PLUS_SIGN; 1035 exponentSeparator = String.valueOf(exponential); 1036 // Although we read the exponential field on stream to create the 1037 // exponentSeparator, we don't do the reverse, since scientific 1038 // notation isn't supported by the old classes, even though the 1039 // symbol is there. 1040 } 1041 ///CLOVER:ON 1042 if (serialVersionOnStream < 3) { 1043 // Resurrected objects from old streams will have no 1044 // locale. There is no 100% fix for this. A 1045 // 90% fix is to construct a mapping of data back to 1046 // locale, perhaps a hash of all our members. This is 1047 // expensive and doesn't seem worth it. 1048 requestedLocale = Locale.getDefault(); 1049 } 1050 if (serialVersionOnStream < 4) { 1051 // use same default behavior as for versions with no Locale 1052 ulocale = ULocale.forLocale(requestedLocale); 1053 } 1054 if (serialVersionOnStream < 5) { 1055 // use the same one for groupingSeparator 1056 monetaryGroupingSeparator = groupingSeparator; 1057 } 1058 if (serialVersionOnStream < 6) { 1059 // Set null to CurrencySpacing related fields. 1060 if (currencySpcBeforeSym == null) { 1061 currencySpcBeforeSym = new String[CURRENCY_SPC_INSERT+1]; 1062 } 1063 if (currencySpcAfterSym == null) { 1064 currencySpcAfterSym = new String[CURRENCY_SPC_INSERT+1]; 1065 } 1066 initSpacingInfo(CurrencyData.CurrencySpacingInfo.DEFAULT); 1067 } 1068 if (serialVersionOnStream < 7) { 1069 // Set minusString,plusString from minusSign,plusSign 1070 if (minusString == null) { 1071 char[] minusArray = { minusSign }; 1072 minusString = new String(minusArray); 1073 } 1074 if (plusString == null) { 1075 char[] plusArray = { plusSign }; 1076 plusString = new String(plusArray); 1077 } 1078 } 1079 if (serialVersionOnStream < 8) { 1080 if (exponentMultiplicationSign == null) { 1081 exponentMultiplicationSign = "\u00D7"; 1082 } 1083 } 1084 serialVersionOnStream = currentSerialVersion; 1085 1086 // recreate 1087 currency = Currency.getInstance(intlCurrencySymbol); 1088 } 1089 1090 /** 1091 * Character used for zero. This remains only for backward compatibility 1092 * purposes. The digits array below is now used to actively store the digits. 1093 * 1094 * @serial 1095 * @see #getZeroDigit 1096 */ 1097 private char zeroDigit; 1098 1099 /** 1100 * Array of characters used for the digits 0-9 in order. 1101 * 1102 */ 1103 private char digits[]; 1104 1105 /** 1106 * Character used for thousands separator. 1107 * 1108 * @serial 1109 * @see #getGroupingSeparator 1110 */ 1111 private char groupingSeparator; 1112 1113 /** 1114 * Character used for decimal sign. 1115 * 1116 * @serial 1117 * @see #getDecimalSeparator 1118 */ 1119 private char decimalSeparator; 1120 1121 /** 1122 * Character used for mille percent sign. 1123 * 1124 * @serial 1125 * @see #getPerMill 1126 */ 1127 private char perMill; 1128 1129 /** 1130 * Character used for percent sign. 1131 * @serial 1132 * @see #getPercent 1133 */ 1134 private char percent; 1135 1136 /** 1137 * Character used for a digit in a pattern. 1138 * 1139 * @serial 1140 * @see #getDigit 1141 */ 1142 private char digit; 1143 1144 /** 1145 * Character used for a significant digit in a pattern. 1146 * 1147 * @serial 1148 * @see #getSignificantDigit 1149 */ 1150 private char sigDigit; 1151 1152 /** 1153 * Character used to separate positive and negative subpatterns 1154 * in a pattern. 1155 * 1156 * @serial 1157 * @see #getPatternSeparator 1158 */ 1159 private char patternSeparator; 1160 1161 /** 1162 * Character used to represent infinity. 1163 * @serial 1164 * @see #getInfinity 1165 */ 1166 private String infinity; 1167 1168 /** 1169 * Character used to represent NaN. 1170 * @serial 1171 * @see #getNaN 1172 */ 1173 private String NaN; 1174 1175 /** 1176 * Character used to represent minus sign. 1177 * @serial 1178 * @see #getMinusSign 1179 */ 1180 private char minusSign; 1181 1182 /** 1183 * String denoting the local currency, e.g. "$". 1184 * @serial 1185 * @see #getCurrencySymbol 1186 */ 1187 private String currencySymbol; 1188 1189 /** 1190 * International string denoting the local currency, e.g. "USD". 1191 * @serial 1192 * @see #getInternationalCurrencySymbol 1193 */ 1194 private String intlCurrencySymbol; 1195 1196 /** 1197 * The decimal separator used when formatting currency values. 1198 * @serial 1199 * @see #getMonetaryDecimalSeparator 1200 */ 1201 private char monetarySeparator; // Field new in JDK 1.1.6 1202 1203 /** 1204 * The decimal separator used when formatting currency values. 1205 * @serial 1206 * @see #getMonetaryGroupingSeparator 1207 */ 1208 private char monetaryGroupingSeparator; // Field new in JDK 1.1.6 1209 1210 /** 1211 * The character used to distinguish the exponent in a number formatted 1212 * in exponential notation, e.g. 'E' for a number such as "1.23E45". 1213 * <p> 1214 * Note that this field has been superseded by <code>exponentSeparator</code>. 1215 * It is retained for backward compatibility. 1216 * 1217 * @serial 1218 */ 1219 private char exponential; // Field new in JDK 1.1.6 1220 1221 /** 1222 * The string used to separate the mantissa from the exponent. 1223 * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4. 1224 * <p> 1225 * Note that this supersedes the <code>exponential</code> field. 1226 * 1227 * @serial 1228 * @since AlphaWorks 1229 */ 1230 private String exponentSeparator; 1231 1232 /** 1233 * The character used to indicate a padding character in a format, 1234 * e.g., '*' in a pattern such as "$*_#,##0.00". 1235 * @serial 1236 * @since AlphaWorks 1237 */ 1238 private char padEscape; 1239 1240 /** 1241 * The character used to indicate a plus sign. 1242 * @serial 1243 * @since AlphaWorks 1244 */ 1245 private char plusSign; 1246 1247 /** 1248 * The locale for which this object was constructed. Set to the 1249 * default locale for objects resurrected from old streams. 1250 * @since ICU 2.2 1251 */ 1252 private Locale requestedLocale; 1253 1254 /** 1255 * The requested ULocale. We keep the old locale for serialization compatibility. 1256 * @since ICU 3.2 1257 */ 1258 private ULocale ulocale; 1259 1260 /** 1261 * String versions of some number symbols. 1262 * @serial 1263 * @since ICU 52 1264 */ 1265 private String minusString = null; 1266 private String plusString = null; 1267 1268 /** 1269 * Exponent multiplication sign. e.g "x" 1270 * @serial 1271 * @since ICU 54 1272 */ 1273 private String exponentMultiplicationSign = null; 1274 1275 // Proclaim JDK 1.1 FCS compatibility 1276 private static final long serialVersionUID = 5772796243397350300L; 1277 1278 // The internal serial version which says which version was written 1279 // - 0 (default) for version up to JDK 1.1.5 1280 // - 1 for version from JDK 1.1.6, which includes two new fields: 1281 // monetarySeparator and exponential. 1282 // - 2 for version from AlphaWorks, which includes 3 new fields: 1283 // padEscape, exponentSeparator, and plusSign. 1284 // - 3 for ICU 2.2, which includes the locale field 1285 // - 4 for ICU 3.2, which includes the ULocale field 1286 // - 5 for ICU 3.6, which includes the monetaryGroupingSeparator field 1287 // - 6 for ICU 4.2, which includes the currencySpc* fields 1288 // - 7 for ICU 52, which includes the minusString and plusString fields 1289 // - 8 for ICU 54, which includes exponentMultiplicationSign field. 1290 private static final int currentSerialVersion = 8; 1291 1292 /** 1293 * Describes the version of <code>DecimalFormatSymbols</code> present on the stream. 1294 * Possible values are: 1295 * <ul> 1296 * <li><b>0</b> (or uninitialized): versions prior to JDK 1.1.6. 1297 * 1298 * <li><b>1</b>: Versions written by JDK 1.1.6 or later, which includes 1299 * two new fields: <code>monetarySeparator</code> and <code>exponential</code>. 1300 * <li><b>2</b>: Version for AlphaWorks. Adds padEscape, exponentSeparator, 1301 * and plusSign. 1302 * <li><b>3</b>: Version for ICU 2.2, which adds locale. 1303 * <li><b>4</b>: Version for ICU 3.2, which adds ulocale. 1304 * <li><b>5</b>: Version for ICU 3.6, which adds monetaryGroupingSeparator. 1305 * <li><b>6</b>: Version for ICU 4.2, which adds currencySpcBeforeSym and 1306 * currencySpcAfterSym. 1307 * <li><b>7</b>: Version for ICU 52, which adds minusString and plusString. 1308 * </ul> 1309 * When streaming out a <code>DecimalFormatSymbols</code>, the most recent format 1310 * (corresponding to the highest allowable <code>serialVersionOnStream</code>) 1311 * is always written. 1312 * 1313 * @serial 1314 */ 1315 private int serialVersionOnStream = currentSerialVersion; 1316 1317 /** 1318 * cache to hold the NumberElements of a Locale. 1319 */ 1320 private static final ICUCache<ULocale, String[][]> cachedLocaleData = 1321 new SimpleCache<ULocale, String[][]>(); 1322 1323 /** 1324 * 1325 */ 1326 private String currencyPattern = null; 1327 1328 // -------- BEGIN ULocale boilerplate -------- 1329 1330 /** 1331 * {@icu} Returns the locale that was used to create this object, or null. 1332 * This may may differ from the locale requested at the time of 1333 * this object's creation. For example, if an object is created 1334 * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be 1335 * drawn from <tt>en</tt> (the <i>actual</i> locale), and 1336 * <tt>en_US</tt> may be the most specific locale that exists (the 1337 * <i>valid</i> locale). 1338 * 1339 * <p>Note: The <i>actual</i> locale is returned correctly, but the <i>valid</i> 1340 * locale is not, in most cases. 1341 * @param type type of information requested, either {@link 1342 * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link 1343 * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}. 1344 * @return the information specified by <i>type</i>, or null if 1345 * this object was not constructed from locale data. 1346 * @see com.ibm.icu.util.ULocale 1347 * @see com.ibm.icu.util.ULocale#VALID_LOCALE 1348 * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE 1349 * @draft ICU 2.8 (retain) 1350 * @provisional This API might change or be removed in a future release. 1351 */ getLocale(ULocale.Type type)1352 public final ULocale getLocale(ULocale.Type type) { 1353 return type == ULocale.ACTUAL_LOCALE ? 1354 this.actualLocale : this.validLocale; 1355 } 1356 1357 /** 1358 * {@icu} Sets information about the locales that were used to create this 1359 * object. If the object was not constructed from locale data, 1360 * both arguments should be set to null. Otherwise, neither 1361 * should be null. The actual locale must be at the same level or 1362 * less specific than the valid locale. This method is intended 1363 * for use by factories or other entities that create objects of 1364 * this class. 1365 * @param valid the most specific locale containing any resource 1366 * data, or null 1367 * @param actual the locale containing data used to construct this 1368 * object, or null 1369 * @see com.ibm.icu.util.ULocale 1370 * @see com.ibm.icu.util.ULocale#VALID_LOCALE 1371 * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE 1372 */ setLocale(ULocale valid, ULocale actual)1373 final void setLocale(ULocale valid, ULocale actual) { 1374 // Change the following to an assertion later 1375 if ((valid == null) != (actual == null)) { 1376 ///CLOVER:OFF 1377 throw new IllegalArgumentException(); 1378 ///CLOVER:ON 1379 } 1380 // Another check we could do is that the actual locale is at 1381 // the same level or less specific than the valid locale. 1382 this.validLocale = valid; 1383 this.actualLocale = actual; 1384 } 1385 1386 /** 1387 * The most specific locale containing any resource data, or null. 1388 * @see com.ibm.icu.util.ULocale 1389 */ 1390 private ULocale validLocale; 1391 1392 /** 1393 * The locale containing data used to construct this object, or 1394 * null. 1395 * @see com.ibm.icu.util.ULocale 1396 */ 1397 private ULocale actualLocale; 1398 1399 // not serialized, reconstructed from intlCurrencyCode 1400 private transient Currency currency; 1401 1402 // -------- END ULocale boilerplate -------- 1403 } 1404