1 /* |
1 /* |
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
35 import java.text.spi.DateFormatSymbolsProvider; |
35 import java.text.spi.DateFormatSymbolsProvider; |
36 import java.text.spi.DecimalFormatSymbolsProvider; |
36 import java.text.spi.DecimalFormatSymbolsProvider; |
37 import java.text.spi.NumberFormatProvider; |
37 import java.text.spi.NumberFormatProvider; |
38 import java.util.Calendar; |
38 import java.util.Calendar; |
39 import java.util.Collections; |
39 import java.util.Collections; |
|
40 import java.util.Currency; |
40 import java.util.HashSet; |
41 import java.util.HashSet; |
41 import java.util.Locale; |
42 import java.util.Locale; |
42 import java.util.Map; |
43 import java.util.Map; |
43 import java.util.ResourceBundle.Control; |
44 import java.util.ResourceBundle.Control; |
44 import java.util.Set; |
45 import java.util.Set; |
46 import java.util.concurrent.ConcurrentHashMap; |
47 import java.util.concurrent.ConcurrentHashMap; |
47 import java.util.concurrent.ConcurrentMap; |
48 import java.util.concurrent.ConcurrentMap; |
48 import java.util.concurrent.atomic.AtomicReferenceArray; |
49 import java.util.concurrent.atomic.AtomicReferenceArray; |
49 import java.util.spi.CalendarDataProvider; |
50 import java.util.spi.CalendarDataProvider; |
50 import java.util.spi.CalendarNameProvider; |
51 import java.util.spi.CalendarNameProvider; |
|
52 import java.util.spi.CurrencyNameProvider; |
|
53 import java.util.spi.LocaleNameProvider; |
51 import sun.util.spi.CalendarProvider; |
54 import sun.util.spi.CalendarProvider; |
52 |
55 |
53 /** |
56 /** |
54 * LocaleProviderdapter implementation for the Windows locale data. |
57 * LocaleProviderdapter implementation for the Windows locale data. |
55 * |
58 * |
69 private static final int NF_MAX = NF_INTEGER; |
72 private static final int NF_MAX = NF_INTEGER; |
70 |
73 |
71 // CalendarData value types |
74 // CalendarData value types |
72 private static final int CD_FIRSTDAYOFWEEK = 0; |
75 private static final int CD_FIRSTDAYOFWEEK = 0; |
73 private static final int CD_MINIMALDAYSINFIRSTWEEK = 1; |
76 private static final int CD_MINIMALDAYSINFIRSTWEEK = 1; |
|
77 |
|
78 // Currency/Locale display name types |
|
79 private static final int DN_CURRENCY_NAME = 0; |
|
80 private static final int DN_CURRENCY_SYMBOL = 1; |
|
81 private static final int DN_LOCALE_LANGUAGE = 2; |
|
82 private static final int DN_LOCALE_SCRIPT = 3; |
|
83 private static final int DN_LOCALE_REGION = 4; |
|
84 private static final int DN_LOCALE_VARIANT = 5; |
74 |
85 |
75 // Native Calendar ID to LDML calendar type map |
86 // Native Calendar ID to LDML calendar type map |
76 private static final String[] calIDToLDML = { |
87 private static final String[] calIDToLDML = { |
77 "", |
88 "", |
78 "gregory", |
89 "gregory", |
94 private static ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> dateFormatSymbolsCache = new ConcurrentHashMap<>(); |
105 private static ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> dateFormatSymbolsCache = new ConcurrentHashMap<>(); |
95 private static ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> numberFormatCache = new ConcurrentHashMap<>(); |
106 private static ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> numberFormatCache = new ConcurrentHashMap<>(); |
96 private static ConcurrentMap<Locale, SoftReference<DecimalFormatSymbols>> decimalFormatSymbolsCache = new ConcurrentHashMap<>(); |
107 private static ConcurrentMap<Locale, SoftReference<DecimalFormatSymbols>> decimalFormatSymbolsCache = new ConcurrentHashMap<>(); |
97 |
108 |
98 private static final Set<Locale> supportedLocaleSet; |
109 private static final Set<Locale> supportedLocaleSet; |
|
110 private static final String nativeDisplayLanguage; |
99 static { |
111 static { |
100 Set<Locale> tmpSet = new HashSet<>(); |
112 Set<Locale> tmpSet = new HashSet<>(); |
101 if (initialize()) { |
113 if (initialize()) { |
102 // Assuming the default locales do not include any extensions, so |
114 // Assuming the default locales do not include any extensions, so |
103 // no stripping is needed here. |
115 // no stripping is needed here. |
104 Locale l = Locale.forLanguageTag(getDefaultLocale(CAT_FORMAT).replace('_', '-')); |
116 Control c = Control.getNoFallbackControl(Control.FORMAT_DEFAULT); |
105 tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l)); |
117 String displayLocale = getDefaultLocale(CAT_DISPLAY); |
106 l = Locale.forLanguageTag(getDefaultLocale(CAT_DISPLAY).replace('_', '-')); |
118 Locale l = Locale.forLanguageTag(displayLocale.replace('_', '-')); |
107 tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l)); |
119 tmpSet.addAll(c.getCandidateLocales("", l)); |
|
120 nativeDisplayLanguage = l.getLanguage(); |
|
121 |
|
122 String formatLocale = getDefaultLocale(CAT_FORMAT); |
|
123 if (!formatLocale.equals(displayLocale)) { |
|
124 l = Locale.forLanguageTag(formatLocale.replace('_', '-')); |
|
125 tmpSet.addAll(c.getCandidateLocales("", l)); |
|
126 } |
|
127 } else { |
|
128 nativeDisplayLanguage = ""; |
108 } |
129 } |
109 supportedLocaleSet = Collections.unmodifiableSet(tmpSet); |
130 supportedLocaleSet = Collections.unmodifiableSet(tmpSet); |
110 } |
131 } |
111 private final static Locale[] supportedLocale = supportedLocaleSet.toArray(new Locale[0]); |
132 private final static Locale[] supportedLocale = supportedLocaleSet.toArray(new Locale[0]); |
112 |
133 |
390 .build(); |
411 .build(); |
391 } |
412 } |
392 }; |
413 }; |
393 } |
414 } |
394 |
415 |
|
416 public static CurrencyNameProvider getCurrencyNameProvider() { |
|
417 return new CurrencyNameProvider() { |
|
418 @Override |
|
419 public Locale[] getAvailableLocales() { |
|
420 return supportedLocale; |
|
421 } |
|
422 |
|
423 @Override |
|
424 public boolean isSupportedLocale(Locale locale) { |
|
425 // Ignore the extensions for now |
|
426 return supportedLocaleSet.contains(locale.stripExtensions()) && |
|
427 locale.getLanguage().equals(nativeDisplayLanguage); |
|
428 } |
|
429 |
|
430 @Override |
|
431 public String getSymbol(String currencyCode, Locale locale) { |
|
432 // Retrieves the currency symbol by calling |
|
433 // GetLocaleInfoEx(LOCALE_SCURRENCY). |
|
434 // It only works with the "locale"'s currency in its native |
|
435 // language. |
|
436 try { |
|
437 if (Currency.getInstance(locale).getCurrencyCode() |
|
438 .equals(currencyCode)) { |
|
439 return getDisplayString(locale.toLanguageTag(), |
|
440 DN_CURRENCY_SYMBOL, currencyCode); |
|
441 } |
|
442 } catch (IllegalArgumentException iae) {} |
|
443 return null; |
|
444 } |
|
445 |
|
446 @Override |
|
447 public String getDisplayName(String currencyCode, Locale locale) { |
|
448 // Retrieves the display name by calling |
|
449 // GetLocaleInfoEx(LOCALE_SNATIVECURRNAME). |
|
450 // It only works with the "locale"'s currency in its native |
|
451 // language. |
|
452 try { |
|
453 if (Currency.getInstance(locale).getCurrencyCode() |
|
454 .equals(currencyCode)) { |
|
455 return getDisplayString(locale.toLanguageTag(), |
|
456 DN_CURRENCY_NAME, currencyCode); |
|
457 } |
|
458 } catch (IllegalArgumentException iae) {} |
|
459 return null; |
|
460 } |
|
461 }; |
|
462 } |
|
463 |
|
464 public static LocaleNameProvider getLocaleNameProvider() { |
|
465 return new LocaleNameProvider() { |
|
466 @Override |
|
467 public Locale[] getAvailableLocales() { |
|
468 return supportedLocale; |
|
469 } |
|
470 |
|
471 @Override |
|
472 public boolean isSupportedLocale(Locale locale) { |
|
473 return supportedLocaleSet.contains(locale.stripExtensions()) && |
|
474 locale.getLanguage().equals(nativeDisplayLanguage); |
|
475 } |
|
476 |
|
477 @Override |
|
478 public String getDisplayLanguage(String languageCode, Locale locale) { |
|
479 // Retrieves the display language name by calling |
|
480 // GetLocaleInfoEx(LOCALE_SLOCALIZEDLANGUAGENAME). |
|
481 return getDisplayString(locale.toLanguageTag(), |
|
482 DN_LOCALE_LANGUAGE, languageCode); |
|
483 } |
|
484 |
|
485 @Override |
|
486 public String getDisplayCountry(String countryCode, Locale locale) { |
|
487 // Retrieves the display country name by calling |
|
488 // GetLocaleInfoEx(LOCALE_SLOCALIZEDCOUNTRYNAME). |
|
489 return getDisplayString(locale.toLanguageTag(), |
|
490 DN_LOCALE_REGION, nativeDisplayLanguage+"-"+countryCode); |
|
491 } |
|
492 |
|
493 @Override |
|
494 public String getDisplayScript(String scriptCode, Locale locale) { |
|
495 return null; |
|
496 } |
|
497 |
|
498 @Override |
|
499 public String getDisplayVariant(String variantCode, Locale locale) { |
|
500 return null; |
|
501 } |
|
502 }; |
|
503 } |
|
504 |
|
505 |
395 private static String convertDateTimePattern(String winPattern) { |
506 private static String convertDateTimePattern(String winPattern) { |
396 String ret = winPattern.replaceAll("dddd", "EEEE"); |
507 String ret = winPattern.replaceAll("dddd", "EEEE"); |
397 ret = ret.replaceAll("ddd", "EEE"); |
508 ret = ret.replaceAll("ddd", "EEE"); |
398 ret = ret.replaceAll("tt", "aa"); |
509 ret = ret.replaceAll("tt", "aa"); |
399 ret = ret.replaceAll("g", "GG"); |
510 ret = ret.replaceAll("g", "GG"); |
411 } |
522 } |
412 return supportedLocale; |
523 return supportedLocale; |
413 } |
524 } |
414 |
525 |
415 private static boolean isSupportedCalendarLocale(Locale locale) { |
526 private static boolean isSupportedCalendarLocale(Locale locale) { |
416 Locale base = locale.stripExtensions(); |
527 Locale base = locale; |
|
528 |
|
529 if (base.hasExtensions() || base.getVariant() != "") { |
|
530 // strip off extensions and variant. |
|
531 base = new Locale.Builder() |
|
532 .setLocale(locale) |
|
533 .clearExtensions() |
|
534 .build(); |
|
535 } |
|
536 |
417 if (!supportedLocaleSet.contains(base)) { |
537 if (!supportedLocaleSet.contains(base)) { |
418 return false; |
538 return false; |
419 } |
539 } |
420 |
540 |
421 int calid = getCalendarID(locale.toLanguageTag()); |
541 int calid = getCalendarID(base.toLanguageTag()); |
422 if (calid <= 0 || calid >= calIDToLDML.length) { |
542 if (calid <= 0 || calid >= calIDToLDML.length) { |
423 return false; |
543 return false; |
424 } |
544 } |
425 |
545 |
426 String requestedCalType = locale.getUnicodeLocaleType("ca"); |
546 String requestedCalType = locale.getUnicodeLocaleType("ca"); |
544 private static native char getPerMill(String langTag, char perMill); |
664 private static native char getPerMill(String langTag, char perMill); |
545 private static native char getZeroDigit(String langTag, char zeroDigit); |
665 private static native char getZeroDigit(String langTag, char zeroDigit); |
546 |
666 |
547 // For CalendarDataProvider |
667 // For CalendarDataProvider |
548 private static native int getCalendarDataValue(String langTag, int type); |
668 private static native int getCalendarDataValue(String langTag, int type); |
|
669 |
|
670 // For Locale/CurrencyNameProvider |
|
671 private static native String getDisplayString(String langTag, int key, String value); |
549 } |
672 } |