2 *******************************************************************************
\r
3 * Copyright (C) 1996-2010, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.text;
\r
9 import java.io.IOException;
\r
10 import java.io.ObjectInputStream;
\r
11 import java.io.Serializable;
\r
12 import java.text.ChoiceFormat;
\r
13 import java.util.Hashtable;
\r
14 import java.util.Locale;
\r
16 import com.ibm.icu.impl.CurrencyData;
\r
17 import com.ibm.icu.impl.ICUResourceBundle;
\r
18 import com.ibm.icu.impl.CurrencyData.CurrencyDisplayInfo;
\r
19 import com.ibm.icu.impl.CurrencyData.CurrencyFormatInfo;
\r
20 import com.ibm.icu.impl.CurrencyData.CurrencySpacingInfo;
\r
21 import com.ibm.icu.util.Currency;
\r
22 import com.ibm.icu.util.ULocale;
\r
23 import com.ibm.icu.util.UResourceBundle;
\r
26 * {@icuenhanced java.text.DecimalFormatSymbols}.{@icu _usage_}
\r
28 * This class represents the set of symbols (such as the decimal separator, the grouping
\r
29 * separator, and so on) needed by <code>DecimalFormat</code> to format
\r
30 * numbers. <code>DecimalFormat</code> creates for itself an instance of
\r
31 * <code>DecimalFormatSymbols</code> from its locale data. If you need to change any of
\r
32 * these symbols, you can get the <code>DecimalFormatSymbols</code> object from your
\r
33 * <code>DecimalFormat</code> and modify it.
\r
35 * @see java.util.Locale
\r
36 * @see DecimalFormat
\r
37 * @author Mark Davis
\r
41 public class DecimalFormatSymbols implements Cloneable, Serializable {
\r
43 * Creates a DecimalFormatSymbols object for the default locale.
\r
46 public DecimalFormatSymbols() {
\r
47 initialize(ULocale.getDefault());
\r
51 * Creates a DecimalFormatSymbols object for the given locale.
\r
52 * @param locale the locale
\r
55 public DecimalFormatSymbols(Locale locale) {
\r
56 initialize(ULocale.forLocale(locale));
\r
60 * {@icu} Creates a DecimalFormatSymbols object for the given locale.
\r
61 * @param locale the locale
\r
64 public DecimalFormatSymbols(ULocale locale) {
\r
69 * Returns a DecimalFormatSymbols instance for the default locale.
\r
71 * <p><strong>Note:</strong> Unlike
\r
72 * <code>java.text.DecimalFormatSymbols#getInstance</code>, this method simply returns
\r
73 * <code>new com.ibm.icu.text.DecimalFormatSymbols()</code>. ICU currently does not
\r
74 * support <code>DecimalFormatSymbolsProvider</code>, which was introduced in Java 6.
\r
76 * @return A DecimalFormatSymbols instance.
\r
79 public static DecimalFormatSymbols getInstance() {
\r
80 return new DecimalFormatSymbols();
\r
84 * Returns a DecimalFormatSymbols instance for the given locale.
\r
86 * <p><strong>Note:</strong> Unlike
\r
87 * <code>java.text.DecimalFormatSymbols#getInstance</code>, this method simply returns
\r
88 * <code>new com.ibm.icu.text.DecimalFormatSymbols(locale)</code>. ICU currently does
\r
89 * not support <code>DecimalFormatSymbolsProvider</code>, which was introduced in Java
\r
92 * @param locale the locale.
\r
93 * @return A DecimalFormatSymbols instance.
\r
96 public static DecimalFormatSymbols getInstance(Locale locale) {
\r
97 return new DecimalFormatSymbols(locale);
\r
101 * Returns a DecimalFormatSymbols instance for the given locale.
\r
103 * <p><strong>Note:</strong> Unlike
\r
104 * <code>java.text.DecimalFormatSymbols#getInstance</code>, this method simply returns
\r
105 * <code>new com.ibm.icu.text.DecimalFormatSymbols(locale)</code>. ICU currently does
\r
106 * not support <code>DecimalFormatSymbolsProvider</code>, which was introduced in Java
\r
109 * @param locale the locale.
\r
110 * @return A DecimalFormatSymbols instance.
\r
113 public static DecimalFormatSymbols getInstance(ULocale locale) {
\r
114 return new DecimalFormatSymbols(locale);
\r
118 * Returns an array of all locales for which the <code>getInstance</code> methods of
\r
119 * this class can return localized instances.
\r
121 * <p><strong>Note:</strong> Unlike
\r
122 * <code>java.text.DecimalFormatSymbols#getAvailableLocales</code>, this method simply
\r
123 * returns the array of <code>Locale</code>s available for this class. ICU currently
\r
124 * does not support <code>DecimalFormatSymbolsProvider</code>, which was introduced in
\r
127 * @return An array of <code>Locale</code>s for which localized
\r
128 * <code>DecimalFormatSymbols</code> instances are available.
\r
131 public static Locale[] getAvailableLocales() {
\r
132 return ICUResourceBundle.getAvailableLocales();
\r
136 * {@icu} Returns an array of all locales for which the <code>getInstance</code>
\r
137 * methods of this class can return localized instances.
\r
139 * <p><strong>Note:</strong> Unlike
\r
140 * <code>java.text.DecimalFormatSymbols#getAvailableLocales</code>, this method simply
\r
141 * returns the array of <code>ULocale</code>s available in this class. ICU currently
\r
142 * does not support <code>DecimalFormatSymbolsProvider</code>, which was introduced in
\r
145 * @return An array of <code>ULocale</code>s for which localized
\r
146 * <code>DecimalFormatSymbols</code> instances are available.
\r
147 * @stable ICU 3.8 (retain)
\r
148 * @provisional This API might change or be removed in a future release.
\r
150 public static ULocale[] getAvailableULocales() {
\r
151 return ICUResourceBundle.getAvailableULocales();
\r
156 * Returns the character used for zero. Different for Arabic, etc.
\r
157 * @return the character
\r
160 public char getZeroDigit() {
\r
165 * Sets the character used for zero.
\r
166 * @param zeroDigit the zero character.
\r
169 public void setZeroDigit(char zeroDigit) {
\r
170 this.zeroDigit = zeroDigit;
\r
174 * Returns the character used to represent a significant digit in a pattern.
\r
175 * @return the significant digit pattern character
\r
178 public char getSignificantDigit() {
\r
183 * Sets the character used to represent a significant digit in a pattern.
\r
184 * @param sigDigit the significant digit pattern character
\r
187 public void setSignificantDigit(char sigDigit) {
\r
188 this.sigDigit = sigDigit;
\r
192 * Returns the character used for thousands separator. Different for French, etc.
\r
193 * @return the thousands character
\r
196 public char getGroupingSeparator() {
\r
197 return groupingSeparator;
\r
201 * Sets the character used for thousands separator. Different for French, etc.
\r
202 * @param groupingSeparator the thousands character
\r
205 public void setGroupingSeparator(char groupingSeparator) {
\r
206 this.groupingSeparator = groupingSeparator;
\r
210 * Returns the character used for decimal sign. Different for French, etc.
\r
211 * @return the decimal character
\r
214 public char getDecimalSeparator() {
\r
215 return decimalSeparator;
\r
219 * Sets the character used for decimal sign. Different for French, etc.
\r
220 * @param decimalSeparator the decimal character
\r
223 public void setDecimalSeparator(char decimalSeparator) {
\r
224 this.decimalSeparator = decimalSeparator;
\r
228 * Returns the character used for mille percent sign. Different for Arabic, etc.
\r
229 * @return the mille percent character
\r
232 public char getPerMill() {
\r
237 * Sets the character used for mille percent sign. Different for Arabic, etc.
\r
238 * @param perMill the mille percent character
\r
241 public void setPerMill(char perMill) {
\r
242 this.perMill = perMill;
\r
246 * Returns the character used for percent sign. Different for Arabic, etc.
\r
247 * @return the percent character
\r
250 public char getPercent() {
\r
255 * Sets the character used for percent sign. Different for Arabic, etc.
\r
256 * @param percent the percent character
\r
259 public void setPercent(char percent) {
\r
260 this.percent = percent;
\r
264 * Returns the character used for a digit in a pattern.
\r
265 * @return the digit pattern character
\r
268 public char getDigit() {
\r
273 * Sets the character used for a digit in a pattern.
\r
274 * @param digit the digit pattern character
\r
277 public void setDigit(char digit) {
\r
278 this.digit = digit;
\r
282 * Returns the character used to separate positive and negative subpatterns
\r
284 * @return the pattern separator character
\r
287 public char getPatternSeparator() {
\r
288 return patternSeparator;
\r
292 * Sets the character used to separate positive and negative subpatterns
\r
294 * @param patternSeparator the pattern separator character
\r
297 public void setPatternSeparator(char patternSeparator) {
\r
298 this.patternSeparator = patternSeparator;
\r
302 * Returns the String used to represent infinity. Almost always left
\r
304 * @return the Infinity string
\r
307 //Bug 4194173 [Richard/GCL]
\r
309 public String getInfinity() {
\r
314 * Sets the String used to represent infinity. Almost always left
\r
316 * @param infinity the Infinity String
\r
319 public void setInfinity(String infinity) {
\r
320 this.infinity = infinity;
\r
324 * Returns the String used to represent NaN. Almost always left
\r
326 * @return the NaN String
\r
329 //Bug 4194173 [Richard/GCL]
\r
330 public String getNaN() {
\r
335 * Sets the String used to represent NaN. Almost always left
\r
337 * @param NaN the NaN String
\r
340 public void setNaN(String NaN) {
\r
345 * Returns the character used to represent minus sign. If no explicit
\r
346 * negative format is specified, one is formed by prefixing
\r
347 * minusSign to the positive format.
\r
348 * @return the minus sign character
\r
351 public char getMinusSign() {
\r
356 * Sets the character used to represent minus sign. If no explicit
\r
357 * negative format is specified, one is formed by prefixing
\r
358 * minusSign to the positive format.
\r
359 * @param minusSign the minus sign character
\r
362 public void setMinusSign(char minusSign) {
\r
363 this.minusSign = minusSign;
\r
367 * Returns the string denoting the local currency.
\r
368 * @return the local currency String.
\r
371 public String getCurrencySymbol() {
\r
372 return currencySymbol;
\r
376 * Sets the string denoting the local currency.
\r
377 * @param currency the local currency String.
\r
380 public void setCurrencySymbol(String currency) {
\r
381 currencySymbol = currency;
\r
385 * Returns the international string denoting the local currency.
\r
386 * @return the international string denoting the local currency
\r
389 public String getInternationalCurrencySymbol() {
\r
390 return intlCurrencySymbol;
\r
394 * Sets the international string denoting the local currency.
\r
395 * @param currency the international string denoting the local currency.
\r
398 public void setInternationalCurrencySymbol(String currency) {
\r
399 intlCurrencySymbol = currency;
\r
403 * Returns the currency symbol, for JDK 1.4 compatibility only.
\r
404 * ICU clients should use the Currency API directly.
\r
405 * @return the currency used, or null
\r
408 public Currency getCurrency() {
\r
413 * Sets the currency.
\r
415 * <p><strong>Note:</strong> ICU does not use the DecimalFormatSymbols for the currency
\r
416 * any more. This API is present for API compatibility only.
\r
418 * <p>This also sets the currency symbol attribute to the currency's symbol
\r
419 * in the DecimalFormatSymbols' locale, and the international currency
\r
420 * symbol attribute to the currency's ISO 4217 currency code.
\r
422 * @param currency the new currency to be used
\r
423 * @throws NullPointerException if <code>currency</code> is null
\r
424 * @see #setCurrencySymbol
\r
425 * @see #setInternationalCurrencySymbol
\r
429 public void setCurrency(Currency currency) {
\r
430 if (currency == null) {
\r
431 throw new NullPointerException();
\r
433 this.currency = currency;
\r
434 intlCurrencySymbol = currency.getCurrencyCode();
\r
435 currencySymbol = currency.getSymbol(requestedLocale);
\r
439 * Returns the monetary decimal separator.
\r
440 * @return the monetary decimal separator character
\r
443 public char getMonetaryDecimalSeparator() {
\r
444 return monetarySeparator;
\r
448 * {@icu} Returns the monetary grouping separator.
\r
449 * @return the monetary grouping separator character
\r
452 public char getMonetaryGroupingSeparator() {
\r
453 return monetaryGroupingSeparator;
\r
457 * Internal API for NumberFormat
\r
458 * @return String currency pattern string
\r
460 String getCurrencyPattern() {
\r
461 return currencyPattern;
\r
465 * Sets the monetary decimal separator.
\r
466 * @param sep the monetary decimal separator character
\r
469 public void setMonetaryDecimalSeparator(char sep) {
\r
470 monetarySeparator = sep;
\r
474 * Sets the monetary decimal separator.
\r
475 * @param sep the monetary decimal separator character
\r
478 public void setMonetaryGroupingSeparator(char sep) {
\r
479 monetaryGroupingSeparator = sep;
\r
483 * {@icu} Returns the string used to separate the mantissa from the exponent.
\r
484 * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
\r
485 * @return the localized exponent symbol, used in localized patterns
\r
486 * and formatted strings
\r
487 * @see #setExponentSeparator
\r
490 public String getExponentSeparator() {
\r
491 return exponentSeparator;
\r
495 * {@icu} Sets the string used to separate the mantissa from the exponent.
\r
496 * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
\r
497 * @param exp the localized exponent symbol, used in localized patterns
\r
498 * and formatted strings
\r
499 * @see #getExponentSeparator
\r
502 public void setExponentSeparator(String exp) {
\r
503 exponentSeparator = exp;
\r
507 * {@icu} Returns the localized plus sign.
\r
508 * @return the plus sign, used in localized patterns and formatted
\r
510 * @see #setPlusSign
\r
511 * @see #setMinusSign
\r
512 * @see #getMinusSign
\r
515 public char getPlusSign() {
\r
520 * {@icu} Sets the localized plus sign.
\r
521 * @param plus the plus sign, used in localized patterns and formatted
\r
523 * @see #getPlusSign
\r
524 * @see #setMinusSign
\r
525 * @see #getMinusSign
\r
528 public void setPlusSign(char plus) {
\r
533 * {@icu} Returns the character used to pad numbers out to a specified width. This is
\r
534 * not the pad character itself; rather, it is the special pattern character
\r
535 * <em>preceding</em> the pad character. In the pattern "*_#,##0", '*' is the pad
\r
536 * escape, and '_' is the pad character.
\r
537 * @return the character
\r
538 * @see #setPadEscape
\r
539 * @see DecimalFormat#getFormatWidth
\r
540 * @see DecimalFormat#getPadPosition
\r
541 * @see DecimalFormat#getPadCharacter
\r
544 public char getPadEscape() {
\r
549 * {@icu} Sets the character used to pad numbers out to a specified width. This is not
\r
550 * the pad character itself; rather, it is the special pattern character
\r
551 * <em>preceding</em> the pad character. In the pattern "*_#,##0", '*' is the pad
\r
552 * escape, and '_' is the pad character.
\r
553 * @see #getPadEscape
\r
554 * @see DecimalFormat#setFormatWidth
\r
555 * @see DecimalFormat#setPadPosition
\r
556 * @see DecimalFormat#setPadCharacter
\r
559 public void setPadEscape(char c) {
\r
564 * {@icu} Indicates the currency match pattern used in {@link #getPatternForCurrencySpacing}.
\r
567 public static final int CURRENCY_SPC_CURRENCY_MATCH = 0;
\r
570 * {@icu} Indicates the surrounding match pattern used in {@link
\r
571 * #getPatternForCurrencySpacing}.
\r
574 public static final int CURRENCY_SPC_SURROUNDING_MATCH = 1;
\r
577 * {@icu} Indicates the insertion value used in {@link #getPatternForCurrencySpacing}.
\r
580 public static final int CURRENCY_SPC_INSERT = 2;
\r
582 private String[] currencySpcBeforeSym;
\r
583 private String[] currencySpcAfterSym;
\r
586 * {@icu} Returns the desired currency spacing value. Original values come from ICU's
\r
587 * CLDR data based on the locale provided during construction, and can be null. These
\r
588 * values govern what and when text is inserted between a currency code/name/symbol
\r
589 * and the currency amount when formatting money.
\r
591 * <p>For more information, see <a href="http://www.unicode.org/reports/tr35/#Currencies"
\r
592 * >UTS#35 section 5.10.2</a>.
\r
594 * <p><strong>Note:</strong> ICU4J does not currently use this information.
\r
596 * @param itemType one of CURRENCY_SPC_CURRENCY_MATCH, CURRENCY_SPC_SURROUNDING_MATCH
\r
597 * or CURRENCY_SPC_INSERT
\r
598 * @param beforeCurrency true to get the <code>beforeCurrency</code> values, false
\r
599 * to get the <code>afterCurrency</code> values.
\r
600 * @return the value, or null.
\r
601 * @see #setPatternForCurrencySpacing(int, boolean, String)
\r
604 public String getPatternForCurrencySpacing(int itemType, boolean beforeCurrency) {
\r
605 if (itemType < CURRENCY_SPC_CURRENCY_MATCH ||
\r
606 itemType > CURRENCY_SPC_INSERT ) {
\r
607 throw new IllegalArgumentException("unknown currency spacing: " + itemType);
\r
609 if (beforeCurrency) {
\r
610 return currencySpcBeforeSym[itemType];
\r
612 return currencySpcAfterSym[itemType];
\r
616 * {@icu} Sets the indicated currency spacing pattern or value. See {@link
\r
617 * #getPatternForCurrencySpacing} for more information.
\r
619 * <p>Values for currency match and surrounding match must be {@link
\r
620 * com.ibm.icu.text.UnicodeSet} patterns. Values for insert can be any string.
\r
622 * <p><strong>Note:</strong> ICU4J does not currently use this information.
\r
624 * @param itemType one of CURRENCY_SPC_CURRENCY_MATCH, CURRENCY_SPC_SURROUNDING_MATCH
\r
625 * or CURRENCY_SPC_INSERT
\r
626 * @param beforeCurrency true if the pattern is for before the currency symbol.
\r
627 * false if the pattern is for after it.
\r
628 * @param pattern string to override current setting; can be null.
\r
629 * @see #getPatternForCurrencySpacing(int, boolean)
\r
632 public void setPatternForCurrencySpacing(int itemType, boolean beforeCurrency, String pattern) {
\r
633 if (itemType < CURRENCY_SPC_CURRENCY_MATCH ||
\r
634 itemType > CURRENCY_SPC_INSERT ) {
\r
635 throw new IllegalArgumentException("unknown currency spacing: " + itemType);
\r
637 if (beforeCurrency) {
\r
638 currencySpcBeforeSym[itemType] = pattern;
\r
640 currencySpcAfterSym[itemType] = pattern;
\r
645 * Returns the locale for which this object was constructed.
\r
646 * @return the locale for which this object was constructed
\r
649 public Locale getLocale() {
\r
650 return requestedLocale;
\r
654 * Returns the locale for which this object was constructed.
\r
655 * @return the locale for which this object was constructed
\r
658 public ULocale getULocale() {
\r
666 public Object clone() {
\r
668 return (DecimalFormatSymbols) super.clone();
\r
669 // other fields are bit-copied
\r
670 } catch (CloneNotSupportedException e) {
\r
672 throw new IllegalStateException();
\r
681 public boolean equals(Object obj) {
\r
682 if (obj == null) return false;
\r
683 if (this == obj) return true;
\r
684 DecimalFormatSymbols other = (DecimalFormatSymbols) obj;
\r
685 for (int i = 0; i <= CURRENCY_SPC_INSERT; i++) {
\r
686 if (!currencySpcBeforeSym[i].equals(other.currencySpcBeforeSym[i])) {
\r
689 if (!currencySpcAfterSym[i].equals(other.currencySpcAfterSym[i])) {
\r
694 return (zeroDigit == other.zeroDigit &&
\r
695 groupingSeparator == other.groupingSeparator &&
\r
696 decimalSeparator == other.decimalSeparator &&
\r
697 percent == other.percent &&
\r
698 perMill == other.perMill &&
\r
699 digit == other.digit &&
\r
700 minusSign == other.minusSign &&
\r
701 patternSeparator == other.patternSeparator &&
\r
702 infinity.equals(other.infinity) &&
\r
703 NaN.equals(other.NaN) &&
\r
704 currencySymbol.equals(other.currencySymbol) &&
\r
705 intlCurrencySymbol.equals(other.intlCurrencySymbol) &&
\r
706 padEscape == other.padEscape &&
\r
707 plusSign == other.plusSign &&
\r
708 exponentSeparator.equals(other.exponentSeparator) &&
\r
709 monetarySeparator == other.monetarySeparator);
\r
716 public int hashCode() {
\r
717 int result = zeroDigit;
\r
718 result = result * 37 + groupingSeparator;
\r
719 result = result * 37 + decimalSeparator;
\r
724 * Initializes the symbols from the LocaleElements resource bundle.
\r
725 * Note: The organization of LocaleElements badly needs to be
\r
728 private void initialize( ULocale locale ) {
\r
729 this.requestedLocale = locale.toLocale();
\r
730 this.ulocale = locale;
\r
732 /* try the cache first */
\r
733 String[][] data = cachedLocaleData.get(locale);
\r
734 String[] numberElements;
\r
735 if (data == null) { /* cache miss */
\r
736 data = new String[1][];
\r
737 ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.
\r
738 getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale);
\r
739 data[0] = rb.getStringArray("NumberElements");
\r
741 cachedLocaleData.put(locale, data);
\r
743 numberElements = data[0];
\r
745 ICUResourceBundle r = (ICUResourceBundle)UResourceBundle.
\r
746 getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale);
\r
748 // TODO: Determine actual and valid locale correctly.
\r
749 ULocale uloc = r.getULocale();
\r
750 setLocale(uloc, uloc);
\r
752 decimalSeparator = numberElements[0].charAt(0);
\r
753 groupingSeparator = numberElements[1].charAt(0);
\r
754 patternSeparator = numberElements[2].charAt(0);
\r
755 percent = numberElements[3].charAt(0);
\r
756 zeroDigit = numberElements[4].charAt(0); //different for Arabic,etc.
\r
757 digit = numberElements[5].charAt(0);
\r
758 minusSign = numberElements[6].charAt(0);
\r
760 exponentSeparator = numberElements[7];
\r
761 perMill = numberElements[8].charAt(0);
\r
762 infinity = numberElements[9];
\r
763 NaN = numberElements[10];
\r
765 plusSign =numberElements[11].charAt(0);
\r
766 padEscape = DecimalFormat.PATTERN_PAD_ESCAPE;
\r
767 sigDigit = DecimalFormat.PATTERN_SIGNIFICANT_DIGIT;
\r
769 // Attempt to set the zero digit based on the numbering system for the locale requested
\r
770 NumberingSystem ns = NumberingSystem.getInstance(locale);
\r
771 if ( ns != null && ns.getRadix() == 10 && !ns.isAlgorithmic()) {
\r
772 zeroDigit = ns.getDescription().charAt(0);
\r
775 CurrencyDisplayInfo info = CurrencyData.provider.getInstance(locale, true);
\r
777 // Obtain currency data from the currency API. This is strictly
\r
778 // for backward compatibility; we don't use DecimalFormatSymbols
\r
779 // for currency data anymore.
\r
780 String currname = null;
\r
781 currency = Currency.getInstance(locale);
\r
782 if (currency != null) {
\r
783 intlCurrencySymbol = currency.getCurrencyCode();
\r
784 boolean[] isChoiceFormat = new boolean[1];
\r
785 currname = currency.getName(locale, Currency.SYMBOL_NAME, isChoiceFormat);
\r
786 // If this is a ChoiceFormat currency, then format an
\r
787 // arbitrary value; pick something != 1; more common.
\r
788 currencySymbol = isChoiceFormat[0]
\r
789 ? new ChoiceFormat(currname).format(2.0)
\r
792 intlCurrencySymbol = "XXX";
\r
793 currencySymbol = "\u00A4"; // 'OX' currency symbol
\r
797 // Get currency pattern/separator overrides if they exist.
\r
798 monetarySeparator = decimalSeparator;
\r
799 monetaryGroupingSeparator = groupingSeparator;
\r
800 Currency curr = Currency.getInstance(locale);
\r
802 CurrencyFormatInfo fmtInfo = info.getFormatInfo(curr.getCurrencyCode());
\r
803 if (fmtInfo != null) {
\r
804 currencyPattern = fmtInfo.currencyPattern;
\r
805 monetarySeparator = fmtInfo.monetarySeparator;
\r
806 monetaryGroupingSeparator = fmtInfo.monetaryGroupingSeparator;
\r
810 // Get currency spacing data.
\r
811 currencySpcBeforeSym = new String[3];
\r
812 currencySpcAfterSym = new String[3];
\r
813 initSpacingInfo(info.getSpacingInfo());
\r
816 private void initSpacingInfo(CurrencySpacingInfo spcInfo) {
\r
817 currencySpcBeforeSym[CURRENCY_SPC_CURRENCY_MATCH] = spcInfo.beforeCurrencyMatch;
\r
818 currencySpcBeforeSym[CURRENCY_SPC_SURROUNDING_MATCH] = spcInfo.beforeContextMatch;
\r
819 currencySpcBeforeSym[CURRENCY_SPC_INSERT] = spcInfo.beforeInsert;
\r
820 currencySpcAfterSym[CURRENCY_SPC_CURRENCY_MATCH] = spcInfo.afterCurrencyMatch;
\r
821 currencySpcAfterSym[CURRENCY_SPC_SURROUNDING_MATCH] = spcInfo.afterContextMatch;
\r
822 currencySpcAfterSym[CURRENCY_SPC_INSERT] = spcInfo.afterInsert;
\r
826 * Reads the default serializable fields, then if <code>serialVersionOnStream</code>
\r
827 * is less than 1, initialize <code>monetarySeparator</code> to be
\r
828 * the same as <code>decimalSeparator</code> and <code>exponential</code>
\r
830 * Finally, sets serialVersionOnStream back to the maximum allowed value so that
\r
831 * default serialization will work properly if this object is streamed out again.
\r
833 private void readObject(ObjectInputStream stream)
\r
834 throws IOException, ClassNotFoundException {
\r
836 // TODO: it looks to me {dlf} that the serialization code was never updated
\r
837 // to handle the actual/valid ulocale fields.
\r
839 stream.defaultReadObject();
\r
841 // we don't have data for these old serialized forms any more
\r
842 if (serialVersionOnStream < 1) {
\r
843 // Didn't have monetarySeparator or exponential field;
\r
845 monetarySeparator = decimalSeparator;
\r
848 if (serialVersionOnStream < 2) {
\r
849 padEscape = DecimalFormat.PATTERN_PAD_ESCAPE;
\r
850 plusSign = DecimalFormat.PATTERN_PLUS_SIGN;
\r
851 exponentSeparator = String.valueOf(exponential);
\r
852 // Although we read the exponential field on stream to create the
\r
853 // exponentSeparator, we don't do the reverse, since scientific
\r
854 // notation isn't supported by the old classes, even though the
\r
855 // symbol is there.
\r
858 if (serialVersionOnStream < 3) {
\r
859 // Resurrected objects from old streams will have no
\r
860 // locale. There is no 100% fix for this. A
\r
861 // 90% fix is to construct a mapping of data back to
\r
862 // locale, perhaps a hash of all our members. This is
\r
863 // expensive and doesn't seem worth it.
\r
864 requestedLocale = Locale.getDefault();
\r
866 if (serialVersionOnStream < 4) {
\r
867 // use same default behavior as for versions with no Locale
\r
868 ulocale = ULocale.forLocale(requestedLocale);
\r
870 if (serialVersionOnStream < 5) {
\r
871 // use the same one for groupingSeparator
\r
872 monetaryGroupingSeparator = groupingSeparator;
\r
874 if (serialVersionOnStream < 6) {
\r
875 // Set null to CurrencySpacing related fields.
\r
876 if (currencySpcBeforeSym == null) {
\r
877 currencySpcBeforeSym = new String[CURRENCY_SPC_INSERT+1];
\r
879 if (currencySpcAfterSym == null) {
\r
880 currencySpcAfterSym = new String[CURRENCY_SPC_INSERT+1];
\r
882 initSpacingInfo(CurrencyData.CurrencySpacingInfo.DEFAULT);
\r
884 serialVersionOnStream = currentSerialVersion;
\r
887 currency = Currency.getInstance(intlCurrencySymbol);
\r
891 * Character used for zero.
\r
894 * @see #getZeroDigit
\r
896 private char zeroDigit;
\r
899 * Character used for thousands separator.
\r
902 * @see #getGroupingSeparator
\r
904 private char groupingSeparator;
\r
907 * Character used for decimal sign.
\r
910 * @see #getDecimalSeparator
\r
912 private char decimalSeparator;
\r
915 * Character used for mille percent sign.
\r
920 private char perMill;
\r
923 * Character used for percent sign.
\r
927 private char percent;
\r
930 * Character used for a digit in a pattern.
\r
935 private char digit;
\r
938 * Character used for a significant digit in a pattern.
\r
941 * @see #getSignificantDigit
\r
943 private char sigDigit;
\r
946 * Character used to separate positive and negative subpatterns
\r
950 * @see #getPatternSeparator
\r
952 private char patternSeparator;
\r
955 * Character used to represent infinity.
\r
957 * @see #getInfinity
\r
959 private String infinity;
\r
962 * Character used to represent NaN.
\r
966 private String NaN;
\r
969 * Character used to represent minus sign.
\r
971 * @see #getMinusSign
\r
973 private char minusSign;
\r
976 * String denoting the local currency, e.g. "$".
\r
978 * @see #getCurrencySymbol
\r
980 private String currencySymbol;
\r
983 * International string denoting the local currency, e.g. "USD".
\r
985 * @see #getInternationalCurrencySymbol
\r
987 private String intlCurrencySymbol;
\r
990 * The decimal separator used when formatting currency values.
\r
992 * @see #getMonetaryDecimalSeparator
\r
994 private char monetarySeparator; // Field new in JDK 1.1.6
\r
997 * The decimal separator used when formatting currency values.
\r
999 * @see #getMonetaryGroupingSeparator
\r
1001 private char monetaryGroupingSeparator; // Field new in JDK 1.1.6
\r
1004 * The character used to distinguish the exponent in a number formatted
\r
1005 * in exponential notation, e.g. 'E' for a number such as "1.23E45".
\r
1007 * Note that this field has been superseded by <code>exponentSeparator</code>.
\r
1008 * It is retained for backward compatibility.
\r
1012 private char exponential; // Field new in JDK 1.1.6
\r
1015 * The string used to separate the mantissa from the exponent.
\r
1016 * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
\r
1018 * Note that this supersedes the <code>exponential</code> field.
\r
1021 * @since AlphaWorks
\r
1023 private String exponentSeparator;
\r
1026 * The character used to indicate a padding character in a format,
\r
1027 * e.g., '*' in a pattern such as "$*_#,##0.00".
\r
1029 * @since AlphaWorks
\r
1031 private char padEscape;
\r
1034 * The character used to indicate a plus sign.
\r
1036 * @since AlphaWorks
\r
1038 private char plusSign;
\r
1041 * The locale for which this object was constructed. Set to the
\r
1042 * default locale for objects resurrected from old streams.
\r
1045 private Locale requestedLocale;
\r
1048 * The requested ULocale. We keep the old locale for serialization compatibility.
\r
1051 private ULocale ulocale;
\r
1053 // Proclaim JDK 1.1 FCS compatibility
\r
1054 private static final long serialVersionUID = 5772796243397350300L;
\r
1056 // The internal serial version which says which version was written
\r
1057 // - 0 (default) for version up to JDK 1.1.5
\r
1058 // - 1 for version from JDK 1.1.6, which includes two new fields:
\r
1059 // monetarySeparator and exponential.
\r
1060 // - 2 for version from AlphaWorks, which includes 3 new fields:
\r
1061 // padEscape, exponentSeparator, and plusSign.
\r
1062 // - 3 for ICU 2.2, which includes the locale field
\r
1063 // - 4 for ICU 3.2, which includes the ULocale field
\r
1064 // - 5 for ICU 3.6, which includes the monetaryGroupingSeparator field
\r
1065 // - 6 for ICU 4.2, which includes the currencySpc* fields
\r
1066 private static final int currentSerialVersion = 6;
\r
1069 * Describes the version of <code>DecimalFormatSymbols</code> present on the stream.
\r
1070 * Possible values are:
\r
1072 * <li><b>0</b> (or uninitialized): versions prior to JDK 1.1.6.
\r
1074 * <li><b>1</b>: Versions written by JDK 1.1.6 or later, which includes
\r
1075 * two new fields: <code>monetarySeparator</code> and <code>exponential</code>.
\r
1076 * <li><b>2</b>: Version for AlphaWorks. Adds padEscape, exponentSeparator,
\r
1078 * <li><b>3</b>: Version for ICU 2.2, which adds locale.
\r
1079 * <li><b>4</b>: Version for ICU 3.2, which adds ulocale.
\r
1080 * <li><b>5</b>: Version for ICU 3.6, which adds monetaryGroupingSeparator.
\r
1081 * <li><b>6</b>: Version for ICU 4.2, which adds currencySpcBeforeSym and
\r
1082 * currencySpcAfterSym.
\r
1084 * When streaming out a <code>DecimalFormatSymbols</code>, the most recent format
\r
1085 * (corresponding to the highest allowable <code>serialVersionOnStream</code>)
\r
1086 * is always written.
\r
1090 private int serialVersionOnStream = currentSerialVersion;
\r
1093 * cache to hold the NumberElements of a Locale.
\r
1095 private static final Hashtable<ULocale, String[][]> cachedLocaleData =
\r
1096 new Hashtable<ULocale, String[][]>(3);
\r
1101 private String currencyPattern = null;
\r
1103 // -------- BEGIN ULocale boilerplate --------
\r
1106 * {@icu} Returns the locale that was used to create this object, or null.
\r
1107 * This may may differ from the locale requested at the time of
\r
1108 * this object's creation. For example, if an object is created
\r
1109 * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
\r
1110 * drawn from <tt>en</tt> (the <i>actual</i> locale), and
\r
1111 * <tt>en_US</tt> may be the most specific locale that exists (the
\r
1112 * <i>valid</i> locale).
\r
1114 * <p>Note: The <i>actual</i> locale is returned correctly, but the <i>valid</i>
\r
1115 * locale is not, in most cases.
\r
1116 * @param type type of information requested, either {@link
\r
1117 * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
\r
1118 * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
\r
1119 * @return the information specified by <i>type</i>, or null if
\r
1120 * this object was not constructed from locale data.
\r
1121 * @see com.ibm.icu.util.ULocale
\r
1122 * @see com.ibm.icu.util.ULocale#VALID_LOCALE
\r
1123 * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
\r
1124 * @draft ICU 2.8 (retain)
\r
1125 * @provisional This API might change or be removed in a future release.
\r
1127 public final ULocale getLocale(ULocale.Type type) {
\r
1128 return type == ULocale.ACTUAL_LOCALE ?
\r
1129 this.actualLocale : this.validLocale;
\r
1133 * {@icu} Sets information about the locales that were used to create this
\r
1134 * object. If the object was not constructed from locale data,
\r
1135 * both arguments should be set to null. Otherwise, neither
\r
1136 * should be null. The actual locale must be at the same level or
\r
1137 * less specific than the valid locale. This method is intended
\r
1138 * for use by factories or other entities that create objects of
\r
1140 * @param valid the most specific locale containing any resource
\r
1142 * @param actual the locale containing data used to construct this
\r
1144 * @see com.ibm.icu.util.ULocale
\r
1145 * @see com.ibm.icu.util.ULocale#VALID_LOCALE
\r
1146 * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
\r
1148 final void setLocale(ULocale valid, ULocale actual) {
\r
1149 // Change the following to an assertion later
\r
1150 if ((valid == null) != (actual == null)) {
\r
1152 throw new IllegalArgumentException();
\r
1155 // Another check we could do is that the actual locale is at
\r
1156 // the same level or less specific than the valid locale.
\r
1157 this.validLocale = valid;
\r
1158 this.actualLocale = actual;
\r
1162 * The most specific locale containing any resource data, or null.
\r
1163 * @see com.ibm.icu.util.ULocale
\r
1165 private ULocale validLocale;
\r
1168 * The locale containing data used to construct this object, or
\r
1170 * @see com.ibm.icu.util.ULocale
\r
1172 private ULocale actualLocale;
\r
1174 // not serialized, reconstructed from intlCurrencyCode
\r
1175 private transient Currency currency;
\r
1177 // -------- END ULocale boilerplate --------
\r