]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/text/DecimalFormatSymbols.java
icu4jsrc
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / text / DecimalFormatSymbols.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 1996-2009, 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 com.ibm.icu.impl.ICUResourceBundle;\r
10 import com.ibm.icu.util.Currency;\r
11 import com.ibm.icu.util.ULocale;\r
12 import com.ibm.icu.util.UResourceBundle;\r
13 \r
14 import java.io.IOException;\r
15 import java.io.ObjectInputStream;\r
16 import java.io.Serializable;\r
17 import java.text.ChoiceFormat;\r
18 import java.util.Hashtable;\r
19 import java.util.Locale;\r
20 import java.util.MissingResourceException;\r
21 \r
22 /**\r
23  * This class represents the set of symbols (such as the decimal separator, the\r
24  * grouping separator, and so on) needed by <code>DecimalFormat</code> to format\r
25  * numbers. <code>DecimalFormat</code> creates for itself an instance of\r
26  * <code>DecimalFormatSymbols</code> from its locale data.  If you need to\r
27  * change any of these symbols, you can get the\r
28  * <code>DecimalFormatSymbols</code> object from your <code>DecimalFormat</code>\r
29  * and modify it.\r
30  *\r
31  * <p><strong>This is an enhanced version of <code>DecimalFormatSymbols</code> that\r
32  * is based on the standard version in the JDK.  New or changed functionality\r
33  * is labeled\r
34  * <strong><font face=helvetica color=red>NEW</font></strong>.</strong>\r
35  *\r
36  * @see          java.util.Locale\r
37  * @see          DecimalFormat\r
38  * @author       Mark Davis\r
39  * @author       Alan Liu\r
40  * @stable ICU 2.0\r
41  */\r
42 \r
43 public class DecimalFormatSymbols implements Cloneable, Serializable {\r
44 \r
45     /**\r
46      * Create a DecimalFormatSymbols object for the default locale.\r
47      * @stable ICU 2.0\r
48      */\r
49     public DecimalFormatSymbols() {\r
50         initialize( ULocale.getDefault() );\r
51     }\r
52 \r
53     /**\r
54      * Create a DecimalFormatSymbols object for the given locale.\r
55      * @param locale the locale\r
56      * @stable ICU 2.0\r
57      */\r
58     public DecimalFormatSymbols( Locale locale ) {\r
59         initialize( ULocale.forLocale(locale) );\r
60     }\r
61 \r
62     /**\r
63      * Create a DecimalFormatSymbols object for the given locale.\r
64      * @param locale the locale\r
65      * @stable ICU 3.2\r
66      */\r
67     public DecimalFormatSymbols( ULocale locale ) {\r
68         initialize( locale );\r
69     }\r
70 \r
71     /**\r
72      * Gets a DecimalFormatSymbols instance for the default locale.\r
73      * <br><br>\r
74      * <b>Note:</b> Unlike <code>java.text.DecimalFormatSymbols#getInstance</code>,\r
75      * this method simply returns <code>new com.ibm.icu.text.DecimalFormatSymbols()</code>.\r
76      * ICU does not support <code>DecimalFormatSymbolsProvider</code> introduced in Java 6\r
77      * or its equivalent implementation for now.\r
78      * \r
79      * @return A DecimalFormatSymbols instance.\r
80      * @stable ICU 3.8\r
81      */\r
82     public static DecimalFormatSymbols getInstance() {\r
83         return new DecimalFormatSymbols();\r
84     }\r
85 \r
86     /**\r
87      * Gets a DecimalFormatSymbols instance for the given locale.\r
88      * <br><br>\r
89      * <b>Note:</b> Unlike <code>java.text.DecimalFormatSymbols#getInstance</code>,\r
90      * this method simply returns <code>new com.ibm.icu.text.DecimalFormatSymbols(locale)</code>.\r
91      * ICU does not support <code>DecimalFormatSymbolsProvider</code> introduced in Java 6\r
92      * or its equivalent implementation for now.\r
93      * \r
94      * @param locale the locale.\r
95      * @return A DecimalFormatSymbols instance.\r
96      * @stable ICU 3.8\r
97      */\r
98     public static DecimalFormatSymbols getInstance(Locale locale) {\r
99         return new DecimalFormatSymbols(locale);\r
100     }\r
101 \r
102     /**\r
103      * Gets a DecimalFormatSymbols instance for the given locale.\r
104      * <br><br>\r
105      * <b>Note:</b> Unlike <code>java.text.DecimalFormatSymbols#getInstance</code>,\r
106      * this method simply returns <code>new com.ibm.icu.text.DecimalFormatSymbols(locale)</code>.\r
107      * ICU does not support <code>DecimalFormatSymbolsProvider</code> introduced in Java 6\r
108      * or its equivalent implementation for now.\r
109      * \r
110      * @param locale the locale.\r
111      * @return A DecimalFormatSymbols instance.\r
112      * @stable ICU 3.8\r
113      */\r
114     public static DecimalFormatSymbols getInstance(ULocale locale) {\r
115         return new DecimalFormatSymbols(locale);\r
116     }\r
117 \r
118     /**\r
119      * Returns an array of all locales for which the <code>getInstance</code> methods of this\r
120      * class can return localized instances.\r
121      * <br><br>\r
122      * <b>Note:</b> Unlike <code>java.text.DecimalFormatSymbols#getAvailableLocales</code>,\r
123      * this method simply returns the array of <code>Locale</code>s available for this class.\r
124      * ICU does not support <code>DecimalFormatSymbolsProvider</code> introduced in Java 6\r
125      * or its equivalent implementation for now.\r
126      * \r
127      * @return An array of <code>Locale</code>s for which localized <code>DecimalFormatSymbols</code> instances are available.\r
128      * @stable ICU 3.8\r
129      */\r
130     public static Locale[] getAvailableLocales() {\r
131         return ICUResourceBundle.getAvailableLocales(ICUResourceBundle.ICU_BASE_NAME);\r
132     }\r
133 \r
134     /**\r
135      * Returns an array of all locales for which the <code>getInstance</code> methods of this\r
136      * class can return localized instances.\r
137      * <br><br>\r
138      * <b>Note:</b> Unlike <code>java.text.DecimalFormatSymbols#getAvailableLocales</code>,\r
139      * this method simply returns the array of <code>ULocale</code>s available in this class.\r
140      * ICU does not support <code>DecimalFormatSymbolsProvider</code> introduced in Java 6\r
141      * or its equivalent implementation for now.\r
142      * \r
143      * @return An array of <code>ULocale</code>s for which localized <code>DecimalFormatSymbols</code> instances are available.\r
144      * @stable ICU 3.8 (retain)\r
145      * @provisional This API might change or be removed in a future release.\r
146      */\r
147     public static ULocale[] getAvailableULocales() {\r
148         return ICUResourceBundle.getAvailableULocales(ICUResourceBundle.ICU_BASE_NAME);\r
149     }\r
150 \r
151     \r
152     /**\r
153      * Return the character used for zero. Different for Arabic, etc.\r
154      * @return the character\r
155      * @stable ICU 2.0\r
156      */\r
157     public char getZeroDigit() {\r
158         return zeroDigit;\r
159     }\r
160 \r
161     /**\r
162      * Set the character used for zero.\r
163      * @param zeroDigit the zero character.\r
164      * @stable ICU 2.0\r
165      */\r
166     public void setZeroDigit(char zeroDigit) {\r
167         this.zeroDigit = zeroDigit;\r
168     }\r
169 \r
170     /**\r
171      * Return the character used to represent a significant digit in a pattern.\r
172      * @return the significant digit pattern character\r
173      * @stable ICU 3.0\r
174      */\r
175     public char getSignificantDigit() {\r
176         return sigDigit;\r
177     }\r
178 \r
179     /**\r
180      * Set the character used to represent a significant digit in a pattern.\r
181      * @param sigDigit the significant digit pattern character\r
182      * @stable ICU 3.0\r
183      */\r
184     public void setSignificantDigit(char sigDigit) {\r
185         this.sigDigit = sigDigit;\r
186     }    \r
187     \r
188     /**\r
189      * Return the character used for thousands separator. Different for French, etc.\r
190      * @return the thousands character\r
191      * @stable ICU 2.0\r
192      */\r
193     public char getGroupingSeparator() {\r
194         return groupingSeparator;\r
195     }\r
196 \r
197     /**\r
198      * Set the character used for thousands separator. Different for French, etc.\r
199      * @param groupingSeparator the thousands character\r
200      * @stable ICU 2.0\r
201      */\r
202     public void setGroupingSeparator(char groupingSeparator) {\r
203         this.groupingSeparator = groupingSeparator;\r
204     }\r
205 \r
206     /**\r
207      * Return the character used for decimal sign. Different for French, etc.\r
208      * @return the decimal character\r
209      * @stable ICU 2.0\r
210      */\r
211     public char getDecimalSeparator() {\r
212         return decimalSeparator;\r
213     }\r
214 \r
215     /**\r
216      * Set the character used for decimal sign. Different for French, etc.\r
217      * @param decimalSeparator the decimal character\r
218      * @stable ICU 2.0\r
219      */\r
220     public void setDecimalSeparator(char decimalSeparator) {\r
221         this.decimalSeparator = decimalSeparator;\r
222     }\r
223 \r
224     /**\r
225      * Return the character used for mille percent sign. Different for Arabic, etc.\r
226      * @return the mille percent character\r
227      * @stable ICU 2.0\r
228      */\r
229     public char getPerMill() {\r
230         return perMill;\r
231     }\r
232 \r
233     /**\r
234      * Set the character used for mille percent sign. Different for Arabic, etc.\r
235      * @param perMill the mille percent character\r
236      * @stable ICU 2.0\r
237      */\r
238     public void setPerMill(char perMill) {\r
239         this.perMill = perMill;\r
240     }\r
241 \r
242     /**\r
243      * Return the character used for percent sign. Different for Arabic, etc.\r
244      * @return the percent character\r
245      * @stable ICU 2.0\r
246      */\r
247     public char getPercent() {\r
248         return percent;\r
249     }\r
250 \r
251     /**\r
252      * Set the character used for percent sign. Different for Arabic, etc.\r
253      * @param percent the percent character\r
254      * @stable ICU 2.0\r
255      */\r
256     public void setPercent(char percent) {\r
257         this.percent = percent;\r
258     }\r
259 \r
260     /**\r
261      * Return the character used for a digit in a pattern.\r
262      * @return the digit pattern character\r
263      * @stable ICU 2.0\r
264      */\r
265     public char getDigit() {\r
266         return digit;\r
267     }\r
268 \r
269     /**\r
270      * Set the character used for a digit in a pattern.\r
271      * @param digit the digit pattern character\r
272      * @stable ICU 2.0\r
273      */\r
274     public void setDigit(char digit) {\r
275         this.digit = digit;\r
276     }\r
277 \r
278     /**\r
279      * Return the character used to separate positive and negative subpatterns\r
280      * in a pattern.\r
281      * @return the pattern separator character\r
282      * @stable ICU 2.0\r
283      */\r
284     public char getPatternSeparator() {\r
285         return patternSeparator;\r
286     }\r
287 \r
288     /**\r
289      * Set the character used to separate positive and negative subpatterns\r
290      * in a pattern.\r
291      * @param patternSeparator the pattern separator character\r
292      * @stable ICU 2.0\r
293      */\r
294     public void setPatternSeparator(char patternSeparator) {\r
295         this.patternSeparator = patternSeparator;\r
296     }\r
297 \r
298     /**\r
299      * Return the String used to represent infinity. Almost always left\r
300      * unchanged.\r
301      * @return the Infinity string\r
302      * @stable ICU 2.0\r
303      */\r
304      //Bug 4194173 [Richard/GCL]\r
305 \r
306     public String getInfinity() {\r
307         return infinity;\r
308     }\r
309 \r
310     /**\r
311      * Set the String used to represent infinity. Almost always left\r
312      * unchanged.\r
313      * @param infinity the Infinity String\r
314      * @stable ICU 2.0\r
315      */\r
316     public void setInfinity(String infinity) {\r
317         this.infinity = infinity;\r
318     }\r
319 \r
320     /**\r
321      * Return the String used to represent NaN. Almost always left\r
322      * unchanged.\r
323      * @return the NaN String\r
324      * @stable ICU 2.0\r
325      */\r
326      //Bug 4194173 [Richard/GCL]\r
327     public String getNaN() {\r
328         return NaN;\r
329     }\r
330 \r
331     /**\r
332      * Set the String used to represent NaN. Almost always left\r
333      * unchanged.\r
334      * @param NaN the NaN String\r
335      * @stable ICU 2.0\r
336      */\r
337     public void setNaN(String NaN) {\r
338         this.NaN = NaN;\r
339     }\r
340 \r
341     /**\r
342      * Return the character used to represent minus sign. If no explicit\r
343      * negative format is specified, one is formed by prefixing\r
344      * minusSign to the positive format.\r
345      * @return the minus sign character\r
346      * @stable ICU 2.0\r
347      */\r
348     public char getMinusSign() {\r
349         return minusSign;\r
350     }\r
351 \r
352     /**\r
353      * Set the character used to represent minus sign. If no explicit\r
354      * negative format is specified, one is formed by prefixing\r
355      * minusSign to the positive format.\r
356      * @param minusSign the minus sign character\r
357      * @stable ICU 2.0\r
358      */\r
359     public void setMinusSign(char minusSign) {\r
360         this.minusSign = minusSign;\r
361     }\r
362 \r
363     /**\r
364      * Return the string denoting the local currency.\r
365      * @return the local currency String.\r
366      * @stable ICU 2.0\r
367      */\r
368     public String getCurrencySymbol()\r
369     {\r
370         return currencySymbol;\r
371     }\r
372 \r
373     /**\r
374      * Set the string denoting the local currency.\r
375      * @param currency the local currency String.\r
376      * @stable ICU 2.0\r
377      */\r
378     public void setCurrencySymbol(String currency)\r
379     {\r
380         currencySymbol = currency;\r
381     }\r
382 \r
383     /**\r
384      * Return the international string denoting the local currency.\r
385      * @return the international string denoting the local currency\r
386      * @stable ICU 2.0\r
387      */\r
388     public String getInternationalCurrencySymbol()\r
389     {\r
390         return intlCurrencySymbol;\r
391     }\r
392 \r
393     /**\r
394      * Set 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     {\r
400         intlCurrencySymbol = currency;\r
401     }\r
402 \r
403     /**\r
404      * Returns the currency symbol, for JDK 1.4 compatibility only.\r
405      * ICU clients should use the Currency API directly.\r
406      * @return the currency used, or null\r
407      * @stable ICU 3.4\r
408      */\r
409     public Currency getCurrency() {\r
410         return currency;\r
411     }\r
412     \r
413     /**\r
414      * ICU does not use the DecimalFormatSymbols for the \r
415      * currency any more.  This API is present\r
416      * for API compatibility only.\r
417      *\r
418      * 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      * Return 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     {\r
445         return monetarySeparator;\r
446     }\r
447 \r
448     /**\r
449      * Return the monetary decimal separator.\r
450      * @return the monetary decimal separator character\r
451      * @stable ICU 3.6\r
452      */\r
453     public char getMonetaryGroupingSeparator()\r
454     {\r
455         return monetaryGroupingSeparator;\r
456     }\r
457     \r
458     /**\r
459      * Internal API for NumberFormat\r
460      * @return String currency pattern string\r
461      * @internal\r
462      */\r
463     String getCurrencyPattern(){\r
464         return currencyPattern;\r
465     }\r
466     /**\r
467      * Set the monetary decimal separator.\r
468      * @param sep the monetary decimal separator character\r
469      * @stable ICU 2.0\r
470      */\r
471     public void setMonetaryDecimalSeparator(char sep)\r
472     {\r
473         monetarySeparator = sep;\r
474     }\r
475     /**\r
476      * Set the monetary decimal separator.\r
477      * @param sep the monetary decimal separator character\r
478      * @stable ICU 3.6\r
479      */\r
480     public void setMonetaryGroupingSeparator(char sep)\r
481     {\r
482         monetaryGroupingSeparator = sep;\r
483     }\r
484 \r
485     /**\r
486      * <strong><font face=helvetica color=red>NEW</font></strong>\r
487      * Return the string used to separate the mantissa from the exponent.\r
488      * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.\r
489      * @return the localized exponent symbol, used in localized patterns\r
490      * and formatted strings\r
491      * @see #setExponentSeparator\r
492      * @stable ICU 2.0\r
493      */\r
494     public String getExponentSeparator()\r
495     {\r
496         return exponentSeparator;\r
497     }\r
498 \r
499     /**\r
500      * <strong><font face=helvetica color=red>NEW</font></strong>\r
501      * Set the string used to separate the mantissa from the exponent.\r
502      * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.\r
503      * @param exp the localized exponent symbol, used in localized patterns\r
504      * and formatted strings\r
505      * @see #getExponentSeparator\r
506      * @stable ICU 2.0\r
507      */\r
508     public void setExponentSeparator(String exp)\r
509     {\r
510         exponentSeparator = exp;\r
511     }\r
512 \r
513     /**\r
514      * <strong><font face=helvetica color=red>NEW</font></strong>\r
515      * Return the localized plus sign.\r
516      * @return the plus sign, used in localized patterns and formatted\r
517      * strings\r
518      * @see #setPlusSign\r
519      * @see #setMinusSign\r
520      * @see #getMinusSign\r
521      * @stable ICU 2.0\r
522      */\r
523     public char getPlusSign() {\r
524         return plusSign;\r
525     }\r
526 \r
527     /**\r
528      * <strong><font face=helvetica color=red>NEW</font></strong>\r
529      * Set the localized plus sign.\r
530      * @param plus the plus sign, used in localized patterns and formatted\r
531      * strings\r
532      * @see #getPlusSign\r
533      * @see #setMinusSign\r
534      * @see #getMinusSign\r
535      * @stable ICU 2.0\r
536      */\r
537     public void setPlusSign(char plus) {\r
538         plusSign = plus;\r
539     }\r
540 \r
541     /**\r
542      * <strong><font face=helvetica color=red>NEW</font></strong>\r
543      * Return the character used to pad numbers out to a specified width.  This\r
544      * is not the pad character itself; rather, it is the special pattern\r
545      * character <em>preceding</em> the pad character.  In the pattern\r
546      * "*_#,##0", '*' is the pad escape, and '_' is the pad character.\r
547      * @return the character \r
548      * @see #setPadEscape\r
549      * @see DecimalFormat#getFormatWidth\r
550      * @see DecimalFormat#getPadPosition\r
551      * @see DecimalFormat#getPadCharacter\r
552      * @stable ICU 2.0\r
553      */\r
554     public char getPadEscape() {\r
555         return padEscape;\r
556     }\r
557 \r
558     /**\r
559      * <strong><font face=helvetica color=red>NEW</font></strong>\r
560      * Set the character used to pad numbers out to a specified width.  This is\r
561      * not the pad character itself; rather, it is the special pattern character\r
562      * <em>preceding</em> the pad character.  In the pattern "*_#,##0", '*' is\r
563      * the pad escape, and '_' is the pad character.\r
564      * @see #getPadEscape\r
565      * @see DecimalFormat#setFormatWidth\r
566      * @see DecimalFormat#setPadPosition\r
567      * @see DecimalFormat#setPadCharacter\r
568      * @stable ICU 2.0\r
569      */\r
570     public void setPadEscape(char c) {\r
571         padEscape = c;\r
572     }\r
573     \r
574     public static final int CURRENCY_SPC_CURRENCY_MATCH = 0;\r
575     public static final int CURRENCT_SPC_SURROUNDING_MATCH = 1;\r
576     public static final int CURRENCY_SPC_INSERT = 2;\r
577 \r
578     private static final String CURRENCY_SPACING = "currencySpacing";\r
579     private static final String BEFORE_CURRENCY = "beforeCurrency";\r
580     private static final String AFTER_CURRENCY = "afterCurrency";\r
581     private static final String[] CURRENCY_SPACING_KEYS = \r
582         { "currencyMatch", "surroundingMatch" ,"insertBetween"};\r
583     private static final String DEFAULT_SPC_MATCH = "[:letter:]";\r
584     private static final String DEFAULT_SPC_INSERT = " ";\r
585     private static final String DEFAULT_SPC_SUR_MATCH = "[:digit:]";\r
586 \r
587     private String[] currencySpcBeforeSym; // before currency symbol.\r
588     private String[] currencySpcAfterSym; // after currency symbol.\r
589     /**\r
590      * Get pattern string for 'CurrencySpacing' that can be applied to\r
591      * currency format.\r
592      * This API gets the CurrencySpacing data from ResourceBundle. The pattern can\r
593      * be null if there is no data from current locale and its parent locales.\r
594      *\r
595      * @param itemType : CURRENCY_SPC_CURRENCY_MATCH, CURRENCY_SPC_SURROUNDING_MATCH\r
596      *                   or CURRENCY_SPC_INSERT\r
597      * @param beforeCurrency : true if the pattern is for before currency symbol.\r
598      *                         false if the pattern is for after currency symbol.\r
599      * @return  pattern string for currencyMatch, surroundingMatch or spaceInsert.\r
600      *     Return null of there is no data for this locale and its parent locales.\r
601      */\r
602     public String getPatternForCurrencySpacing(int itemType, boolean beforeCurrency)  {\r
603         if (itemType < CURRENCY_SPC_CURRENCY_MATCH ||\r
604             itemType > CURRENCY_SPC_INSERT ) {\r
605             return null;  // invalid itemType.\r
606         }\r
607         if (beforeCurrency) {\r
608             return currencySpcBeforeSym[itemType];\r
609         } else {\r
610             return currencySpcAfterSym[itemType];\r
611         }\r
612     }\r
613 \r
614     \r
615     /**\r
616      * Set pattern string for 'CurrencySpacing' that can be applied to\r
617      * CurrencyFormat.\r
618      * \r
619      * @param itemType : CURRENCY_SPC_CURRENCY_MATCH, CURRENCY_SPC_SURROUNDING_MATCH\r
620      *                   or CURRENCY_SPC_INSERT\r
621      * @param beforeCurrency : true if the pattern is for before currency symbol.\r
622      *                         false if the pattern is for after currency symbol.\r
623      * @param  pattern string to override current setting.\r
624      */\r
625     public void setPatternForCurrencySpacing(int itemType, boolean beforeCurrency, String pattern) {\r
626 \r
627         if (itemType < CURRENCY_SPC_CURRENCY_MATCH ||\r
628             itemType > CURRENCY_SPC_INSERT ) {\r
629             return;  // invalid itemType.\r
630         }\r
631         if (beforeCurrency) {\r
632             currencySpcBeforeSym[itemType] = pattern;\r
633         } else {\r
634             currencySpcAfterSym[itemType] = pattern;\r
635         }\r
636     }\r
637     \r
638     /**\r
639      * Returns the locale for which this object was constructed.\r
640      * @return the locale for which this object was constructed\r
641      * @stable ICU 2.0\r
642      */\r
643     public Locale getLocale() {\r
644         return requestedLocale;\r
645     }\r
646 \r
647     /**\r
648      * Returns the locale for which this object was constructed.\r
649      * @return the locale for which this object was constructed\r
650      * @stable ICU 3.2\r
651      */\r
652     public ULocale getULocale() {\r
653         return ulocale;\r
654     }\r
655 \r
656     /**\r
657      * Standard override.\r
658      * @stable ICU 2.0\r
659      */\r
660     public Object clone() {\r
661         try {\r
662             return (DecimalFormatSymbols) super.clone();\r
663             // other fields are bit-copied\r
664         } catch (CloneNotSupportedException e) {\r
665             ///CLOVER:OFF\r
666             throw new IllegalStateException();\r
667             ///CLOVER:ON\r
668         }\r
669     }\r
670 \r
671     /**\r
672      * Override equals.\r
673      * @stable ICU 2.0\r
674      */\r
675     public boolean equals(Object obj) {\r
676         if (obj == null) return false;\r
677         if (this == obj) return true;\r
678         DecimalFormatSymbols other = (DecimalFormatSymbols) obj;\r
679         for (int i = 0; i <= CURRENCY_SPC_INSERT; i++) {\r
680             if (!currencySpcBeforeSym[i].equals(other.currencySpcBeforeSym[i])) {\r
681                 return false;\r
682             }\r
683             if (!currencySpcAfterSym[i].equals(other.currencySpcAfterSym[i])) {\r
684                 return false;\r
685             }\r
686         }\r
687 \r
688         return (zeroDigit == other.zeroDigit &&\r
689         groupingSeparator == other.groupingSeparator &&\r
690         decimalSeparator == other.decimalSeparator &&\r
691         percent == other.percent &&\r
692         perMill == other.perMill &&\r
693         digit == other.digit &&\r
694         minusSign == other.minusSign &&\r
695         patternSeparator == other.patternSeparator &&\r
696         infinity.equals(other.infinity) &&\r
697         NaN.equals(other.NaN) &&\r
698         currencySymbol.equals(other.currencySymbol) &&\r
699         intlCurrencySymbol.equals(other.intlCurrencySymbol) &&\r
700         padEscape == other.padEscape && // [NEW]\r
701         plusSign == other.plusSign && // [NEW]\r
702         exponentSeparator.equals(other.exponentSeparator) && // [NEW]\r
703         monetarySeparator == other.monetarySeparator);\r
704     }\r
705 \r
706     /**\r
707      * Override hashCode\r
708      * @stable ICU 2.0\r
709      */\r
710     public int hashCode() {\r
711             int result = zeroDigit;\r
712             result = result * 37 + groupingSeparator;\r
713             result = result * 37 + decimalSeparator;\r
714             return result;\r
715     }\r
716 \r
717     /**\r
718      * Initializes the symbols from the LocaleElements resource bundle.\r
719      * Note: The organization of LocaleElements badly needs to be\r
720      * cleaned up.\r
721      */\r
722     private void initialize( ULocale locale ) {\r
723         this.requestedLocale = locale.toLocale();\r
724         this.ulocale = locale;\r
725 \r
726         /* try the cache first */\r
727         String[][] data = (String[][]) cachedLocaleData.get(locale);\r
728         String[] numberElements;\r
729         if (data == null) {  /* cache miss */\r
730             data = new String[1][];\r
731             ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.\r
732                 getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale);\r
733             data[0] = rb.getStringArray("NumberElements");\r
734             /* update cache */\r
735             cachedLocaleData.put(locale, data);\r
736         }\r
737         numberElements = data[0];\r
738         \r
739         ICUResourceBundle r = (ICUResourceBundle)UResourceBundle.\r
740             getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale);\r
741         \r
742         // TODO: Determine actual and valid locale correctly.\r
743         ULocale uloc = r.getULocale();\r
744         setLocale(uloc, uloc);\r
745 \r
746     // {dlf} clean up below now that we have our own resource data\r
747         decimalSeparator = numberElements[0].charAt(0);\r
748         groupingSeparator = numberElements[1].charAt(0);\r
749         // Temporary hack to support old JDK 1.1 resources\r
750 //        patternSeparator = numberElements[2].length() > 0 ?\r
751 //            numberElements[2].charAt(0) : ';';\r
752         patternSeparator = numberElements[2].charAt(0);\r
753         percent = numberElements[3].charAt(0);\r
754         zeroDigit = numberElements[4].charAt(0); //different for Arabic,etc.\r
755         digit = numberElements[5].charAt(0);\r
756         minusSign = numberElements[6].charAt(0);\r
757         \r
758         // Temporary hack to support JDK versions before 1.1.6 (?)\r
759 //        exponentSeparator = numberElements.length >= 9 ?\r
760 //            numberElements[7] : DecimalFormat.PATTERN_EXPONENT;\r
761 //        perMill = numberElements.length >= 9 ?\r
762 //            numberElements[8].charAt(0) : '\u2030';\r
763 //        infinity  = numberElements.length >= 10 ?\r
764 //            numberElements[9] : "\u221e";\r
765 //        NaN = numberElements.length >= 11 ?\r
766 //            numberElements[10] : "\ufffd";\r
767         exponentSeparator = numberElements[7];\r
768         perMill = numberElements[8].charAt(0);\r
769         infinity = numberElements[9];\r
770         NaN = numberElements[10];\r
771         \r
772         plusSign  =numberElements[11].charAt(0);\r
773         padEscape = DecimalFormat.PATTERN_PAD_ESCAPE;\r
774         sigDigit  = DecimalFormat.PATTERN_SIGNIFICANT_DIGIT;\r
775         \r
776         // Attempt to set the zero digit based on the numbering system for the locale requested\r
777         //\r
778         NumberingSystem ns = NumberingSystem.getInstance(locale);\r
779         if ( ns != null && ns.getRadix() == 10 && !ns.isAlgorithmic()) {\r
780             zeroDigit = ns.getDescription().charAt(0);\r
781         }\r
782 \r
783         // Obtain currency data from the currency API.  This is strictly\r
784         // for backward compatibility; we don't use DecimalFormatSymbols\r
785         // for currency data anymore.\r
786         String currname = null;\r
787         currency = Currency.getInstance(locale);\r
788         if (currency != null) {\r
789             intlCurrencySymbol = currency.getCurrencyCode();\r
790             boolean[] isChoiceFormat = new boolean[1];\r
791             currname = currency.getName(locale,\r
792                                     Currency.SYMBOL_NAME,\r
793                                     isChoiceFormat);\r
794             // If this is a ChoiceFormat currency, then format an\r
795             // arbitrary value; pick something != 1; more common.\r
796             currencySymbol = isChoiceFormat[0]\r
797                 ? new ChoiceFormat(currname).format(2.0)\r
798                 : currname;\r
799         } else {\r
800             intlCurrencySymbol = "XXX";\r
801             currencySymbol = "\u00A4"; // 'OX' currency symbol\r
802         }\r
803         // If there is a currency decimal, use it.\r
804         monetarySeparator = decimalSeparator;\r
805         monetaryGroupingSeparator = groupingSeparator;\r
806         Currency curr = Currency.getInstance(locale);\r
807         if(curr!=null){\r
808             String currencyCode = curr.getCurrencyCode();\r
809             if(currencyCode != null) {\r
810                 /* An explicit currency was requested */\r
811                 ICUResourceBundle resource = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale);\r
812                 ICUResourceBundle currencyRes = resource.getWithFallback("Currencies");\r
813                 try{\r
814                     currencyRes = currencyRes.getWithFallback(currencyCode);\r
815                     if(currencyRes.getSize()>2) {\r
816                         currencyRes = (ICUResourceBundle)currencyRes.get(2);\r
817                         currencyPattern = currencyRes.getString(0);\r
818                         monetarySeparator = currencyRes.getString(1).charAt(0);\r
819                         monetaryGroupingSeparator = currencyRes.getString(2).charAt(0);\r
820                     }\r
821                 }catch(MissingResourceException ex){\r
822                     /* else An explicit currency was requested and is unknown or locale data is malformed. */\r
823                     /* decimal format API will get the correct value later on. */\r
824                 }\r
825             }\r
826             /* else no currency keyword used. */\r
827         }\r
828         //monetarySeparator = numberElements[11].charAt(0);\r
829         \r
830         // Get Currency Spacing data. \r
831         currencySpcBeforeSym = new String[CURRENCY_SPC_INSERT+1];\r
832         currencySpcAfterSym = new String[CURRENCY_SPC_INSERT+1];\r
833         ICUResourceBundle curSpcBundle = (ICUResourceBundle)r.get(CURRENCY_SPACING);\r
834         if (curSpcBundle != null) {\r
835             ICUResourceBundle beforeCurBundle = (ICUResourceBundle)curSpcBundle.get(BEFORE_CURRENCY);\r
836             ICUResourceBundle afterCurBundle = (ICUResourceBundle)curSpcBundle.get(AFTER_CURRENCY);\r
837             for (int i = CURRENCY_SPC_CURRENCY_MATCH; i <= CURRENCY_SPC_INSERT; i++) {\r
838                 currencySpcBeforeSym[i] = beforeCurBundle.getStringWithFallback(CURRENCY_SPACING_KEYS[i]);\r
839                 currencySpcAfterSym[i] = afterCurBundle.getStringWithFallback(CURRENCY_SPACING_KEYS[i]);\r
840             }\r
841         }\r
842         \r
843     }\r
844 \r
845     /**\r
846      * Read the default serializable fields, then if <code>serialVersionOnStream</code>\r
847      * is less than 1, initialize <code>monetarySeparator</code> to be\r
848      * the same as <code>decimalSeparator</code> and <code>exponential</code>\r
849      * to be 'E'.\r
850      * Finally, set serialVersionOnStream back to the maximum allowed value so that\r
851      * default serialization will work properly if this object is streamed out again.\r
852      */\r
853     private void readObject(ObjectInputStream stream)\r
854         throws IOException, ClassNotFoundException {\r
855 \r
856         // TODO: it looks to me {dlf} that the serialization code was never updated\r
857         // to handle the actual/valid ulocale fields.\r
858 \r
859         stream.defaultReadObject();\r
860         ///CLOVER:OFF\r
861         // we don't have data for these old serialized forms any more\r
862         if (serialVersionOnStream < 1) {\r
863             // Didn't have monetarySeparator or exponential field;\r
864             // use defaults.\r
865             monetarySeparator = decimalSeparator;\r
866             exponential = 'E';\r
867         }\r
868         if (serialVersionOnStream < 2) {\r
869             padEscape = DecimalFormat.PATTERN_PAD_ESCAPE;\r
870             plusSign = DecimalFormat.PATTERN_PLUS_SIGN;\r
871             exponentSeparator = String.valueOf(exponential);\r
872             // Although we read the exponential field on stream to create the\r
873             // exponentSeparator, we don't do the reverse, since scientific\r
874             // notation isn't supported by the old classes, even though the\r
875             // symbol is there.\r
876         }\r
877         ///CLOVER:ON\r
878         if (serialVersionOnStream < 3) {\r
879             // Resurrected objects from old streams will have no\r
880             // locale.  There is no 100% fix for this.  A\r
881             // 90% fix is to construct a mapping of data back to\r
882             // locale, perhaps a hash of all our members.  This is\r
883             // expensive and doesn't seem worth it.\r
884             requestedLocale = Locale.getDefault();\r
885         }\r
886         if (serialVersionOnStream < 4) {\r
887             // use same default behavior as for versions with no Locale\r
888             ulocale = ULocale.forLocale(requestedLocale);\r
889         }\r
890         if (serialVersionOnStream < 5) {\r
891             // use the same one for groupingSeparator\r
892             monetaryGroupingSeparator = groupingSeparator;\r
893         }\r
894         if (serialVersionOnStream < 6) {\r
895             // Set null to CurrencySpacing related fields.\r
896             if (currencySpcBeforeSym == null) {\r
897                 currencySpcBeforeSym = new String[CURRENCY_SPC_INSERT+1];\r
898             }\r
899             if (currencySpcAfterSym == null) {\r
900                 currencySpcAfterSym = new String[CURRENCY_SPC_INSERT+1];\r
901             }\r
902             currencySpcBeforeSym[CURRENCY_SPC_CURRENCY_MATCH] = \r
903                 currencySpcAfterSym[CURRENCY_SPC_CURRENCY_MATCH] = DEFAULT_SPC_MATCH;\r
904             currencySpcBeforeSym[CURRENCT_SPC_SURROUNDING_MATCH] = \r
905                 currencySpcAfterSym[CURRENCT_SPC_SURROUNDING_MATCH] = DEFAULT_SPC_SUR_MATCH;\r
906             currencySpcBeforeSym[CURRENCY_SPC_INSERT] = \r
907                 currencySpcAfterSym[CURRENCY_SPC_INSERT] = DEFAULT_SPC_INSERT;\r
908         }\r
909         serialVersionOnStream = currentSerialVersion;\r
910 \r
911     // recreate\r
912     currency = Currency.getInstance(intlCurrencySymbol);\r
913     }\r
914 \r
915     /**\r
916      * Character used for zero.\r
917      *\r
918      * @serial\r
919      * @see #getZeroDigit\r
920      */\r
921     private  char    zeroDigit;\r
922 \r
923     /**\r
924      * Character used for thousands separator.\r
925      *\r
926      * @serial\r
927      * @see #getGroupingSeparator\r
928      */\r
929     private  char    groupingSeparator;\r
930 \r
931     /**\r
932      * Character used for decimal sign.\r
933      *\r
934      * @serial\r
935      * @see #getDecimalSeparator\r
936      */\r
937     private  char    decimalSeparator;\r
938 \r
939     /**\r
940      * Character used for mille percent sign.\r
941      *\r
942      * @serial\r
943      * @see #getPerMill\r
944      */\r
945     private  char    perMill;\r
946 \r
947     /**\r
948      * Character used for percent sign.\r
949      * @serial\r
950      * @see #getPercent\r
951      */\r
952     private  char    percent;\r
953 \r
954     /**\r
955      * Character used for a digit in a pattern.\r
956      *\r
957      * @serial\r
958      * @see #getDigit\r
959      */\r
960     private  char    digit;\r
961 \r
962     /**\r
963      * Character used for a significant digit in a pattern.\r
964      *\r
965      * @serial\r
966      * @see #getSignificantDigit\r
967      */\r
968     private  char    sigDigit;\r
969 \r
970     /**\r
971      * Character used to separate positive and negative subpatterns\r
972      * in a pattern.\r
973      *\r
974      * @serial\r
975      * @see #getPatternSeparator\r
976      */\r
977     private  char    patternSeparator;\r
978 \r
979     /**\r
980      * Character used to represent infinity.\r
981      * @serial\r
982      * @see #getInfinity\r
983      */\r
984     private  String  infinity;\r
985 \r
986     /**\r
987      * Character used to represent NaN.\r
988      * @serial\r
989      * @see #getNaN\r
990      */\r
991     private  String  NaN;\r
992 \r
993     /**\r
994      * Character used to represent minus sign.\r
995      * @serial\r
996      * @see #getMinusSign\r
997      */\r
998     private  char    minusSign;\r
999 \r
1000     /**\r
1001      * String denoting the local currency, e.g. "$".\r
1002      * @serial\r
1003      * @see #getCurrencySymbol\r
1004      */\r
1005     private  String  currencySymbol;\r
1006 \r
1007     /**\r
1008      * International string denoting the local currency, e.g. "USD".\r
1009      * @serial\r
1010      * @see #getInternationalCurrencySymbol\r
1011      */\r
1012     private  String  intlCurrencySymbol;\r
1013 \r
1014     /**\r
1015      * The decimal separator used when formatting currency values.\r
1016      * @serial\r
1017      * @see #getMonetaryDecimalSeparator\r
1018      */\r
1019     private  char    monetarySeparator; // Field new in JDK 1.1.6\r
1020 \r
1021     /**\r
1022      * The decimal separator used when formatting currency values.\r
1023      * @serial\r
1024      * @see #getMonetaryGroupingSeparator\r
1025      */\r
1026     private  char    monetaryGroupingSeparator; // Field new in JDK 1.1.6\r
1027 \r
1028     /**\r
1029      * The character used to distinguish the exponent in a number formatted\r
1030      * in exponential notation, e.g. 'E' for a number such as "1.23E45".\r
1031      * <p>\r
1032      * Note that this field has been superseded by <code>exponentSeparator</code>.\r
1033      * It is retained for backward compatibility.\r
1034      *\r
1035      * @serial\r
1036      */\r
1037     private  char    exponential;       // Field new in JDK 1.1.6\r
1038 \r
1039     /**\r
1040      * The string used to separate the mantissa from the exponent.\r
1041      * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.\r
1042      * <p>\r
1043      * Note that this supersedes the <code>exponential</code> field.\r
1044      *\r
1045      * @serial\r
1046      * @since AlphaWorks\r
1047      */\r
1048     private String exponentSeparator;\r
1049 \r
1050     /**\r
1051      * <strong><font face=helvetica color=red>NEW</font></strong>\r
1052      * The character used to indicate a padding character in a format,\r
1053      * e.g., '*' in a pattern such as "$*_#,##0.00".\r
1054      * @serial\r
1055      * @since AlphaWorks\r
1056      */\r
1057     private char padEscape;\r
1058 \r
1059     /**\r
1060      * <strong><font face=helvetica color=red>NEW</font></strong>\r
1061      * The character used to indicate a plus sign.\r
1062      * @serial\r
1063      * @since AlphaWorks\r
1064      */\r
1065     private char plusSign;\r
1066 \r
1067     /**\r
1068      * The locale for which this object was constructed.  Set to the\r
1069      * default locale for objects resurrected from old streams.\r
1070      * @since ICU 2.2\r
1071      */\r
1072     private Locale requestedLocale;\r
1073 \r
1074     /**\r
1075      * The requested ULocale.  We keep the old locale for serialization compatibility.\r
1076      * @since IDU 3.2\r
1077      */\r
1078     private ULocale ulocale;\r
1079 \r
1080     // Proclaim JDK 1.1 FCS compatibility\r
1081     private static final long serialVersionUID = 5772796243397350300L;\r
1082 \r
1083     // The internal serial version which says which version was written\r
1084     // - 0 (default) for version up to JDK 1.1.5\r
1085     // - 1 for version from JDK 1.1.6, which includes two new fields:\r
1086     //     monetarySeparator and exponential.\r
1087     // - 2 for version from AlphaWorks, which includes 3 new fields:\r
1088     //     padEscape, exponentSeparator, and plusSign.\r
1089     // - 3 for ICU 2.2, which includes the locale field\r
1090     // - 4 for ICU 3.2, which includes the ULocale field\r
1091     // - 5 for ICU 3.6, which includes the monetaryGroupingSeparator field\r
1092     // - 6 for ICU 4.2, which includes the currencySpc* fields\r
1093     private static final int currentSerialVersion = 6;\r
1094     \r
1095     /**\r
1096      * Describes the version of <code>DecimalFormatSymbols</code> present on the stream.\r
1097      * Possible values are:\r
1098      * <ul>\r
1099      * <li><b>0</b> (or uninitialized): versions prior to JDK 1.1.6.\r
1100      *\r
1101      * <li><b>1</b>: Versions written by JDK 1.1.6 or later, which includes\r
1102      *      two new fields: <code>monetarySeparator</code> and <code>exponential</code>.\r
1103      * <li><b>2</b>: Version for AlphaWorks.  Adds padEscape, exponentSeparator,\r
1104      *      and plusSign.\r
1105      * </ul>\r
1106      * When streaming out a <code>DecimalFormatSymbols</code>, the most recent format\r
1107      * (corresponding to the highest allowable <code>serialVersionOnStream</code>)\r
1108      * is always written.\r
1109      *\r
1110      * @serial\r
1111      */\r
1112     private int serialVersionOnStream = currentSerialVersion;\r
1113 \r
1114     /**\r
1115      * cache to hold the NumberElements of a Locale.\r
1116      */\r
1117     private static final Hashtable cachedLocaleData = new Hashtable(3);\r
1118     \r
1119     /**\r
1120      * \r
1121      */\r
1122     private String  currencyPattern = null;\r
1123     \r
1124     // -------- BEGIN ULocale boilerplate --------\r
1125 \r
1126     /**\r
1127      * Return the locale that was used to create this object, or null.\r
1128      * This may may differ from the locale requested at the time of\r
1129      * this object's creation.  For example, if an object is created\r
1130      * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be\r
1131      * drawn from <tt>en</tt> (the <i>actual</i> locale), and\r
1132      * <tt>en_US</tt> may be the most specific locale that exists (the\r
1133      * <i>valid</i> locale).\r
1134      *\r
1135      * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8\r
1136      * contains a partial preview implementation.  The * <i>actual</i>\r
1137      * locale is returned correctly, but the <i>valid</i> locale is\r
1138      * not, in most cases.\r
1139      * @param type type of information requested, either {@link\r
1140      * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link\r
1141      * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.\r
1142      * @return the information specified by <i>type</i>, or null if\r
1143      * this object was not constructed from locale data.\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      * @draft ICU 2.8 (retain)\r
1148      * @provisional This API might change or be removed in a future release.\r
1149      */\r
1150     public final ULocale getLocale(ULocale.Type type) {\r
1151         return type == ULocale.ACTUAL_LOCALE ?\r
1152             this.actualLocale : this.validLocale;\r
1153     }\r
1154 \r
1155     /**\r
1156      * Set information about the locales that were used to create this\r
1157      * object.  If the object was not constructed from locale data,\r
1158      * both arguments should be set to null.  Otherwise, neither\r
1159      * should be null.  The actual locale must be at the same level or\r
1160      * less specific than the valid locale.  This method is intended\r
1161      * for use by factories or other entities that create objects of\r
1162      * this class.\r
1163      * @param valid the most specific locale containing any resource\r
1164      * data, or null\r
1165      * @param actual the locale containing data used to construct this\r
1166      * object, or null\r
1167      * @see com.ibm.icu.util.ULocale\r
1168      * @see com.ibm.icu.util.ULocale#VALID_LOCALE\r
1169      * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE\r
1170      * @internal\r
1171      */\r
1172     final void setLocale(ULocale valid, ULocale actual) {\r
1173         // Change the following to an assertion later\r
1174         if ((valid == null) != (actual == null)) {\r
1175             ///CLOVER:OFF\r
1176             throw new IllegalArgumentException();\r
1177             ///CLOVER:ON\r
1178         }\r
1179         // Another check we could do is that the actual locale is at\r
1180         // the same level or less specific than the valid locale.\r
1181         this.validLocale = valid;\r
1182         this.actualLocale = actual;\r
1183     }\r
1184 \r
1185     /**\r
1186      * The most specific locale containing any resource data, or null.\r
1187      * @see com.ibm.icu.util.ULocale\r
1188      * @internal\r
1189      */\r
1190     private ULocale validLocale;\r
1191 \r
1192     /**\r
1193      * The locale containing data used to construct this object, or\r
1194      * null.\r
1195      * @see com.ibm.icu.util.ULocale\r
1196      * @internal\r
1197      */\r
1198     private ULocale actualLocale;\r
1199 \r
1200     // not serialized, reconstructed from intlCurrencyCode\r
1201     private transient Currency currency;\r
1202 \r
1203     // -------- END ULocale boilerplate --------\r
1204 }\r