]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/classes/core/src/com/ibm/icu/text/DecimalFormatSymbols.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / classes / core / src / com / ibm / icu / text / DecimalFormatSymbols.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 1996-2010, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.text;\r
8 \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
15 \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
24 \r
25 /**\r
26  * {@icuenhanced java.text.DecimalFormatSymbols}.{@icu _usage_}\r
27  *\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
34  *\r
35  * @see          java.util.Locale\r
36  * @see          DecimalFormat\r
37  * @author       Mark Davis\r
38  * @author       Alan Liu\r
39  * @stable ICU 2.0\r
40  */\r
41 public class DecimalFormatSymbols implements Cloneable, Serializable {\r
42     /**\r
43      * Creates a DecimalFormatSymbols object for the default locale.\r
44      * @stable ICU 2.0\r
45      */\r
46     public DecimalFormatSymbols() {\r
47         initialize(ULocale.getDefault());\r
48     }\r
49 \r
50     /**\r
51      * Creates a DecimalFormatSymbols object for the given locale.\r
52      * @param locale the locale\r
53      * @stable ICU 2.0\r
54      */\r
55     public DecimalFormatSymbols(Locale locale) {\r
56         initialize(ULocale.forLocale(locale));\r
57     }\r
58 \r
59     /**\r
60      * {@icu} Creates a DecimalFormatSymbols object for the given locale.\r
61      * @param locale the locale\r
62      * @stable ICU 3.2\r
63      */\r
64     public DecimalFormatSymbols(ULocale locale) {\r
65         initialize(locale);\r
66     }\r
67 \r
68     /**\r
69      * Returns a DecimalFormatSymbols instance for the default locale.\r
70      *\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
75      *\r
76      * @return A DecimalFormatSymbols instance.\r
77      * @stable ICU 3.8\r
78      */\r
79     public static DecimalFormatSymbols getInstance() {\r
80         return new DecimalFormatSymbols();\r
81     }\r
82 \r
83     /**\r
84      * Returns a DecimalFormatSymbols instance for the given locale.\r
85      *\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
90      * 6.\r
91      *\r
92      * @param locale the locale.\r
93      * @return A DecimalFormatSymbols instance.\r
94      * @stable ICU 3.8\r
95      */\r
96     public static DecimalFormatSymbols getInstance(Locale locale) {\r
97         return new DecimalFormatSymbols(locale);\r
98     }\r
99 \r
100     /**\r
101      * Returns a DecimalFormatSymbols instance for the given locale.\r
102      *\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
107      * 6.\r
108      *\r
109      * @param locale the locale.\r
110      * @return A DecimalFormatSymbols instance.\r
111      * @stable ICU 3.8\r
112      */\r
113     public static DecimalFormatSymbols getInstance(ULocale locale) {\r
114         return new DecimalFormatSymbols(locale);\r
115     }\r
116 \r
117     /**\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
120      *\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
125      * Java 6.\r
126      *\r
127      * @return An array of <code>Locale</code>s for which localized\r
128      * <code>DecimalFormatSymbols</code> instances are available.\r
129      * @stable ICU 3.8\r
130      */\r
131     public static Locale[] getAvailableLocales() {\r
132         return ICUResourceBundle.getAvailableLocales();\r
133     }\r
134 \r
135     /**\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
138      *\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
143      * Java 6.\r
144      *\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
149      */\r
150     public static ULocale[] getAvailableULocales() {\r
151         return ICUResourceBundle.getAvailableULocales();\r
152     }\r
153 \r
154 \r
155     /**\r
156      * Returns the character used for zero. Different for Arabic, etc.\r
157      * @return the character\r
158      * @stable ICU 2.0\r
159      */\r
160     public char getZeroDigit() {\r
161         return zeroDigit;\r
162     }\r
163 \r
164     /**\r
165      * Sets the character used for zero.\r
166      * @param zeroDigit the zero character.\r
167      * @stable ICU 2.0\r
168      */\r
169     public void setZeroDigit(char zeroDigit) {\r
170         this.zeroDigit = zeroDigit;\r
171     }\r
172 \r
173     /**\r
174      * Returns the character used to represent a significant digit in a pattern.\r
175      * @return the significant digit pattern character\r
176      * @stable ICU 3.0\r
177      */\r
178     public char getSignificantDigit() {\r
179         return sigDigit;\r
180     }\r
181 \r
182     /**\r
183      * Sets the character used to represent a significant digit in a pattern.\r
184      * @param sigDigit the significant digit pattern character\r
185      * @stable ICU 3.0\r
186      */\r
187     public void setSignificantDigit(char sigDigit) {\r
188         this.sigDigit = sigDigit;\r
189     }\r
190 \r
191     /**\r
192      * Returns the character used for thousands separator. Different for French, etc.\r
193      * @return the thousands character\r
194      * @stable ICU 2.0\r
195      */\r
196     public char getGroupingSeparator() {\r
197         return groupingSeparator;\r
198     }\r
199 \r
200     /**\r
201      * Sets the character used for thousands separator. Different for French, etc.\r
202      * @param groupingSeparator the thousands character\r
203      * @stable ICU 2.0\r
204      */\r
205     public void setGroupingSeparator(char groupingSeparator) {\r
206         this.groupingSeparator = groupingSeparator;\r
207     }\r
208 \r
209     /**\r
210      * Returns the character used for decimal sign. Different for French, etc.\r
211      * @return the decimal character\r
212      * @stable ICU 2.0\r
213      */\r
214     public char getDecimalSeparator() {\r
215         return decimalSeparator;\r
216     }\r
217 \r
218     /**\r
219      * Sets the character used for decimal sign. Different for French, etc.\r
220      * @param decimalSeparator the decimal character\r
221      * @stable ICU 2.0\r
222      */\r
223     public void setDecimalSeparator(char decimalSeparator) {\r
224         this.decimalSeparator = decimalSeparator;\r
225     }\r
226 \r
227     /**\r
228      * Returns the character used for mille percent sign. Different for Arabic, etc.\r
229      * @return the mille percent character\r
230      * @stable ICU 2.0\r
231      */\r
232     public char getPerMill() {\r
233         return perMill;\r
234     }\r
235 \r
236     /**\r
237      * Sets the character used for mille percent sign. Different for Arabic, etc.\r
238      * @param perMill the mille percent character\r
239      * @stable ICU 2.0\r
240      */\r
241     public void setPerMill(char perMill) {\r
242         this.perMill = perMill;\r
243     }\r
244 \r
245     /**\r
246      * Returns the character used for percent sign. Different for Arabic, etc.\r
247      * @return the percent character\r
248      * @stable ICU 2.0\r
249      */\r
250     public char getPercent() {\r
251         return percent;\r
252     }\r
253 \r
254     /**\r
255      * Sets the character used for percent sign. Different for Arabic, etc.\r
256      * @param percent the percent character\r
257      * @stable ICU 2.0\r
258      */\r
259     public void setPercent(char percent) {\r
260         this.percent = percent;\r
261     }\r
262 \r
263     /**\r
264      * Returns the character used for a digit in a pattern.\r
265      * @return the digit pattern character\r
266      * @stable ICU 2.0\r
267      */\r
268     public char getDigit() {\r
269         return digit;\r
270     }\r
271 \r
272     /**\r
273      * Sets the character used for a digit in a pattern.\r
274      * @param digit the digit pattern character\r
275      * @stable ICU 2.0\r
276      */\r
277     public void setDigit(char digit) {\r
278         this.digit = digit;\r
279     }\r
280 \r
281     /**\r
282      * Returns the character used to separate positive and negative subpatterns\r
283      * in a pattern.\r
284      * @return the pattern separator character\r
285      * @stable ICU 2.0\r
286      */\r
287     public char getPatternSeparator() {\r
288         return patternSeparator;\r
289     }\r
290 \r
291     /**\r
292      * Sets the character used to separate positive and negative subpatterns\r
293      * in a pattern.\r
294      * @param patternSeparator the pattern separator character\r
295      * @stable ICU 2.0\r
296      */\r
297     public void setPatternSeparator(char patternSeparator) {\r
298         this.patternSeparator = patternSeparator;\r
299     }\r
300 \r
301     /**\r
302      * Returns the String used to represent infinity. Almost always left\r
303      * unchanged.\r
304      * @return the Infinity string\r
305      * @stable ICU 2.0\r
306      */\r
307      //Bug 4194173 [Richard/GCL]\r
308 \r
309     public String getInfinity() {\r
310         return infinity;\r
311     }\r
312 \r
313     /**\r
314      * Sets the String used to represent infinity. Almost always left\r
315      * unchanged.\r
316      * @param infinity the Infinity String\r
317      * @stable ICU 2.0\r
318      */\r
319     public void setInfinity(String infinity) {\r
320         this.infinity = infinity;\r
321     }\r
322 \r
323     /**\r
324      * Returns the String used to represent NaN. Almost always left\r
325      * unchanged.\r
326      * @return the NaN String\r
327      * @stable ICU 2.0\r
328      */\r
329      //Bug 4194173 [Richard/GCL]\r
330     public String getNaN() {\r
331         return NaN;\r
332     }\r
333 \r
334     /**\r
335      * Sets the String used to represent NaN. Almost always left\r
336      * unchanged.\r
337      * @param NaN the NaN String\r
338      * @stable ICU 2.0\r
339      */\r
340     public void setNaN(String NaN) {\r
341         this.NaN = NaN;\r
342     }\r
343 \r
344     /**\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
349      * @stable ICU 2.0\r
350      */\r
351     public char getMinusSign() {\r
352         return minusSign;\r
353     }\r
354 \r
355     /**\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
360      * @stable ICU 2.0\r
361      */\r
362     public void setMinusSign(char minusSign) {\r
363         this.minusSign = minusSign;\r
364     }\r
365 \r
366     /**\r
367      * Returns the string denoting the local currency.\r
368      * @return the local currency String.\r
369      * @stable ICU 2.0\r
370      */\r
371     public String getCurrencySymbol() {\r
372         return currencySymbol;\r
373     }\r
374 \r
375     /**\r
376      * Sets the string denoting the local currency.\r
377      * @param currency the local currency String.\r
378      * @stable ICU 2.0\r
379      */\r
380     public void setCurrencySymbol(String currency) {\r
381         currencySymbol = currency;\r
382     }\r
383 \r
384     /**\r
385      * Returns the international string denoting the local currency.\r
386      * @return the international string denoting the local currency\r
387      * @stable ICU 2.0\r
388      */\r
389     public String getInternationalCurrencySymbol() {\r
390         return intlCurrencySymbol;\r
391     }\r
392 \r
393     /**\r
394      * Sets the international string denoting the local currency.\r
395      * @param currency the international string denoting the local currency.\r
396      * @stable ICU 2.0\r
397      */\r
398     public void setInternationalCurrencySymbol(String currency) {\r
399         intlCurrencySymbol = currency;\r
400     }\r
401 \r
402     /**\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
406      * @stable ICU 3.4\r
407      */\r
408     public Currency getCurrency() {\r
409         return currency;\r
410     }\r
411 \r
412     /**\r
413      * Sets the currency.\r
414      *\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
417      *\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
421      *\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
426      *\r
427      * @stable ICU 3.4\r
428      */\r
429     public void setCurrency(Currency currency) {\r
430         if (currency == null) {\r
431             throw new NullPointerException();\r
432         }\r
433         this.currency = currency;\r
434         intlCurrencySymbol = currency.getCurrencyCode();\r
435         currencySymbol = currency.getSymbol(requestedLocale);\r
436     }\r
437 \r
438     /**\r
439      * Returns the monetary decimal separator.\r
440      * @return the monetary decimal separator character\r
441      * @stable ICU 2.0\r
442      */\r
443     public char getMonetaryDecimalSeparator() {\r
444         return monetarySeparator;\r
445     }\r
446 \r
447     /**\r
448      * {@icu} Returns the monetary grouping separator.\r
449      * @return the monetary grouping separator character\r
450      * @stable ICU 3.6\r
451      */\r
452     public char getMonetaryGroupingSeparator() {\r
453         return monetaryGroupingSeparator;\r
454     }\r
455 \r
456     /**\r
457      * Internal API for NumberFormat\r
458      * @return String currency pattern string\r
459      */\r
460     String getCurrencyPattern() {\r
461         return currencyPattern;\r
462     }\r
463 \r
464     /**\r
465      * Sets the monetary decimal separator.\r
466      * @param sep the monetary decimal separator character\r
467      * @stable ICU 2.0\r
468      */\r
469     public void setMonetaryDecimalSeparator(char sep) {\r
470         monetarySeparator = sep;\r
471     }\r
472 \r
473     /**\r
474      * Sets the monetary decimal separator.\r
475      * @param sep the monetary decimal separator character\r
476      * @stable ICU 3.6\r
477      */\r
478     public void setMonetaryGroupingSeparator(char sep) {\r
479         monetaryGroupingSeparator = sep;\r
480     }\r
481 \r
482     /**\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
488      * @stable ICU 2.0\r
489      */\r
490     public String getExponentSeparator() {\r
491         return exponentSeparator;\r
492     }\r
493 \r
494     /**\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
500      * @stable ICU 2.0\r
501      */\r
502     public void setExponentSeparator(String exp) {\r
503         exponentSeparator = exp;\r
504     }\r
505 \r
506     /**\r
507      * {@icu} Returns the localized plus sign.\r
508      * @return the plus sign, used in localized patterns and formatted\r
509      * strings\r
510      * @see #setPlusSign\r
511      * @see #setMinusSign\r
512      * @see #getMinusSign\r
513      * @stable ICU 2.0\r
514      */\r
515     public char getPlusSign() {\r
516         return plusSign;\r
517     }\r
518 \r
519     /**\r
520      * {@icu} Sets the localized plus sign.\r
521      * @param plus the plus sign, used in localized patterns and formatted\r
522      * strings\r
523      * @see #getPlusSign\r
524      * @see #setMinusSign\r
525      * @see #getMinusSign\r
526      * @stable ICU 2.0\r
527      */\r
528     public void setPlusSign(char plus) {\r
529         plusSign = plus;\r
530     }\r
531 \r
532     /**\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
542      * @stable ICU 2.0\r
543      */\r
544     public char getPadEscape() {\r
545         return padEscape;\r
546     }\r
547 \r
548     /**\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
557      * @stable ICU 2.0\r
558      */\r
559     public void setPadEscape(char c) {\r
560         padEscape = c;\r
561     }\r
562 \r
563     /**\r
564      * {@icu} Indicates the currency match pattern used in {@link #getPatternForCurrencySpacing}.\r
565      * @draft ICU 4.2\r
566      */\r
567     public static final int CURRENCY_SPC_CURRENCY_MATCH = 0;\r
568 \r
569     /**\r
570      * {@icu} Indicates the surrounding match pattern used in {@link\r
571      * #getPatternForCurrencySpacing}.\r
572      * @draft ICU 4.2\r
573      */\r
574     public static final int CURRENCY_SPC_SURROUNDING_MATCH = 1;\r
575 \r
576     /**\r
577      * {@icu} Indicates the insertion value used in {@link #getPatternForCurrencySpacing}.\r
578      * @draft ICU 4.4\r
579      */\r
580     public static final int CURRENCY_SPC_INSERT = 2;\r
581 \r
582     private String[] currencySpcBeforeSym;\r
583     private String[] currencySpcAfterSym;\r
584 \r
585     /**\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
590      *\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
593      *\r
594      * <p><strong>Note:</strong> ICU4J does not currently use this information.\r
595      *\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
602      * @draft ICU 4.2\r
603      */\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
608         }\r
609         if (beforeCurrency) {\r
610             return currencySpcBeforeSym[itemType];\r
611         }\r
612         return currencySpcAfterSym[itemType];\r
613     }\r
614 \r
615     /**\r
616      * {@icu} Sets the indicated currency spacing pattern or value. See {@link\r
617      * #getPatternForCurrencySpacing} for more information.\r
618      *\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
621      *\r
622      * <p><strong>Note:</strong> ICU4J does not currently use this information.\r
623      *\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
630      * @draft ICU 4.2\r
631      */\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
636         }\r
637         if (beforeCurrency) {\r
638             currencySpcBeforeSym[itemType] = pattern;\r
639         } else {\r
640             currencySpcAfterSym[itemType] = pattern;\r
641         }\r
642     }\r
643 \r
644     /**\r
645      * Returns the locale for which this object was constructed.\r
646      * @return the locale for which this object was constructed\r
647      * @stable ICU 2.0\r
648      */\r
649     public Locale getLocale() {\r
650         return requestedLocale;\r
651     }\r
652 \r
653     /**\r
654      * Returns the locale for which this object was constructed.\r
655      * @return the locale for which this object was constructed\r
656      * @stable ICU 3.2\r
657      */\r
658     public ULocale getULocale() {\r
659         return ulocale;\r
660     }\r
661 \r
662     /**\r
663      * {@inheritDoc}\r
664      * @stable ICU 2.0\r
665      */\r
666     public Object clone() {\r
667         try {\r
668             return (DecimalFormatSymbols) super.clone();\r
669             // other fields are bit-copied\r
670         } catch (CloneNotSupportedException e) {\r
671             ///CLOVER:OFF\r
672             throw new IllegalStateException();\r
673             ///CLOVER:ON\r
674         }\r
675     }\r
676 \r
677     /**\r
678      * {@inheritDoc}\r
679      * @stable ICU 2.0\r
680      */\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
687                 return false;\r
688             }\r
689             if (!currencySpcAfterSym[i].equals(other.currencySpcAfterSym[i])) {\r
690                 return false;\r
691             }\r
692         }\r
693 \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
710     }\r
711 \r
712     /**\r
713      * {@inheritDoc}\r
714      * @stable ICU 2.0\r
715      */\r
716     public int hashCode() {\r
717             int result = zeroDigit;\r
718             result = result * 37 + groupingSeparator;\r
719             result = result * 37 + decimalSeparator;\r
720             return result;\r
721     }\r
722 \r
723     /**\r
724      * Initializes the symbols from the LocaleElements resource bundle.\r
725      * Note: The organization of LocaleElements badly needs to be\r
726      * cleaned up.\r
727      */\r
728     private void initialize( ULocale locale ) {\r
729         this.requestedLocale = locale.toLocale();\r
730         this.ulocale = locale;\r
731 \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
740             /* update cache */\r
741             cachedLocaleData.put(locale, data);\r
742         }\r
743         numberElements = data[0];\r
744 \r
745         ICUResourceBundle r = (ICUResourceBundle)UResourceBundle.\r
746             getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale);\r
747 \r
748         // TODO: Determine actual and valid locale correctly.\r
749         ULocale uloc = r.getULocale();\r
750         setLocale(uloc, uloc);\r
751 \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
759 \r
760         exponentSeparator = numberElements[7];\r
761         perMill = numberElements[8].charAt(0);\r
762         infinity = numberElements[9];\r
763         NaN = numberElements[10];\r
764 \r
765         plusSign  =numberElements[11].charAt(0);\r
766         padEscape = DecimalFormat.PATTERN_PAD_ESCAPE;\r
767         sigDigit  = DecimalFormat.PATTERN_SIGNIFICANT_DIGIT;\r
768 \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
773         }\r
774 \r
775         CurrencyDisplayInfo info = CurrencyData.provider.getInstance(locale, true);\r
776 \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
790                 : currname;\r
791         } else {\r
792             intlCurrencySymbol = "XXX";\r
793             currencySymbol = "\u00A4"; // 'OX' currency symbol\r
794         }\r
795 \r
796 \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
801         if (curr != null){\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
807             }\r
808         }\r
809 \r
810         // Get currency spacing data.\r
811         currencySpcBeforeSym = new String[3];\r
812         currencySpcAfterSym = new String[3];\r
813         initSpacingInfo(info.getSpacingInfo());\r
814     }\r
815 \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
823     }\r
824 \r
825     /**\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
829      * to be 'E'.\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
832      */\r
833     private void readObject(ObjectInputStream stream)\r
834         throws IOException, ClassNotFoundException {\r
835 \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
838 \r
839         stream.defaultReadObject();\r
840         ///CLOVER:OFF\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
844             // use defaults.\r
845             monetarySeparator = decimalSeparator;\r
846             exponential = 'E';\r
847         }\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
856         }\r
857         ///CLOVER:ON\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
865         }\r
866         if (serialVersionOnStream < 4) {\r
867             // use same default behavior as for versions with no Locale\r
868             ulocale = ULocale.forLocale(requestedLocale);\r
869         }\r
870         if (serialVersionOnStream < 5) {\r
871             // use the same one for groupingSeparator\r
872             monetaryGroupingSeparator = groupingSeparator;\r
873         }\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
878             }\r
879             if (currencySpcAfterSym == null) {\r
880                 currencySpcAfterSym = new String[CURRENCY_SPC_INSERT+1];\r
881             }\r
882             initSpacingInfo(CurrencyData.CurrencySpacingInfo.DEFAULT);\r
883         }\r
884         serialVersionOnStream = currentSerialVersion;\r
885 \r
886     // recreate\r
887     currency = Currency.getInstance(intlCurrencySymbol);\r
888     }\r
889 \r
890     /**\r
891      * Character used for zero.\r
892      *\r
893      * @serial\r
894      * @see #getZeroDigit\r
895      */\r
896     private  char    zeroDigit;\r
897 \r
898     /**\r
899      * Character used for thousands separator.\r
900      *\r
901      * @serial\r
902      * @see #getGroupingSeparator\r
903      */\r
904     private  char    groupingSeparator;\r
905 \r
906     /**\r
907      * Character used for decimal sign.\r
908      *\r
909      * @serial\r
910      * @see #getDecimalSeparator\r
911      */\r
912     private  char    decimalSeparator;\r
913 \r
914     /**\r
915      * Character used for mille percent sign.\r
916      *\r
917      * @serial\r
918      * @see #getPerMill\r
919      */\r
920     private  char    perMill;\r
921 \r
922     /**\r
923      * Character used for percent sign.\r
924      * @serial\r
925      * @see #getPercent\r
926      */\r
927     private  char    percent;\r
928 \r
929     /**\r
930      * Character used for a digit in a pattern.\r
931      *\r
932      * @serial\r
933      * @see #getDigit\r
934      */\r
935     private  char    digit;\r
936 \r
937     /**\r
938      * Character used for a significant digit in a pattern.\r
939      *\r
940      * @serial\r
941      * @see #getSignificantDigit\r
942      */\r
943     private  char    sigDigit;\r
944 \r
945     /**\r
946      * Character used to separate positive and negative subpatterns\r
947      * in a pattern.\r
948      *\r
949      * @serial\r
950      * @see #getPatternSeparator\r
951      */\r
952     private  char    patternSeparator;\r
953 \r
954     /**\r
955      * Character used to represent infinity.\r
956      * @serial\r
957      * @see #getInfinity\r
958      */\r
959     private  String  infinity;\r
960 \r
961     /**\r
962      * Character used to represent NaN.\r
963      * @serial\r
964      * @see #getNaN\r
965      */\r
966     private  String  NaN;\r
967 \r
968     /**\r
969      * Character used to represent minus sign.\r
970      * @serial\r
971      * @see #getMinusSign\r
972      */\r
973     private  char    minusSign;\r
974 \r
975     /**\r
976      * String denoting the local currency, e.g. "$".\r
977      * @serial\r
978      * @see #getCurrencySymbol\r
979      */\r
980     private  String  currencySymbol;\r
981 \r
982     /**\r
983      * International string denoting the local currency, e.g. "USD".\r
984      * @serial\r
985      * @see #getInternationalCurrencySymbol\r
986      */\r
987     private  String  intlCurrencySymbol;\r
988 \r
989     /**\r
990      * The decimal separator used when formatting currency values.\r
991      * @serial\r
992      * @see #getMonetaryDecimalSeparator\r
993      */\r
994     private  char    monetarySeparator; // Field new in JDK 1.1.6\r
995 \r
996     /**\r
997      * The decimal separator used when formatting currency values.\r
998      * @serial\r
999      * @see #getMonetaryGroupingSeparator\r
1000      */\r
1001     private  char    monetaryGroupingSeparator; // Field new in JDK 1.1.6\r
1002 \r
1003     /**\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
1006      * <p>\r
1007      * Note that this field has been superseded by <code>exponentSeparator</code>.\r
1008      * It is retained for backward compatibility.\r
1009      *\r
1010      * @serial\r
1011      */\r
1012     private  char    exponential;       // Field new in JDK 1.1.6\r
1013 \r
1014     /**\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
1017      * <p>\r
1018      * Note that this supersedes the <code>exponential</code> field.\r
1019      *\r
1020      * @serial\r
1021      * @since AlphaWorks\r
1022      */\r
1023     private String exponentSeparator;\r
1024 \r
1025     /**\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
1028      * @serial\r
1029      * @since AlphaWorks\r
1030      */\r
1031     private char padEscape;\r
1032 \r
1033     /**\r
1034      * The character used to indicate a plus sign.\r
1035      * @serial\r
1036      * @since AlphaWorks\r
1037      */\r
1038     private char plusSign;\r
1039 \r
1040     /**\r
1041      * The locale for which this object was constructed.  Set to the\r
1042      * default locale for objects resurrected from old streams.\r
1043      * @since ICU 2.2\r
1044      */\r
1045     private Locale requestedLocale;\r
1046 \r
1047     /**\r
1048      * The requested ULocale.  We keep the old locale for serialization compatibility.\r
1049      * @since IDU 3.2\r
1050      */\r
1051     private ULocale ulocale;\r
1052 \r
1053     // Proclaim JDK 1.1 FCS compatibility\r
1054     private static final long serialVersionUID = 5772796243397350300L;\r
1055 \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
1067 \r
1068     /**\r
1069      * Describes the version of <code>DecimalFormatSymbols</code> present on the stream.\r
1070      * Possible values are:\r
1071      * <ul>\r
1072      * <li><b>0</b> (or uninitialized): versions prior to JDK 1.1.6.\r
1073      *\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
1077      *      and plusSign.\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
1083      * </ul>\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
1087      *\r
1088      * @serial\r
1089      */\r
1090     private int serialVersionOnStream = currentSerialVersion;\r
1091 \r
1092     /**\r
1093      * cache to hold the NumberElements of a Locale.\r
1094      */\r
1095     private static final Hashtable<ULocale, String[][]> cachedLocaleData =\r
1096         new Hashtable<ULocale, String[][]>(3);\r
1097 \r
1098     /**\r
1099      *\r
1100      */\r
1101     private String  currencyPattern = null;\r
1102 \r
1103     // -------- BEGIN ULocale boilerplate --------\r
1104 \r
1105     /**\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
1113      *\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
1126      */\r
1127     public final ULocale getLocale(ULocale.Type type) {\r
1128         return type == ULocale.ACTUAL_LOCALE ?\r
1129             this.actualLocale : this.validLocale;\r
1130     }\r
1131 \r
1132     /**\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
1139      * this class.\r
1140      * @param valid the most specific locale containing any resource\r
1141      * data, or null\r
1142      * @param actual the locale containing data used to construct this\r
1143      * object, or null\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
1147      */\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
1151             ///CLOVER:OFF\r
1152             throw new IllegalArgumentException();\r
1153             ///CLOVER:ON\r
1154         }\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
1159     }\r
1160 \r
1161     /**\r
1162      * The most specific locale containing any resource data, or null.\r
1163      * @see com.ibm.icu.util.ULocale\r
1164      */\r
1165     private ULocale validLocale;\r
1166 \r
1167     /**\r
1168      * The locale containing data used to construct this object, or\r
1169      * null.\r
1170      * @see com.ibm.icu.util.ULocale\r
1171      */\r
1172     private ULocale actualLocale;\r
1173 \r
1174     // not serialized, reconstructed from intlCurrencyCode\r
1175     private transient Currency currency;\r
1176 \r
1177     // -------- END ULocale boilerplate --------\r
1178 }\r