src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java

Print this page
rev 6958 : imported patch 8010666

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -35,10 +35,11 @@
 import java.text.spi.DateFormatSymbolsProvider;
 import java.text.spi.DecimalFormatSymbolsProvider;
 import java.text.spi.NumberFormatProvider;
 import java.util.Calendar;
 import java.util.Collections;
+import java.util.Currency;
 import java.util.HashSet;
 import java.util.Locale;
 import java.util.Map;
 import java.util.ResourceBundle.Control;
 import java.util.Set;

@@ -46,10 +47,12 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicReferenceArray;
 import java.util.spi.CalendarDataProvider;
 import java.util.spi.CalendarNameProvider;
+import java.util.spi.CurrencyNameProvider;
+import java.util.spi.LocaleNameProvider;
 import sun.util.spi.CalendarProvider;
 
 /**
  * LocaleProviderdapter implementation for the Windows locale data.
  *

@@ -70,10 +73,18 @@
 
     // CalendarData value types
     private static final int CD_FIRSTDAYOFWEEK = 0;
     private static final int CD_MINIMALDAYSINFIRSTWEEK = 1;
 
+    // Currency/Locale display name types
+    private static final int DN_CURRENCY_NAME   = 0;
+    private static final int DN_CURRENCY_SYMBOL = 1;
+    private static final int DN_LOCALE_LANGUAGE = 2;
+    private static final int DN_LOCALE_SCRIPT   = 3;
+    private static final int DN_LOCALE_REGION   = 4;
+    private static final int DN_LOCALE_VARIANT  = 5;
+
     // Native Calendar ID to LDML calendar type map
     private static final String[] calIDToLDML = {
         "",
         "gregory",
         "gregory_en-US",

@@ -94,20 +105,30 @@
     private static ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> dateFormatSymbolsCache = new ConcurrentHashMap<>();
     private static ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> numberFormatCache = new ConcurrentHashMap<>();
     private static ConcurrentMap<Locale, SoftReference<DecimalFormatSymbols>> decimalFormatSymbolsCache = new ConcurrentHashMap<>();
 
     private static final Set<Locale> supportedLocaleSet;
+    private static final String nativeDisplayLanguage;
     static {
         Set<Locale> tmpSet = new HashSet<>();
         if (initialize()) {
             // Assuming the default locales do not include any extensions, so
             // no stripping is needed here.
-            Locale l = Locale.forLanguageTag(getDefaultLocale(CAT_FORMAT).replace('_', '-'));
-            tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));
-            l = Locale.forLanguageTag(getDefaultLocale(CAT_DISPLAY).replace('_', '-'));
-            tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));
+            Control c = Control.getNoFallbackControl(Control.FORMAT_DEFAULT);
+            String displayLocale = getDefaultLocale(CAT_DISPLAY);
+            Locale l = Locale.forLanguageTag(displayLocale.replace('_', '-'));
+            tmpSet.addAll(c.getCandidateLocales("", l));
+            nativeDisplayLanguage = l.getLanguage();
+
+            String formatLocale = getDefaultLocale(CAT_FORMAT);
+            if (!formatLocale.equals(displayLocale)) {
+                l = Locale.forLanguageTag(formatLocale.replace('_', '-'));
+                tmpSet.addAll(c.getCandidateLocales("", l));
         }
+        } else {
+            nativeDisplayLanguage = "";
+        }
         supportedLocaleSet = Collections.unmodifiableSet(tmpSet);
     }
     private final static Locale[] supportedLocale = supportedLocaleSet.toArray(new Locale[0]);
 
     public static DateFormatProvider getDateFormatProvider() {

@@ -390,10 +411,100 @@
                              .build();
             }
         };
     }
 
+    public static CurrencyNameProvider getCurrencyNameProvider() {
+        return new CurrencyNameProvider() {
+            @Override
+            public Locale[] getAvailableLocales() {
+                return supportedLocale;
+            }
+
+            @Override
+            public boolean isSupportedLocale(Locale locale) {
+                // Ignore the extensions for now
+                return supportedLocaleSet.contains(locale.stripExtensions()) &&
+                       locale.getLanguage().equals(nativeDisplayLanguage);
+            }
+
+            @Override
+            public String getSymbol(String currencyCode, Locale locale) {
+                // Retrieves the currency symbol by calling
+                // GetLocaleInfoEx(LOCALE_SCURRENCY).
+                // It only works with the "locale"'s currency in its native
+                // language.
+                try {
+                    if (Currency.getInstance(locale).getCurrencyCode()
+                        .equals(currencyCode)) {
+                        return getDisplayString(locale.toLanguageTag(),
+                                DN_CURRENCY_SYMBOL, currencyCode);
+                    }
+                } catch (IllegalArgumentException iae) {}
+                return null;
+            }
+
+            @Override
+            public String getDisplayName(String currencyCode, Locale locale) {
+                // Retrieves the display name by calling
+                // GetLocaleInfoEx(LOCALE_SNATIVECURRNAME).
+                // It only works with the "locale"'s currency in its native
+                // language.
+                try {
+                    if (Currency.getInstance(locale).getCurrencyCode()
+                        .equals(currencyCode)) {
+                        return getDisplayString(locale.toLanguageTag(),
+                                DN_CURRENCY_NAME, currencyCode);
+                    }
+                } catch (IllegalArgumentException iae) {}
+                return null;
+            }
+        };
+    }
+
+    public static LocaleNameProvider getLocaleNameProvider() {
+        return new LocaleNameProvider() {
+            @Override
+            public Locale[] getAvailableLocales() {
+                return supportedLocale;
+            }
+
+            @Override
+            public boolean isSupportedLocale(Locale locale) {
+                return supportedLocaleSet.contains(locale.stripExtensions()) &&
+                       locale.getLanguage().equals(nativeDisplayLanguage);
+            }
+
+            @Override
+            public String getDisplayLanguage(String languageCode, Locale locale) {
+                // Retrieves the display language name by calling
+                // GetLocaleInfoEx(LOCALE_SLOCALIZEDLANGUAGENAME).
+                return getDisplayString(locale.toLanguageTag(),
+                            DN_LOCALE_LANGUAGE, languageCode);
+            }
+
+            @Override
+            public String getDisplayCountry(String countryCode, Locale locale) {
+                // Retrieves the display country name by calling
+                // GetLocaleInfoEx(LOCALE_SLOCALIZEDCOUNTRYNAME).
+                return getDisplayString(locale.toLanguageTag(),
+                            DN_LOCALE_REGION, nativeDisplayLanguage+"-"+countryCode);
+            }
+
+            @Override
+            public String getDisplayScript(String scriptCode, Locale locale) {
+                return null;
+            }
+
+            @Override
+            public String getDisplayVariant(String variantCode, Locale locale) {
+                return null;
+            }
+        };
+    }
+
+
     private static String convertDateTimePattern(String winPattern) {
         String ret = winPattern.replaceAll("dddd", "EEEE");
         ret = ret.replaceAll("ddd", "EEE");
         ret = ret.replaceAll("tt", "aa");
         ret = ret.replaceAll("g", "GG");

@@ -411,16 +522,25 @@
         }
         return supportedLocale;
     }
 
     private static boolean isSupportedCalendarLocale(Locale locale) {
-        Locale base = locale.stripExtensions();
+        Locale base = locale;
+
+        if (base.hasExtensions() || base.getVariant() != "") {
+            // strip off extensions and variant.
+            base = new Locale.Builder()
+                            .setLocale(locale)
+                            .clearExtensions()
+                            .build();
+        }
+
         if (!supportedLocaleSet.contains(base)) {
             return false;
         }
 
-        int calid = getCalendarID(locale.toLanguageTag());
+        int calid = getCalendarID(base.toLanguageTag());
         if (calid <= 0 || calid >= calIDToLDML.length) {
             return false;
         }
 
         String requestedCalType = locale.getUnicodeLocaleType("ca");

@@ -544,6 +664,9 @@
     private static native char getPerMill(String langTag, char perMill);
     private static native char getZeroDigit(String langTag, char zeroDigit);
 
     // For CalendarDataProvider
     private static native int getCalendarDataValue(String langTag, int type);
+
+    // For Locale/CurrencyNameProvider
+    private static native String getDisplayString(String langTag, int key, String value);
 }