|
1 /* |
|
2 * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Sun designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Sun in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 * have any questions. |
|
24 */ |
|
25 |
|
26 /* |
|
27 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved |
|
28 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved |
|
29 * |
|
30 * The original version of this source code and documentation is copyrighted |
|
31 * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These |
|
32 * materials are provided under terms of a License Agreement between Taligent |
|
33 * and Sun. This technology is protected by multiple US and International |
|
34 * patents. This notice and attribution to Taligent may not be removed. |
|
35 * Taligent is a registered trademark of Taligent, Inc. |
|
36 * |
|
37 */ |
|
38 |
|
39 package java.text; |
|
40 |
|
41 import java.io.IOException; |
|
42 import java.io.ObjectInputStream; |
|
43 import java.io.Serializable; |
|
44 import java.text.spi.DecimalFormatSymbolsProvider; |
|
45 import java.util.Currency; |
|
46 import java.util.Hashtable; |
|
47 import java.util.Locale; |
|
48 import java.util.ResourceBundle; |
|
49 import java.util.spi.LocaleServiceProvider; |
|
50 import sun.util.LocaleServiceProviderPool; |
|
51 import sun.util.resources.LocaleData; |
|
52 |
|
53 /** |
|
54 * This class represents the set of symbols (such as the decimal separator, |
|
55 * the grouping separator, and so on) needed by <code>DecimalFormat</code> |
|
56 * to format numbers. <code>DecimalFormat</code> creates for itself an instance of |
|
57 * <code>DecimalFormatSymbols</code> from its locale data. If you need to change any |
|
58 * of these symbols, you can get the <code>DecimalFormatSymbols</code> object from |
|
59 * your <code>DecimalFormat</code> and modify it. |
|
60 * |
|
61 * @see java.util.Locale |
|
62 * @see DecimalFormat |
|
63 * @author Mark Davis |
|
64 * @author Alan Liu |
|
65 */ |
|
66 |
|
67 public class DecimalFormatSymbols implements Cloneable, Serializable { |
|
68 |
|
69 /** |
|
70 * Create a DecimalFormatSymbols object for the default locale. |
|
71 * This constructor can only construct instances for the locales |
|
72 * supported by the Java runtime environment, not for those |
|
73 * supported by installed |
|
74 * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider} |
|
75 * implementations. For full locale coverage, use the |
|
76 * {@link #getInstance(Locale) getInstance} method. |
|
77 */ |
|
78 public DecimalFormatSymbols() { |
|
79 initialize( Locale.getDefault() ); |
|
80 } |
|
81 |
|
82 /** |
|
83 * Create a DecimalFormatSymbols object for the given locale. |
|
84 * This constructor can only construct instances for the locales |
|
85 * supported by the Java runtime environment, not for those |
|
86 * supported by installed |
|
87 * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider} |
|
88 * implementations. For full locale coverage, use the |
|
89 * {@link #getInstance(Locale) getInstance} method. |
|
90 * |
|
91 * @exception NullPointerException if <code>locale</code> is null |
|
92 */ |
|
93 public DecimalFormatSymbols( Locale locale ) { |
|
94 initialize( locale ); |
|
95 } |
|
96 |
|
97 /** |
|
98 * Returns an array of all locales for which the |
|
99 * <code>getInstance</code> methods of this class can return |
|
100 * localized instances. |
|
101 * The returned array represents the union of locales supported by the Java |
|
102 * runtime and by installed |
|
103 * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider} |
|
104 * implementations. It must contain at least a <code>Locale</code> |
|
105 * instance equal to {@link java.util.Locale#US Locale.US}. |
|
106 * |
|
107 * @return An array of locales for which localized |
|
108 * <code>DecimalFormatSymbols</code> instances are available. |
|
109 * @since 1.6 |
|
110 */ |
|
111 public static Locale[] getAvailableLocales() { |
|
112 LocaleServiceProviderPool pool = |
|
113 LocaleServiceProviderPool.getPool(DecimalFormatSymbolsProvider.class); |
|
114 return pool.getAvailableLocales(); |
|
115 } |
|
116 |
|
117 /** |
|
118 * Gets the <code>DecimalFormatSymbols</code> instance for the default |
|
119 * locale. This method provides access to <code>DecimalFormatSymbols</code> |
|
120 * instances for locales supported by the Java runtime itself as well |
|
121 * as for those supported by installed |
|
122 * {@link java.text.spi.DecimalFormatSymbolsProvider |
|
123 * DecimalFormatSymbolsProvider} implementations. |
|
124 * @return a <code>DecimalFormatSymbols</code> instance. |
|
125 * @since 1.6 |
|
126 */ |
|
127 public static final DecimalFormatSymbols getInstance() { |
|
128 return getInstance(Locale.getDefault()); |
|
129 } |
|
130 |
|
131 /** |
|
132 * Gets the <code>DecimalFormatSymbols</code> instance for the specified |
|
133 * locale. This method provides access to <code>DecimalFormatSymbols</code> |
|
134 * instances for locales supported by the Java runtime itself as well |
|
135 * as for those supported by installed |
|
136 * {@link java.text.spi.DecimalFormatSymbolsProvider |
|
137 * DecimalFormatSymbolsProvider} implementations. |
|
138 * @param locale the desired locale. |
|
139 * @return a <code>DecimalFormatSymbols</code> instance. |
|
140 * @exception NullPointerException if <code>locale</code> is null |
|
141 * @since 1.6 |
|
142 */ |
|
143 public static final DecimalFormatSymbols getInstance(Locale locale) { |
|
144 |
|
145 // Check whether a provider can provide an implementation that's closer |
|
146 // to the requested locale than what the Java runtime itself can provide. |
|
147 LocaleServiceProviderPool pool = |
|
148 LocaleServiceProviderPool.getPool(DecimalFormatSymbolsProvider.class); |
|
149 if (pool.hasProviders()) { |
|
150 DecimalFormatSymbols providersInstance = pool.getLocalizedObject( |
|
151 DecimalFormatSymbolsGetter.INSTANCE, locale); |
|
152 if (providersInstance != null) { |
|
153 return providersInstance; |
|
154 } |
|
155 } |
|
156 |
|
157 return new DecimalFormatSymbols(locale); |
|
158 } |
|
159 |
|
160 /** |
|
161 * Gets the character used for zero. Different for Arabic, etc. |
|
162 */ |
|
163 public char getZeroDigit() { |
|
164 return zeroDigit; |
|
165 } |
|
166 |
|
167 /** |
|
168 * Sets the character used for zero. Different for Arabic, etc. |
|
169 */ |
|
170 public void setZeroDigit(char zeroDigit) { |
|
171 this.zeroDigit = zeroDigit; |
|
172 } |
|
173 |
|
174 /** |
|
175 * Gets the character used for thousands separator. Different for French, etc. |
|
176 */ |
|
177 public char getGroupingSeparator() { |
|
178 return groupingSeparator; |
|
179 } |
|
180 |
|
181 /** |
|
182 * Sets the character used for thousands separator. Different for French, etc. |
|
183 */ |
|
184 public void setGroupingSeparator(char groupingSeparator) { |
|
185 this.groupingSeparator = groupingSeparator; |
|
186 } |
|
187 |
|
188 /** |
|
189 * Gets the character used for decimal sign. Different for French, etc. |
|
190 */ |
|
191 public char getDecimalSeparator() { |
|
192 return decimalSeparator; |
|
193 } |
|
194 |
|
195 /** |
|
196 * Sets the character used for decimal sign. Different for French, etc. |
|
197 */ |
|
198 public void setDecimalSeparator(char decimalSeparator) { |
|
199 this.decimalSeparator = decimalSeparator; |
|
200 } |
|
201 |
|
202 /** |
|
203 * Gets the character used for per mille sign. Different for Arabic, etc. |
|
204 */ |
|
205 public char getPerMill() { |
|
206 return perMill; |
|
207 } |
|
208 |
|
209 /** |
|
210 * Sets the character used for per mille sign. Different for Arabic, etc. |
|
211 */ |
|
212 public void setPerMill(char perMill) { |
|
213 this.perMill = perMill; |
|
214 } |
|
215 |
|
216 /** |
|
217 * Gets the character used for percent sign. Different for Arabic, etc. |
|
218 */ |
|
219 public char getPercent() { |
|
220 return percent; |
|
221 } |
|
222 |
|
223 /** |
|
224 * Sets the character used for percent sign. Different for Arabic, etc. |
|
225 */ |
|
226 public void setPercent(char percent) { |
|
227 this.percent = percent; |
|
228 } |
|
229 |
|
230 /** |
|
231 * Gets the character used for a digit in a pattern. |
|
232 */ |
|
233 public char getDigit() { |
|
234 return digit; |
|
235 } |
|
236 |
|
237 /** |
|
238 * Sets the character used for a digit in a pattern. |
|
239 */ |
|
240 public void setDigit(char digit) { |
|
241 this.digit = digit; |
|
242 } |
|
243 |
|
244 /** |
|
245 * Gets the character used to separate positive and negative subpatterns |
|
246 * in a pattern. |
|
247 */ |
|
248 public char getPatternSeparator() { |
|
249 return patternSeparator; |
|
250 } |
|
251 |
|
252 /** |
|
253 * Sets the character used to separate positive and negative subpatterns |
|
254 * in a pattern. |
|
255 */ |
|
256 public void setPatternSeparator(char patternSeparator) { |
|
257 this.patternSeparator = patternSeparator; |
|
258 } |
|
259 |
|
260 /** |
|
261 * Gets the string used to represent infinity. Almost always left |
|
262 * unchanged. |
|
263 */ |
|
264 public String getInfinity() { |
|
265 return infinity; |
|
266 } |
|
267 |
|
268 /** |
|
269 * Sets the string used to represent infinity. Almost always left |
|
270 * unchanged. |
|
271 */ |
|
272 public void setInfinity(String infinity) { |
|
273 this.infinity = infinity; |
|
274 } |
|
275 |
|
276 /** |
|
277 * Gets the string used to represent "not a number". Almost always left |
|
278 * unchanged. |
|
279 */ |
|
280 public String getNaN() { |
|
281 return NaN; |
|
282 } |
|
283 |
|
284 /** |
|
285 * Sets the string used to represent "not a number". Almost always left |
|
286 * unchanged. |
|
287 */ |
|
288 public void setNaN(String NaN) { |
|
289 this.NaN = NaN; |
|
290 } |
|
291 |
|
292 /** |
|
293 * Gets the character used to represent minus sign. If no explicit |
|
294 * negative format is specified, one is formed by prefixing |
|
295 * minusSign to the positive format. |
|
296 */ |
|
297 public char getMinusSign() { |
|
298 return minusSign; |
|
299 } |
|
300 |
|
301 /** |
|
302 * Sets the character used to represent minus sign. If no explicit |
|
303 * negative format is specified, one is formed by prefixing |
|
304 * minusSign to the positive format. |
|
305 */ |
|
306 public void setMinusSign(char minusSign) { |
|
307 this.minusSign = minusSign; |
|
308 } |
|
309 |
|
310 /** |
|
311 * Returns the currency symbol for the currency of these |
|
312 * DecimalFormatSymbols in their locale. |
|
313 * @since 1.2 |
|
314 */ |
|
315 public String getCurrencySymbol() |
|
316 { |
|
317 return currencySymbol; |
|
318 } |
|
319 |
|
320 /** |
|
321 * Sets the currency symbol for the currency of these |
|
322 * DecimalFormatSymbols in their locale. |
|
323 * @since 1.2 |
|
324 */ |
|
325 public void setCurrencySymbol(String currency) |
|
326 { |
|
327 currencySymbol = currency; |
|
328 } |
|
329 |
|
330 /** |
|
331 * Returns the ISO 4217 currency code of the currency of these |
|
332 * DecimalFormatSymbols. |
|
333 * @since 1.2 |
|
334 */ |
|
335 public String getInternationalCurrencySymbol() |
|
336 { |
|
337 return intlCurrencySymbol; |
|
338 } |
|
339 |
|
340 /** |
|
341 * Sets the ISO 4217 currency code of the currency of these |
|
342 * DecimalFormatSymbols. |
|
343 * If the currency code is valid (as defined by |
|
344 * {@link java.util.Currency#getInstance(java.lang.String) Currency.getInstance}), |
|
345 * this also sets the currency attribute to the corresponding Currency |
|
346 * instance and the currency symbol attribute to the currency's symbol |
|
347 * in the DecimalFormatSymbols' locale. If the currency code is not valid, |
|
348 * then the currency attribute is set to null and the currency symbol |
|
349 * attribute is not modified. |
|
350 * |
|
351 * @see #setCurrency |
|
352 * @see #setCurrencySymbol |
|
353 * @since 1.2 |
|
354 */ |
|
355 public void setInternationalCurrencySymbol(String currencyCode) |
|
356 { |
|
357 intlCurrencySymbol = currencyCode; |
|
358 currency = null; |
|
359 if (currencyCode != null) { |
|
360 try { |
|
361 currency = Currency.getInstance(currencyCode); |
|
362 currencySymbol = currency.getSymbol(); |
|
363 } catch (IllegalArgumentException e) { |
|
364 } |
|
365 } |
|
366 } |
|
367 |
|
368 /** |
|
369 * Gets the currency of these DecimalFormatSymbols. May be null if the |
|
370 * currency symbol attribute was previously set to a value that's not |
|
371 * a valid ISO 4217 currency code. |
|
372 * |
|
373 * @return the currency used, or null |
|
374 * @since 1.4 |
|
375 */ |
|
376 public Currency getCurrency() { |
|
377 return currency; |
|
378 } |
|
379 |
|
380 /** |
|
381 * Sets the currency of these DecimalFormatSymbols. |
|
382 * This also sets the currency symbol attribute to the currency's symbol |
|
383 * in the DecimalFormatSymbols' locale, and the international currency |
|
384 * symbol attribute to the currency's ISO 4217 currency code. |
|
385 * |
|
386 * @param currency the new currency to be used |
|
387 * @exception NullPointerException if <code>currency</code> is null |
|
388 * @since 1.4 |
|
389 * @see #setCurrencySymbol |
|
390 * @see #setInternationalCurrencySymbol |
|
391 */ |
|
392 public void setCurrency(Currency currency) { |
|
393 if (currency == null) { |
|
394 throw new NullPointerException(); |
|
395 } |
|
396 this.currency = currency; |
|
397 intlCurrencySymbol = currency.getCurrencyCode(); |
|
398 currencySymbol = currency.getSymbol(locale); |
|
399 } |
|
400 |
|
401 |
|
402 /** |
|
403 * Returns the monetary decimal separator. |
|
404 * @since 1.2 |
|
405 */ |
|
406 public char getMonetaryDecimalSeparator() |
|
407 { |
|
408 return monetarySeparator; |
|
409 } |
|
410 |
|
411 /** |
|
412 * Sets the monetary decimal separator. |
|
413 * @since 1.2 |
|
414 */ |
|
415 public void setMonetaryDecimalSeparator(char sep) |
|
416 { |
|
417 monetarySeparator = sep; |
|
418 } |
|
419 |
|
420 //------------------------------------------------------------ |
|
421 // BEGIN Package Private methods ... to be made public later |
|
422 //------------------------------------------------------------ |
|
423 |
|
424 /** |
|
425 * Returns the character used to separate the mantissa from the exponent. |
|
426 */ |
|
427 char getExponentialSymbol() |
|
428 { |
|
429 return exponential; |
|
430 } |
|
431 /** |
|
432 * Returns the string used to separate the mantissa from the exponent. |
|
433 * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4. |
|
434 * |
|
435 * @return the exponent separator string |
|
436 * @see #setExponentSeparator(java.lang.String) |
|
437 * @since 1.6 |
|
438 */ |
|
439 public String getExponentSeparator() |
|
440 { |
|
441 return exponentialSeparator; |
|
442 } |
|
443 |
|
444 /** |
|
445 * Sets the character used to separate the mantissa from the exponent. |
|
446 */ |
|
447 void setExponentialSymbol(char exp) |
|
448 { |
|
449 exponential = exp; |
|
450 } |
|
451 |
|
452 /** |
|
453 * Sets the string used to separate the mantissa from the exponent. |
|
454 * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4. |
|
455 * |
|
456 * @param exp the exponent separator string |
|
457 * @exception NullPointerException if <code>exp</code> is null |
|
458 * @see #getExponentSeparator() |
|
459 * @since 1.6 |
|
460 */ |
|
461 public void setExponentSeparator(String exp) |
|
462 { |
|
463 if (exp == null) { |
|
464 throw new NullPointerException(); |
|
465 } |
|
466 exponentialSeparator = exp; |
|
467 } |
|
468 |
|
469 |
|
470 //------------------------------------------------------------ |
|
471 // END Package Private methods ... to be made public later |
|
472 //------------------------------------------------------------ |
|
473 |
|
474 /** |
|
475 * Standard override. |
|
476 */ |
|
477 public Object clone() { |
|
478 try { |
|
479 return (DecimalFormatSymbols)super.clone(); |
|
480 // other fields are bit-copied |
|
481 } catch (CloneNotSupportedException e) { |
|
482 throw new InternalError(); |
|
483 } |
|
484 } |
|
485 |
|
486 /** |
|
487 * Override equals. |
|
488 */ |
|
489 public boolean equals(Object obj) { |
|
490 if (obj == null) return false; |
|
491 if (this == obj) return true; |
|
492 if (getClass() != obj.getClass()) return false; |
|
493 DecimalFormatSymbols other = (DecimalFormatSymbols) obj; |
|
494 return (zeroDigit == other.zeroDigit && |
|
495 groupingSeparator == other.groupingSeparator && |
|
496 decimalSeparator == other.decimalSeparator && |
|
497 percent == other.percent && |
|
498 perMill == other.perMill && |
|
499 digit == other.digit && |
|
500 minusSign == other.minusSign && |
|
501 patternSeparator == other.patternSeparator && |
|
502 infinity.equals(other.infinity) && |
|
503 NaN.equals(other.NaN) && |
|
504 currencySymbol.equals(other.currencySymbol) && |
|
505 intlCurrencySymbol.equals(other.intlCurrencySymbol) && |
|
506 currency == other.currency && |
|
507 monetarySeparator == other.monetarySeparator && |
|
508 exponentialSeparator.equals(other.exponentialSeparator) && |
|
509 locale.equals(other.locale)); |
|
510 } |
|
511 |
|
512 /** |
|
513 * Override hashCode. |
|
514 */ |
|
515 public int hashCode() { |
|
516 int result = zeroDigit; |
|
517 result = result * 37 + groupingSeparator; |
|
518 result = result * 37 + decimalSeparator; |
|
519 return result; |
|
520 } |
|
521 |
|
522 /** |
|
523 * Initializes the symbols from the FormatData resource bundle. |
|
524 */ |
|
525 private void initialize( Locale locale ) { |
|
526 this.locale = locale; |
|
527 |
|
528 // get resource bundle data - try the cache first |
|
529 boolean needCacheUpdate = false; |
|
530 Object[] data = (Object[]) cachedLocaleData.get(locale); |
|
531 if (data == null) { /* cache miss */ |
|
532 data = new Object[3]; |
|
533 ResourceBundle rb = LocaleData.getNumberFormatData(locale); |
|
534 data[0] = rb.getStringArray("NumberElements"); |
|
535 needCacheUpdate = true; |
|
536 } |
|
537 |
|
538 String[] numberElements = (String[]) data[0]; |
|
539 |
|
540 decimalSeparator = numberElements[0].charAt(0); |
|
541 groupingSeparator = numberElements[1].charAt(0); |
|
542 patternSeparator = numberElements[2].charAt(0); |
|
543 percent = numberElements[3].charAt(0); |
|
544 zeroDigit = numberElements[4].charAt(0); //different for Arabic,etc. |
|
545 digit = numberElements[5].charAt(0); |
|
546 minusSign = numberElements[6].charAt(0); |
|
547 exponential = numberElements[7].charAt(0); |
|
548 exponentialSeparator = numberElements[7]; //string representation new since 1.6 |
|
549 perMill = numberElements[8].charAt(0); |
|
550 infinity = numberElements[9]; |
|
551 NaN = numberElements[10]; |
|
552 |
|
553 // Try to obtain the currency used in the locale's country. |
|
554 // Check for empty country string separately because it's a valid |
|
555 // country ID for Locale (and used for the C locale), but not a valid |
|
556 // ISO 3166 country code, and exceptions are expensive. |
|
557 if (!"".equals(locale.getCountry())) { |
|
558 try { |
|
559 currency = Currency.getInstance(locale); |
|
560 } catch (IllegalArgumentException e) { |
|
561 // use default values below for compatibility |
|
562 } |
|
563 } |
|
564 if (currency != null) { |
|
565 intlCurrencySymbol = currency.getCurrencyCode(); |
|
566 if (data[1] != null && data[1] == intlCurrencySymbol) { |
|
567 currencySymbol = (String) data[2]; |
|
568 } else { |
|
569 currencySymbol = currency.getSymbol(locale); |
|
570 data[1] = intlCurrencySymbol; |
|
571 data[2] = currencySymbol; |
|
572 needCacheUpdate = true; |
|
573 } |
|
574 } else { |
|
575 // default values |
|
576 intlCurrencySymbol = "XXX"; |
|
577 try { |
|
578 currency = Currency.getInstance(intlCurrencySymbol); |
|
579 } catch (IllegalArgumentException e) { |
|
580 } |
|
581 currencySymbol = "\u00A4"; |
|
582 } |
|
583 // Currently the monetary decimal separator is the same as the |
|
584 // standard decimal separator for all locales that we support. |
|
585 // If that changes, add a new entry to NumberElements. |
|
586 monetarySeparator = decimalSeparator; |
|
587 |
|
588 if (needCacheUpdate) { |
|
589 cachedLocaleData.put(locale, data); |
|
590 } |
|
591 } |
|
592 |
|
593 /** |
|
594 * Reads the default serializable fields, provides default values for objects |
|
595 * in older serial versions, and initializes non-serializable fields. |
|
596 * If <code>serialVersionOnStream</code> |
|
597 * is less than 1, initializes <code>monetarySeparator</code> to be |
|
598 * the same as <code>decimalSeparator</code> and <code>exponential</code> |
|
599 * to be 'E'. |
|
600 * If <code>serialVersionOnStream</code> is less than 2, |
|
601 * initializes <code>locale</code>to the root locale, and initializes |
|
602 * If <code>serialVersionOnStream</code> is less than 3, it initializes |
|
603 * <code>exponentialSeparator</code> using <code>exponential</code>. |
|
604 * Sets <code>serialVersionOnStream</code> back to the maximum allowed value so that |
|
605 * default serialization will work properly if this object is streamed out again. |
|
606 * Initializes the currency from the intlCurrencySymbol field. |
|
607 * |
|
608 * @since JDK 1.1.6 |
|
609 */ |
|
610 private void readObject(ObjectInputStream stream) |
|
611 throws IOException, ClassNotFoundException { |
|
612 stream.defaultReadObject(); |
|
613 if (serialVersionOnStream < 1) { |
|
614 // Didn't have monetarySeparator or exponential field; |
|
615 // use defaults. |
|
616 monetarySeparator = decimalSeparator; |
|
617 exponential = 'E'; |
|
618 } |
|
619 if (serialVersionOnStream < 2) { |
|
620 // didn't have locale; use root locale |
|
621 locale = Locale.ROOT; |
|
622 } |
|
623 if (serialVersionOnStream < 3) { |
|
624 // didn't have exponentialSeparator. Create one using exponential |
|
625 exponentialSeparator = Character.toString(exponential); |
|
626 } |
|
627 serialVersionOnStream = currentSerialVersion; |
|
628 |
|
629 if (intlCurrencySymbol != null) { |
|
630 try { |
|
631 currency = Currency.getInstance(intlCurrencySymbol); |
|
632 } catch (IllegalArgumentException e) { |
|
633 } |
|
634 } |
|
635 } |
|
636 |
|
637 /** |
|
638 * Character used for zero. |
|
639 * |
|
640 * @serial |
|
641 * @see #getZeroDigit |
|
642 */ |
|
643 private char zeroDigit; |
|
644 |
|
645 /** |
|
646 * Character used for thousands separator. |
|
647 * |
|
648 * @serial |
|
649 * @see #getGroupingSeparator |
|
650 */ |
|
651 private char groupingSeparator; |
|
652 |
|
653 /** |
|
654 * Character used for decimal sign. |
|
655 * |
|
656 * @serial |
|
657 * @see #getDecimalSeparator |
|
658 */ |
|
659 private char decimalSeparator; |
|
660 |
|
661 /** |
|
662 * Character used for per mille sign. |
|
663 * |
|
664 * @serial |
|
665 * @see #getPerMill |
|
666 */ |
|
667 private char perMill; |
|
668 |
|
669 /** |
|
670 * Character used for percent sign. |
|
671 * @serial |
|
672 * @see #getPercent |
|
673 */ |
|
674 private char percent; |
|
675 |
|
676 /** |
|
677 * Character used for a digit in a pattern. |
|
678 * |
|
679 * @serial |
|
680 * @see #getDigit |
|
681 */ |
|
682 private char digit; |
|
683 |
|
684 /** |
|
685 * Character used to separate positive and negative subpatterns |
|
686 * in a pattern. |
|
687 * |
|
688 * @serial |
|
689 * @see #getPatternSeparator |
|
690 */ |
|
691 private char patternSeparator; |
|
692 |
|
693 /** |
|
694 * String used to represent infinity. |
|
695 * @serial |
|
696 * @see #getInfinity |
|
697 */ |
|
698 private String infinity; |
|
699 |
|
700 /** |
|
701 * String used to represent "not a number". |
|
702 * @serial |
|
703 * @see #getNaN |
|
704 */ |
|
705 private String NaN; |
|
706 |
|
707 /** |
|
708 * Character used to represent minus sign. |
|
709 * @serial |
|
710 * @see #getMinusSign |
|
711 */ |
|
712 private char minusSign; |
|
713 |
|
714 /** |
|
715 * String denoting the local currency, e.g. "$". |
|
716 * @serial |
|
717 * @see #getCurrencySymbol |
|
718 */ |
|
719 private String currencySymbol; |
|
720 |
|
721 /** |
|
722 * ISO 4217 currency code denoting the local currency, e.g. "USD". |
|
723 * @serial |
|
724 * @see #getInternationalCurrencySymbol |
|
725 */ |
|
726 private String intlCurrencySymbol; |
|
727 |
|
728 /** |
|
729 * The decimal separator used when formatting currency values. |
|
730 * @serial |
|
731 * @since JDK 1.1.6 |
|
732 * @see #getMonetaryDecimalSeparator |
|
733 */ |
|
734 private char monetarySeparator; // Field new in JDK 1.1.6 |
|
735 |
|
736 /** |
|
737 * The character used to distinguish the exponent in a number formatted |
|
738 * in exponential notation, e.g. 'E' for a number such as "1.23E45". |
|
739 * <p> |
|
740 * Note that the public API provides no way to set this field, |
|
741 * even though it is supported by the implementation and the stream format. |
|
742 * The intent is that this will be added to the API in the future. |
|
743 * |
|
744 * @serial |
|
745 * @since JDK 1.1.6 |
|
746 */ |
|
747 private char exponential; // Field new in JDK 1.1.6 |
|
748 |
|
749 /** |
|
750 * The string used to separate the mantissa from the exponent. |
|
751 * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4. |
|
752 * <p> |
|
753 * If both <code>exponential</code> and <code>exponentialSeparator</code> |
|
754 * exist, this <code>exponentialSeparator</code> has the precedence. |
|
755 * |
|
756 * @serial |
|
757 * @since 1.6 |
|
758 */ |
|
759 private String exponentialSeparator; // Field new in JDK 1.6 |
|
760 |
|
761 /** |
|
762 * The locale of these currency format symbols. |
|
763 * |
|
764 * @serial |
|
765 * @since 1.4 |
|
766 */ |
|
767 private Locale locale; |
|
768 |
|
769 // currency; only the ISO code is serialized. |
|
770 private transient Currency currency; |
|
771 |
|
772 // Proclaim JDK 1.1 FCS compatibility |
|
773 static final long serialVersionUID = 5772796243397350300L; |
|
774 |
|
775 // The internal serial version which says which version was written |
|
776 // - 0 (default) for version up to JDK 1.1.5 |
|
777 // - 1 for version from JDK 1.1.6, which includes two new fields: |
|
778 // monetarySeparator and exponential. |
|
779 // - 2 for version from J2SE 1.4, which includes locale field. |
|
780 // - 3 for version from J2SE 1.6, which includes exponentialSeparator field. |
|
781 private static final int currentSerialVersion = 3; |
|
782 |
|
783 /** |
|
784 * Describes the version of <code>DecimalFormatSymbols</code> present on the stream. |
|
785 * Possible values are: |
|
786 * <ul> |
|
787 * <li><b>0</b> (or uninitialized): versions prior to JDK 1.1.6. |
|
788 * |
|
789 * <li><b>1</b>: Versions written by JDK 1.1.6 or later, which include |
|
790 * two new fields: <code>monetarySeparator</code> and <code>exponential</code>. |
|
791 * <li><b>2</b>: Versions written by J2SE 1.4 or later, which include a |
|
792 * new <code>locale</code> field. |
|
793 * <li><b>3</b>: Versions written by J2SE 1.6 or later, which include a |
|
794 * new <code>exponentialSeparator</code> field. |
|
795 * </ul> |
|
796 * When streaming out a <code>DecimalFormatSymbols</code>, the most recent format |
|
797 * (corresponding to the highest allowable <code>serialVersionOnStream</code>) |
|
798 * is always written. |
|
799 * |
|
800 * @serial |
|
801 * @since JDK 1.1.6 |
|
802 */ |
|
803 private int serialVersionOnStream = currentSerialVersion; |
|
804 |
|
805 /** |
|
806 * cache to hold the NumberElements and the Currency |
|
807 * of a Locale. |
|
808 */ |
|
809 private static final Hashtable cachedLocaleData = new Hashtable(3); |
|
810 |
|
811 /** |
|
812 * Obtains a DecimalFormatSymbols instance from a DecimalFormatSymbolsProvider |
|
813 * implementation. |
|
814 */ |
|
815 private static class DecimalFormatSymbolsGetter |
|
816 implements LocaleServiceProviderPool.LocalizedObjectGetter<DecimalFormatSymbolsProvider, |
|
817 DecimalFormatSymbols> { |
|
818 private static final DecimalFormatSymbolsGetter INSTANCE = |
|
819 new DecimalFormatSymbolsGetter(); |
|
820 |
|
821 public DecimalFormatSymbols getObject( |
|
822 DecimalFormatSymbolsProvider decimalFormatSymbolsProvider, |
|
823 Locale locale, |
|
824 String key, |
|
825 Object... params) { |
|
826 assert params.length == 0; |
|
827 return decimalFormatSymbolsProvider.getInstance(locale); |
|
828 } |
|
829 } |
|
830 } |