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